diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 5d9341bbf..6b541cd89 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -18,6 +18,7 @@ body: - 1.16 - 1.18 - 1.19 + - 1.20.x validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/compatibility_issue.yml b/.github/ISSUE_TEMPLATE/compatibility_issue.yml index 1fa48e826..6a29e9206 100644 --- a/.github/ISSUE_TEMPLATE/compatibility_issue.yml +++ b/.github/ISSUE_TEMPLATE/compatibility_issue.yml @@ -29,6 +29,7 @@ body: - 1.16 - 1.18 - 1.19 + - 1.20.x validations: required: true - type: dropdown diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e62babf96..9f9127175 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,11 +13,26 @@ jobs: name: "Validate Gradle wrapper" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true # Clone with vs-core submodule - uses: gradle/wrapper-validation-action@v1 + json-yaml-validate: + name: "Validate Json/Yaml files" + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write # enable write permissions for pull request comments + steps: + - uses: actions/checkout@v4 + + - name: json-yaml-validate + id: json-yaml-validate + uses: GrantBirki/json-yaml-validate@v2.3.1 + with: + comment: "true" # enable comment mode + test-server: name: Test Server strategy: @@ -27,7 +42,7 @@ jobs: timeout-minutes: 20 # Fail after 20 minutes steps: - name: Shallow Clone (--recurse-submodules) - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: recursive diff --git a/.gitmodules b/.gitmodules index 6dad4381c..e69de29bb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "vs-core"] - path = vs-core - url = https://github.com/ValkyrienSkies/vs-core diff --git a/build.gradle b/build.gradle index 251e8a00c..22d0e5286 100644 --- a/build.gradle +++ b/build.gradle @@ -8,18 +8,12 @@ buildscript { plugins { // Needed for Forge+Fabric id "architectury-plugin" version "3.4.146" - id "dev.architectury.loom" version "1.1.346" apply false - id 'io.github.juuxel.loom-quiltflower' version '1.8.0' apply false + id "dev.architectury.loom" version "1.3.355" apply false + id 'io.github.juuxel.loom-vineflower' version '1.11.0' apply false // Kotlin - id "org.jetbrains.kotlin.jvm" version "1.7.10" apply false - // Kotlin linter - id "org.jlleitschuh.gradle.ktlint" version "10.3.0" - + id "org.jetbrains.kotlin.jvm" version "1.9.10" apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false id "com.modrinth.minotaur" version "2.4.3" apply false - - // Java linter - id "checkstyle" } // Determine the version @@ -42,20 +36,73 @@ dependencyLocking { lockAllConfigurations() } -// Determine the version of vs-core -String vsCoreGitRevision = "git rev-parse HEAD".execute(null, gradle.includedBuild("vs-core").projectDir).text.trim() -ext.vs_core_version = "1.1.0+" + vsCoreGitRevision.substring(0, 10) +tasks.register("updateVsCore") { + File versionFile = null + File gradleProperties = file("gradle.properties") + + try { + def vsCoreBuild = gradle.includedBuild("vs-core") + versionFile = new File(vsCoreBuild.projectDir, "api-game/build/version.txt") + + inputs.file(versionFile) + outputs.file(gradleProperties) + dependsOn(vsCoreBuild.task(":api-game:writeVersion")) + + [':impl', ':api', ':api-game', ':util'].each { + dependsOn(vsCoreBuild.task("${it}:publishToMavenLocal")) + } + } catch (UnknownDomainObjectException ignore) {} + + onlyIf { + versionFile != null + } + + doLast { + def vsCoreVersion = versionFile.text + def newGradleProperties = gradleProperties.text.replaceFirst("(?m)^vs_core_version=.*", "vs_core_version=" + vsCoreVersion) + gradleProperties.write(newGradleProperties) + } +} subprojects { apply plugin: "dev.architectury.loom" // Apply checkstyle and ktlint to check the code style of every sub project - apply plugin: "org.jlleitschuh.gradle.ktlint" - apply plugin: "checkstyle" apply plugin: "org.jetbrains.kotlin.jvm" - apply plugin: "io.github.juuxel.loom-quiltflower" + apply plugin: "io.github.juuxel.loom-vineflower" + + configurations.each { it.resolutionStrategy.useGlobalDependencySubstitutionRules.set(false) } repositories { + try { + def vsCoreBuild = gradle.includedBuild("vs-core") + mavenLocal { + content { + includeGroup("org.valkyrienskies.core") + } + } + + [':impl', ':api', ':api-game'].each { + compileJava.dependsOn(vsCoreBuild.task("${it}:publishToMavenLocal")) + } + } catch (UnknownDomainObjectException ignore) {} + mavenCentral() + maven { + url "https://cursemaven.com" + content { + includeModule "curse.maven", "kotlinforforge-351264" + } + } + maven { + name = "Valkyrien Skies Internal" + url = project.vs_maven_url ?: 'https://maven.valkyrienskies.org' + if (project.vs_maven_username && project.vs_maven_password) { + credentials { + username = project.vs_maven_username + password = project.vs_maven_password + } + } + } if (!project.block_external_repositories) { mavenLocal() maven { @@ -72,28 +119,14 @@ subprojects { name = 'tterrag maven' url = 'https://maven.tterrag.com/' } - maven { url = "https://api.modrinth.com/maven" } // LazyDFU, Suggestion Tweaker + maven { url = "https://api.modrinth.com/maven" } // LazyDFU, Suggestion Tweaker, Create Big Cannons maven { url = "https://maven.shedaniel.me/" } // Cloth Config, REI + maven { url "https://maven.architectury.dev/" } maven { url = "https://mvn.devos.one/snapshots/" } // Fabric Create, Porting Lib, Forge Tags, Milk Lib maven { url = "https://raw.githubusercontent.com/Fuzss/modresources/main/maven/" } // Forge Config API Port maven { url = "https://maven.tterrag.com/" } // Registrate, Forge Create and Flywheel maven { url = "https://maven.cafeteria.dev/releases" } // Fake Player API maven { url = "https://maven.jamieswhiteshirt.com/libs-release" } // Reach Entity Attributes - maven { url = "https://mvn.devos.one/#/snapshots/" } // Create Fabric - maven { - url = "https://jitpack.io" - content { includeGroup("com.github.llamalad7.mixinextras") } - } // MixinExtras smh my head - } - maven { - name = "Valkyrien Skies Internal" - url = project.vs_maven_url ?: 'https://maven.valkyrienskies.org' - if (project.vs_maven_username && project.vs_maven_password) { - credentials { - username = project.vs_maven_username - password = project.vs_maven_password - } - } } } @@ -114,37 +147,6 @@ subprojects { compileOnly("com.google.code.findbugs:jsr305:3.0.2") } - - // configure checkstyle - checkstyle { - // configure to use checkstyle v8.41 - toolVersion "8.45.1" - // Gradle should fail builds on checkstyle errors (not warnings) - ignoreFailures = true - // Checkstyle config file is in .checkstyle/checkstyle.xml - configFile = file("${rootDir}/.checkstyle/checkstyle.xml") - } - - // configure checkstyle, but different - // https://docs.gradle.org/current/userguide/checkstyle_plugin.html - tasks.withType(Checkstyle) { - reports { - // Do not output html reports - html.enabled = false - // Output xml reports - xml.enabled = true - } - } - - // configure ktlint - ktlint { - reporters { - // configure to output in checkstyle XML format - reporter "checkstyle" - } - ignoreFailures = true - disabledRules = ["parameter-list-wrapping"] - } } allprojects { diff --git a/changelogs/2.1.1-beta.1.md b/changelogs/2.1.1-beta.1.md new file mode 100644 index 000000000..ff52e1b6d --- /dev/null +++ b/changelogs/2.1.1-beta.1.md @@ -0,0 +1,13 @@ +# New Features +* LOD that adds collision shapes for stairs/slabs/ect, and adds friction/elasticity/density properties to blocks +* Multithreaded Krunch physics engine +* Multithreaded terrain loading (so physics doesn't lag from terrain loading) +* Allow ships to travel through Nether and End portals +* Allow ships to be teleported between dimensions +* Added physics entity support (currently only used to make balls with the Physics Entity Creator Item, but more coming soon 🙂) + +# Bugfixes +* Fixed ships randomly getting stuck in the air +* Fixed scaled ships not behaving correctly in water +* Fixed the @v command argument to behave correctly like the @e argument +* Fixed Ship Creator Item not scaling ships correctly diff --git a/changelogs/2.1.1-beta.2.md b/changelogs/2.1.1-beta.2.md new file mode 100644 index 000000000..8073deae6 --- /dev/null +++ b/changelogs/2.1.1-beta.2.md @@ -0,0 +1,5 @@ +# New Features +Nothing + +# Bugfixes +* Removed old CBC mixin that doesn't work on new versions diff --git a/common/build.gradle b/common/build.gradle index ba3e3f80c..301e677df 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -1,32 +1,37 @@ + dependencies { - annotationProcessor(implementation("com.github.llamalad7.mixinextras:mixinextras-common:0.2.0-beta.8")) + implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:0.2.0")) compileOnly 'com.google.code.findbugs:jsr305:3.0.2' // We depend on fabric loader here to use the fabric @Environment annotations // Do NOT use other classes from fabric loader modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - modApi("me.shedaniel.cloth:cloth-config:11.0.99") + modApi("me.shedaniel.cloth:cloth-config:${cloth_config_version}") - modCompileOnly("maven.modrinth:sodium:mc1.20-0.4.10") + modCompileOnly("maven.modrinth:sodium:${sodium_version}") // vs-core implementation("org.valkyrienskies.core:impl:${rootProject.vs_core_version}") { exclude module: "netty-buffer" exclude module: "fastutil" - exclude group: "com.google.guava" } + implementation("org.valkyrienskies.core:util:${rootProject.vs_core_version}") + // FTB Stuffs - // modCompileOnly("curse.maven:ftb-util-404465:4210935") - // modCompileOnly("curse.maven:ftb-teams-404468:4229138") - // modCompileOnly("curse.maven:ftb-chunks-314906:4229120") + modCompileOnly("curse.maven:ftb-util-404465:4210935") + modCompileOnly("curse.maven:ftb-teams-404468:4229138") + modCompileOnly("curse.maven:ftb-chunks-314906:4229120") - // Common create compat, - // We just use a version from a platform and hope the classes exist on both versions and mixins apply correctly + //Common create compat, + //We just use a version from a platform and hope the classes exist on both versions and mixins apply correctly modCompileOnly("com.simibubi.create:create-fabric-${minecraft_version}:${create_fabric_version}") { exclude group: 'com.github.AlphaMode', module: 'fakeconfigtoml' } - modCompileOnly("com.jozufozu.flywheel:flywheel-fabric-${minecraft_version}:0.6.9-4") + modCompileOnly("net.fabricmc.fabric-api:fabric-api:${fabric_api_version}") + modCompileOnly("com.jozufozu.flywheel:flywheel-fabric-${minecraft_version}:${flywheel_version_fabric}") + + modCompileOnly("maven.modrinth:create-big-cannons:${createbigcannons_version}") } architectury { diff --git a/common/gradle.properties b/common/gradle.properties new file mode 100644 index 000000000..5385872a4 --- /dev/null +++ b/common/gradle.properties @@ -0,0 +1,9 @@ +#https://mvn.devos.one/#/snapshots/io/github/fabricators_of_create/Porting-Lib/Porting-Lib +port_lib_version=2.1.1127+1.20 +port_lib_modules = accessors,base,entity,extensions,fake_players,networking,obj_loader,tags,transfer,models,tool_actions,client_events,brewing + +# https://modrinth.com/mod/cloth-config/version/8.3.103+fabric +cloth_config_version = 11.1.106 + +# https://modrinth.com/mod/sodium/versions +sodium_version = mc1.20-0.4.10 diff --git a/common/src/main/java/org/valkyrienskies/mod/compat/FlywheelEvents.java b/common/src/main/java/org/valkyrienskies/mod/compat/FlywheelEvents.java new file mode 100644 index 000000000..8e5076018 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/compat/FlywheelEvents.java @@ -0,0 +1,35 @@ +package org.valkyrienskies.mod.compat; + +import com.jozufozu.flywheel.backend.instancing.InstanceWorld; +import java.util.Collections; +import java.util.Set; +import java.util.WeakHashMap; +import org.valkyrienskies.core.impl.hooks.VSEvents.ShipUnloadEventClient; +import org.valkyrienskies.mod.mixinducks.MixinBlockEntityInstanceManagerDuck; + +public class FlywheelEvents { + static { + registerEvents(); + } + + private static final Set weakLoadedInstanceWorlds = + Collections.newSetFromMap( + new WeakHashMap<>() + ); + + private static synchronized void registerEvents() { + ShipUnloadEventClient.Companion.on(event -> { + for (final InstanceWorld instanceWorld : weakLoadedInstanceWorlds) { + ((MixinBlockEntityInstanceManagerDuck) instanceWorld.getBlockEntityInstanceManager()).vs$removeShipManager(event.getShip()); + } + }); + } + + public static void onInstanceWorldLoad(final InstanceWorld instanceWorld) { + weakLoadedInstanceWorlds.add(instanceWorld); + } + + public static void onInstanceWorldUnload(final InstanceWorld instanceWorld) { + weakLoadedInstanceWorlds.remove(instanceWorld); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/entity/EntityAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/entity/EntityAccessor.java index 69f0ea951..68b9739ad 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/entity/EntityAccessor.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/entity/EntityAccessor.java @@ -21,5 +21,13 @@ public interface EntityAccessor { @Accessor("feetBlockState") void setFeetBlockState(BlockState feetBlockState); - + + @Accessor("portalCooldown") + void setPortalCooldown(int portalCooldown); + + @Accessor("portalCooldown") + int getPortalCooldown(); + + @Accessor("portalEntrancePos") + BlockPos getPortalEntrancePos(); } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/resource/ResourceKeyAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/resource/ResourceKeyAccessor.java index 50c1a4719..0dc3f0db5 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/resource/ResourceKeyAccessor.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/resource/ResourceKeyAccessor.java @@ -1,5 +1,6 @@ package org.valkyrienskies.mod.mixin.accessors.resource; +import java.util.Map; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import org.spongepowered.asm.mixin.Mixin; @@ -8,6 +9,14 @@ @Mixin(ResourceKey.class) public interface ResourceKeyAccessor { +/* + @Accessor("VALUES") + static Map> getValues() { + throw new AssertionError(); + } + + */ + @Accessor ResourceLocation getRegistryName(); diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/level/ChunkMapAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/level/ChunkMapAccessor.java new file mode 100644 index 000000000..cd00116f3 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/level/ChunkMapAccessor.java @@ -0,0 +1,49 @@ +package org.valkyrienskies.mod.mixin.accessors.server.level; + +import it.unimi.dsi.fastutil.longs.LongSet; +import java.util.function.BooleanSupplier; +import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; +import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkMap.DistanceManager; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.ai.village.poi.PoiManager; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkStatus; +import org.apache.commons.lang3.mutable.MutableObject; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(ChunkMap.class) +public interface ChunkMapAccessor { + @Invoker("updateChunkTracking") + void callUpdateChunkTracking(ServerPlayer player, ChunkPos pos, + MutableObject packets, + boolean withinMaxWatchDistance, boolean withinViewDistance); + + @Invoker("getChunks") + Iterable callGetChunks(); + + @Invoker("getVisibleChunkIfPresent") + ChunkHolder callGetVisibleChunkIfPresent(long l); + + @Invoker("save") + boolean callSave(ChunkAccess chunkAccess); + + @Accessor("toDrop") + LongSet getToDrop(); + + @Invoker("processUnloads") + void callProcessUnloads(BooleanSupplier booleanSupplier); + + @Accessor("poiManager") + PoiManager getPoiManager(); + + @Invoker("markPosition") + byte callMarkPosition(ChunkPos chunkPos, ChunkStatus.ChunkType chunkType); + + @Accessor("distanceManager") + DistanceManager getDistanceManager(); +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/level/DistanceManagerAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/level/DistanceManagerAccessor.java new file mode 100644 index 000000000..87c7229c5 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/level/DistanceManagerAccessor.java @@ -0,0 +1,14 @@ +package org.valkyrienskies.mod.mixin.accessors.server.level; + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.server.level.DistanceManager; +import net.minecraft.server.level.Ticket; +import net.minecraft.util.SortedArraySet; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(DistanceManager.class) +public interface DistanceManagerAccessor { + @Accessor("tickets") + Long2ObjectOpenHashMap>> getTickets(); +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/level/ServerChunkCacheAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/level/ServerChunkCacheAccessor.java new file mode 100644 index 000000000..1dc027ff8 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/level/ServerChunkCacheAccessor.java @@ -0,0 +1,11 @@ +package org.valkyrienskies.mod.mixin.accessors.server.level; + +import net.minecraft.server.level.ServerChunkCache; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(ServerChunkCache.class) +public interface ServerChunkCacheAccessor { + @Invoker("clearCache") + void callClearCache(); +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/world/ChunkMapAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/world/ChunkMapAccessor.java deleted file mode 100644 index c91c849ae..000000000 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/server/world/ChunkMapAccessor.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.valkyrienskies.mod.mixin.accessors.server.world; - -import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.ChunkPos; -import org.apache.commons.lang3.mutable.MutableObject; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(ChunkMap.class) -public interface ChunkMapAccessor { - @Invoker("updateChunkTracking") - void callUpdateChunkTracking(ServerPlayer player, ChunkPos pos, - MutableObject packets, - boolean withinMaxWatchDistance, boolean withinViewDistance); - - @Invoker("getChunks") - Iterable callGetChunks(); - - @Invoker("getVisibleChunkIfPresent") - ChunkHolder callGetVisibleChunkIfPresent(long l); -} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/util/math/Matrix4fAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/util/math/Matrix4fAccessor.java new file mode 100644 index 000000000..95db378c7 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/util/math/Matrix4fAccessor.java @@ -0,0 +1,108 @@ +package org.valkyrienskies.mod.mixin.accessors.util.math; + +import org.joml.Matrix4f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Matrix4f.class) +public interface Matrix4fAccessor { + // region Setters + @Accessor("m00") + void setM00(float a00); + + @Accessor("m01") + void setM01(float a01); + + @Accessor("m02") + void setM02(float a02); + + @Accessor("m03") + void setM03(float a03); + + @Accessor("m10") + void setM10(float a10); + + @Accessor("m11") + void setM11(float a11); + + @Accessor("m12") + void setM12(float a12); + + @Accessor("m13") + void setM13(float a13); + + @Accessor("m20") + void setM20(float a20); + + @Accessor("m21") + void setM21(float a21); + + @Accessor("m22") + void setM22(float a22); + + @Accessor("m23") + void setM23(float a23); + + @Accessor("m30") + void setM30(float a30); + + @Accessor("m31") + void setM31(float a31); + + @Accessor("m32") + void setM32(float a32); + + @Accessor("m33") + void setM33(float a33); + + // endregion + // region Getters + @Accessor("m00") + float getM00(); + + @Accessor("m01") + float getM01(); + + @Accessor("m02") + float getM02(); + + @Accessor("m03") + float getM03(); + + @Accessor("m10") + float getM10(); + + @Accessor("m11") + float getM11(); + + @Accessor("m12") + float getM12(); + + @Accessor("m13") + float getM13(); + + @Accessor("m20") + float getM20(); + + @Accessor("m21") + float getM21(); + + @Accessor("m22") + float getM22(); + + @Accessor("m23") + float getM23(); + + @Accessor("m30") + float getM30(); + + @Accessor("m31") + float getM31(); + + @Accessor("m32") + float getM32(); + + @Accessor("m33") + float getM33(); + // endregion +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/world/level/block/SlabBlockAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/world/level/block/SlabBlockAccessor.java new file mode 100644 index 000000000..e59b5075f --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/world/level/block/SlabBlockAccessor.java @@ -0,0 +1,19 @@ +package org.valkyrienskies.mod.mixin.accessors.world.level.block; + +import net.minecraft.world.level.block.SlabBlock; +import net.minecraft.world.phys.shapes.VoxelShape; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(SlabBlock.class) +public interface SlabBlockAccessor { + @Accessor("BOTTOM_AABB") + static VoxelShape getBottomAABB() { + throw new AssertionError(); + } + + @Accessor("TOP_AABB") + static VoxelShape getTopAABB() { + throw new AssertionError(); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/world/level/block/StairBlockAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/world/level/block/StairBlockAccessor.java new file mode 100644 index 000000000..63cac9bad --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/accessors/world/level/block/StairBlockAccessor.java @@ -0,0 +1,19 @@ +package org.valkyrienskies.mod.mixin.accessors.world.level.block; + +import net.minecraft.world.level.block.StairBlock; +import net.minecraft.world.phys.shapes.VoxelShape; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(StairBlock.class) +public interface StairBlockAccessor { + @Accessor("TOP_SHAPES") + static VoxelShape[] getTopShapes() { + throw new AssertionError(); + } + + @Accessor("BOTTOM_SHAPES") + static VoxelShape[] getBottomShapes() { + throw new AssertionError(); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinCamera.java b/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinCamera.java index 6142e3de8..5b908e493 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinCamera.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinCamera.java @@ -27,6 +27,7 @@ import org.valkyrienskies.core.api.ships.properties.ShipTransform; import org.valkyrienskies.mod.client.IVSCamera; import org.valkyrienskies.mod.common.world.RaycastUtilsKt; +import org.joml.Vector3f; @Mixin(Camera.class) public abstract class MixinCamera implements IVSCamera { diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinGame.java b/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinGame.java new file mode 100644 index 000000000..7fdca259f --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinGame.java @@ -0,0 +1,26 @@ +//package org.valkyrienskies.mod.mixin.client; +// +//import net.minecraft.client.Game; +//import net.minecraft.client.Minecraft; +//import org.spongepowered.asm.mixin.Final; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Shadow; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.Inject; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//import org.valkyrienskies.mod.common.IShipObjectWorldClientCreator; +// +//@Mixin(Game.class) +//public class MixinGame { +// @Shadow +// @Final +// private Minecraft minecraft; +// +// /** +// * @reason Destroy the [ShipObjectClientWorld] when we leave a game session. +// */ +// @Inject(method = "onLeaveGameSession", at = @At("HEAD")) +// private void preOnLeaveGameSession(final CallbackInfo ci) { +// ((IShipObjectWorldClientCreator) minecraft).deleteShipObjectWorldClient(); +// } +//} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinMinecraft.java b/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinMinecraft.java index ffca7228a..424b4f52a 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinMinecraft.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinMinecraft.java @@ -29,7 +29,6 @@ import org.valkyrienskies.mod.common.IShipObjectWorldServerProvider; import org.valkyrienskies.mod.common.ValkyrienSkiesMod; import org.valkyrienskies.mod.common.util.EntityDragger; -import org.valkyrienskies.mod.common.world.DummyShipWorldClient; import org.valkyrienskies.mod.mixinducks.client.MinecraftDuck; @Mixin(Minecraft.class) @@ -38,6 +37,8 @@ public abstract class MixinMinecraft @Unique private static final Logger log = LogManager.getLogger("VS2 MixinMinecraft"); + @Unique + private static long lastLog = System.currentTimeMillis(); @Shadow private boolean pause; @@ -86,9 +87,15 @@ public ClientShipWorldCore getShipObjectWorld() { final ClientShipWorldCore shipObjectWorldCopy = shipObjectWorld; if (shipObjectWorldCopy == null) { - log.warn("Requested getShipObjectWorld() when shipObjectWorld was null!"); - return DummyShipWorldClient.INSTANCE; + if (lastLog + 5000 < System.currentTimeMillis()) { + lastLog = System.currentTimeMillis(); + log.warn("Requested getShipObjectWorld() but failed returning dummy world", + new IllegalStateException("shipObjectWorld is null")); + } + + return ValkyrienSkiesMod.getVsCore().getDummyShipWorldClient(); } + return shipObjectWorldCopy; } @@ -122,6 +129,17 @@ public void setGamePause(final boolean pauseOnly, final CallbackInfo ci) { } } + /* TODO no longer needed + @Inject( + method = "setCurrentServer", + at = @At("HEAD") + ) + public void preSetCurrentServer(final ServerData serverData, final CallbackInfo ci) { + ValkyrienSkiesMod.getVsCore().setClientUsesUDP(false); + } + + */ + @Override public void createShipObjectWorldClient() { if (shipObjectWorld != null) { @@ -136,17 +154,9 @@ public void createShipObjectWorldClient() { public void deleteShipObjectWorldClient() { final ClientShipWorldCore shipObjectWorldCopy = shipObjectWorld; if (shipObjectWorldCopy == null) { - return; // throw new IllegalStateException("shipObjectWorld was null when it should be not null?"); + throw new IllegalStateException("shipObjectWorld was null when it should be not null?"); } shipObjectWorldCopy.destroyWorld(); shipObjectWorld = null; } - - @Inject( - method = "clearLevel", - at = @At("TAIL") - ) - private void postClearLevel(final CallbackInfo ci) { - deleteShipObjectWorldClient(); - } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/client/multiplayer/MixinClientPacketListener.java b/common/src/main/java/org/valkyrienskies/mod/mixin/client/multiplayer/MixinClientPacketListener.java index 6f99f33b8..d17c3aabd 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/client/multiplayer/MixinClientPacketListener.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/client/multiplayer/MixinClientPacketListener.java @@ -53,8 +53,8 @@ private void handleShipMountingEntity(final ClientboundAddEntityPacket packet, f final int i = packet.getId(); entity.syncPacketPositionCodec(d, e, f); entity.moveTo(d, e, f); - entity.setXRot((packet.getXRot() * 360) / 256.0f); - entity.setYRot((packet.getYRot() * 360) / 256.0f); + entity.setXRot((float) (packet.getXRot() * 360) / 256.0f); + entity.setYRot((float) (packet.getYRot() * 360) / 256.0f); entity.setId(i); entity.setUUID(packet.getUUID()); this.level.putNonPlayerEntity(i, entity); diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/client/renderer/MixinLevelRenderer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/client/renderer/MixinLevelRenderer.java index 77773980b..59776e28c 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/client/renderer/MixinLevelRenderer.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/client/renderer/MixinLevelRenderer.java @@ -9,10 +9,12 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.Inject; @@ -27,6 +29,9 @@ public abstract class MixinLevelRenderer { @Shadow private ClientLevel level; + @Unique private PoseStack matrixStack; + @Unique private Vec3 camera; + @Shadow private static void renderShape(final PoseStack matrixStack, final VertexConsumer vertexConsumer, final VoxelShape voxelShape, final double d, final double e, final double f, final float red, final float green, @@ -74,4 +79,50 @@ private void preRenderHitOutline(final PoseStack matrixStack, final VertexConsum 0.0F, 0.0F, 0.0F, 0.4F); } } + + + /** + * This mixin makes block damage render on ships. + */ + /* + @WrapOperation(method = "renderLevel", at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/block/BlockRenderDispatcher;renderBreakingTexture(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/BlockAndTintGetter;Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;)V")) + private void renderBlockDamage(final BlockRenderDispatcher blockRenderManager, final BlockState state, + final BlockPos blockPos, final BlockAndTintGetter blockRenderWorld, final PoseStack matrix, + final VertexConsumer vertexConsumer, final Operation renderBreakingTexture) { + + + final ClientShip ship = VSGameUtilsKt.getShipObjectManagingPos(level, blockPos); + if (ship != null) { + // Remove the vanilla render transform + matrixStack.popPose(); + + // Add the VS render transform + matrixStack.pushPose(); + + final ShipTransform renderTransform = ship.getRenderTransform(); + final Vec3 cameraPos = methodCamera.getPosition(); + + transformRenderWithShip(renderTransform, matrixStack, blockPos, cameraPos.x, cameraPos.y, cameraPos.z); + + final Matrix3f newNormalMatrix = matrixStack.last().normal().copy(); + final Matrix4f newModelMatrix = matrixStack.last().pose().copy(); + + // Then update the matrices in vertexConsumer (I'm guessing vertexConsumer is responsible for mapping + // textures, so we need to update its matrices otherwise the block damage texture looks wrong) + final SheetedDecalTextureGenerator newVertexConsumer = + new SheetedDecalTextureGenerator(((OverlayVertexConsumerAccessor) vertexConsumer).getDelegate(), + newModelMatrix, newNormalMatrix); + + // Finally, invoke the render damage function. + renderBreakingTexture.call(blockRenderManager, state, blockPos, blockRenderWorld, matrix, + newVertexConsumer); + } else { + // Vanilla behavior + renderBreakingTexture.call(blockRenderManager, state, blockPos, blockRenderWorld, matrix, vertexConsumer); + } + } + + */ + } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/client/world/MixinClientChunkCache.java b/common/src/main/java/org/valkyrienskies/mod/mixin/client/world/MixinClientChunkCache.java index 5138bd6df..0f4fb6db1 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/client/world/MixinClientChunkCache.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/client/world/MixinClientChunkCache.java @@ -5,18 +5,16 @@ import java.util.function.Consumer; import net.minecraft.client.multiplayer.ClientChunkCache; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.core.SectionPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData.BlockEntityTagOutput; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.lighting.LevelLightEngine; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -43,11 +41,12 @@ public abstract class MixinClientChunkCache implements ClientChunkCacheDuck { @Final ClientLevel level; - public LongObjectMap vs_getShipChunks() { - return shipChunks; + public LongObjectMap vs$getShipChunks() { + return vs$shipChunks; } - private final LongObjectMap shipChunks = new LongObjectHashMap<>(); + @Unique + private final LongObjectMap vs$shipChunks = new LongObjectHashMap<>(); @Inject(method = "replaceWithPacketData", at = @At("HEAD"), cancellable = true) private void preLoadChunkFromPacket(final int x, final int z, @@ -60,25 +59,19 @@ private void preLoadChunkFromPacket(final int x, final int z, if (VSGameUtilsKt.isChunkInShipyard(level, x, z)) { final long chunkPosLong = ChunkPos.asLong(x, z); - final LevelChunk worldChunk = new LevelChunk(this.level, new ChunkPos(x, z)); - worldChunk.replaceWithPacketData(buf, tag, consumer); - shipChunks.put(chunkPosLong, worldChunk); - - final LevelChunkSection[] chunkSections = worldChunk.getSections(); - final LevelLightEngine lightingProvider = this.getLightEngine(); - lightingProvider.setLightEnabled(new ChunkPos(x, z), true); - - for (int j = 0; j < chunkSections.length; ++j) { - final LevelChunkSection chunkSection = chunkSections[j]; - lightingProvider - .updateSectionStatus(SectionPos.of(x, level.getSectionYFromSectionIndex(j), z), - chunkSection.hasOnlyAir()); + final LevelChunk oldChunk = vs$shipChunks.get(chunkPosLong); + final LevelChunk worldChunk; + if (oldChunk != null) { + worldChunk = oldChunk; + oldChunk.replaceWithPacketData(buf, tag, consumer); + } else { + worldChunk = new LevelChunk(this.level, new ChunkPos(x, z)); + worldChunk.replaceWithPacketData(buf, tag, consumer); + vs$shipChunks.put(chunkPosLong, worldChunk); } this.level.onChunkLoaded(new ChunkPos(x, z)); - SodiumCompat.onChunkAdded(x, z); - cir.setReturnValue(worldChunk); } } @@ -86,7 +79,7 @@ private void preLoadChunkFromPacket(final int x, final int z, @Inject(method = "drop", at = @At("HEAD"), cancellable = true) public void preUnload(final int chunkX, final int chunkZ, final CallbackInfo ci) { - shipChunks.remove(ChunkPos.asLong(chunkX, chunkZ)); + vs$shipChunks.remove(ChunkPos.asLong(chunkX, chunkZ)); if (ValkyrienCommonMixinConfigPlugin.getVSRenderer() != VSRenderer.SODIUM) { ((IVSViewAreaMethods) ((LevelRendererAccessor) ((ClientLevelAccessor) level).getLevelRenderer()).getViewArea()) .unloadChunk(chunkX, chunkZ); @@ -100,12 +93,9 @@ public void preUnload(final int chunkX, final int chunkZ, final CallbackInfo ci) at = @At("HEAD"), cancellable = true) public void preGetChunk(final int chunkX, final int chunkZ, final ChunkStatus chunkStatus, final boolean bl, final CallbackInfoReturnable cir) { - final LevelChunk shipChunk = shipChunks.get(ChunkPos.asLong(chunkX, chunkZ)); + final LevelChunk shipChunk = vs$shipChunks.get(ChunkPos.asLong(chunkX, chunkZ)); if (shipChunk != null) { cir.setReturnValue(shipChunk); } } - - @Shadow - public abstract LevelLightEngine getLightEngine(); } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/client/world/MixinClientLevel.java b/common/src/main/java/org/valkyrienskies/mod/mixin/client/world/MixinClientLevel.java index 533522266..de9148661 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/client/world/MixinClientLevel.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/client/world/MixinClientLevel.java @@ -33,8 +33,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.valkyrienskies.core.api.ships.Ship; import org.valkyrienskies.core.apigame.world.ClientShipWorldCore; -import org.valkyrienskies.core.impl.util.AABBdUtilKt; -import org.valkyrienskies.core.impl.util.VectorConversionsKt; +import org.valkyrienskies.core.util.AABBdUtilKt; +import org.valkyrienskies.core.util.VectorConversionsKt; import org.valkyrienskies.mod.client.audio.SimpleSoundInstanceOnShip; import org.valkyrienskies.mod.common.IShipObjectWorldClientProvider; import org.valkyrienskies.mod.common.VSGameUtilsKt; @@ -186,7 +186,7 @@ private void animateTickVS( @Redirect( at = @At( value = "NEW", - target = "net/minecraft/client/resources/sounds/SimpleSoundInstance" + target = "(Lnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FFLnet/minecraft/util/RandomSource;DDD)Lnet/minecraft/client/resources/sounds/SimpleSoundInstance;" ), method = "playSound(DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FFZJ)V" ) @@ -202,4 +202,5 @@ private SimpleSoundInstance redirectNewSoundInstance(final SoundEvent soundEvent return new SimpleSoundInstance(soundEvent, soundSource, volume, pitch, randomSource, x, y, z); } + } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/commands/argument/selector/MixinEntitySelectorParser.java b/common/src/main/java/org/valkyrienskies/mod/mixin/commands/argument/selector/MixinEntitySelectorParser.java new file mode 100644 index 000000000..4ac8ec653 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/commands/argument/selector/MixinEntitySelectorParser.java @@ -0,0 +1,40 @@ +package org.valkyrienskies.mod.mixin.commands.argument.selector; + +import com.mojang.brigadier.StringReader; +import net.minecraft.commands.arguments.selector.EntitySelector; +import net.minecraft.commands.arguments.selector.EntitySelectorParser; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +/** + * This fixes EntitySelectorParser making suggestions in @v ShipArguments + */ +@Mixin(EntitySelectorParser.class) +public class MixinEntitySelectorParser { + @Shadow + @Final + private StringReader reader; + + @Shadow + private void finalizePredicates() { + throw new IllegalStateException(); + } + + @Shadow + public EntitySelector getSelector() { + throw new IllegalStateException(); + } + + @Inject(method = "parse", at = @At("HEAD"), cancellable = true) + private void preParse(final CallbackInfoReturnable cir) { + // If this starts with '@v' then don't suggest anything + if (this.reader.canRead(2) && this.reader.peek() == '@' && this.reader.peek(1) == 'v') { + this.finalizePredicates(); + cir.setReturnValue(this.getSelector()); + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/block_tint/FEATURE.md b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/block_tint/FEATURE.md new file mode 100644 index 000000000..1b2adb1ff --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/block_tint/FEATURE.md @@ -0,0 +1,8 @@ +# Block Tinting + +These mixins fix block tinting for blocks on ships. + +(Only updates if the chunk render buffer is updated) + +Adds a client side option in the config (called "fixBlockTinting" in the category "BlockTinting") to enable this feature. +(default off!) diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/block_tint/MixinClientLevel.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/block_tint/MixinClientLevel.java new file mode 100644 index 000000000..a796effba --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/block_tint/MixinClientLevel.java @@ -0,0 +1,64 @@ +package org.valkyrienskies.mod.mixin.feature.block_tint; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.ColorResolver; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.config.VSGameConfig; + +@Mixin(ClientLevel.class) +public abstract class MixinClientLevel { + + @ModifyVariable( + method = "calculateBlockTint(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/ColorResolver;)I", + ordinal = 0, + at = @At("HEAD"), + argsOnly = true + ) + private BlockPos fixBlockPos(final BlockPos old) { + if (!VSGameConfig.CLIENT.getBlockTinting().getFixBlockTinting()) + return old; + + final Vector3d newPos = + VSGameUtilsKt.toWorldCoordinates( + ClientLevel.class.cast(this), + new Vector3d( + old.getX(), + old.getY(), + old.getZ() + ) + ); + + return BlockPos.containing( + newPos.x, + newPos.y, + newPos.z + ); + } + + @Inject( + method = "getBlockTint(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/ColorResolver;)I", + at = @At("HEAD"), + cancellable = true + ) + public void getBlockTint( + final BlockPos blockPos, + final ColorResolver colorResolver, + final CallbackInfoReturnable cir + ) { + if (VSGameConfig.CLIENT.getBlockTinting().getFixBlockTinting() && + VSGameUtilsKt.isBlockInShipyard(ClientLevel.class.cast(this), blockPos) + ) { + cir.setReturnValue(ClientLevel.class.cast(this) + .calculateBlockTint(blockPos, colorResolver)); + } + } + + +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/container_distance_check/MixinContainer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/container_distance_check/MixinContainer.java index 5a284edf4..10628cfc2 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/container_distance_check/MixinContainer.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/container_distance_check/MixinContainer.java @@ -9,6 +9,7 @@ @Mixin(Container.class) public interface MixinContainer { + @Redirect( method = "stillValidBlockEntity(Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/world/entity/player/Player;I)Z", at = @At( @@ -20,4 +21,5 @@ private static double includeShipsInDistanceCheck( final Player receiver, final double x, final double y, final double z) { return VSGameUtilsKt.squaredDistanceToInclShips(receiver, x, y, z); } + } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/dismount_dead_entities/MixinLivingEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/dismount_dead_entities/MixinLivingEntity.java new file mode 100644 index 000000000..015a452d1 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/dismount_dead_entities/MixinLivingEntity.java @@ -0,0 +1,54 @@ +package org.valkyrienskies.mod.mixin.feature.dismount_dead_entities; + +import net.minecraft.tags.BlockTags; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.joml.Vector3dc; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(LivingEntity.class) +public abstract class MixinLivingEntity extends Entity { + @Unique + private static final Logger VS$LOGGER = LogManager.getLogger(); + + public MixinLivingEntity(final EntityType entityType, final Level level) { + super(entityType, level); + } + + /** + * Fix dismounting dead chairs on ships teleporting entities into the sky + */ + @Inject(method = "dismountVehicle", at = @At("HEAD"), cancellable = true) + private void preDismountVehicle(final Entity entity, final CallbackInfo ci) { + if (!this.isRemoved() && entity.isRemoved() || this.level.getBlockState(entity.blockPosition()).is(BlockTags.PORTALS)) { + if (VSGameUtilsKt.isBlockInShipyard(level, entity.position())) { + final Ship ship = VSGameUtilsKt.getShipManagingPos(level, entity.position()); + if (ship != null) { + final Vector3dc transformedPos = ship.getTransform().getShipToWorld().transformPosition(VectorConversionsMCKt.toJOML(entity.position())); + final double d = Math.max(this.getY(), transformedPos.y()); + final Vec3 vec3 = new Vec3(this.getX(), d, this.getZ()); + this.dismountTo(vec3.x, vec3.y, vec3.z); + ci.cancel(); + } + } else { + // We're in the shipyard but no ship? + VS$LOGGER.debug("Modifying strange dismount"); + final Vec3 vec3 = new Vec3(this.getX(), this.getY(), this.getZ()); + this.dismountTo(vec3.x, vec3.y, vec3.z); + ci.cancel(); + } + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinEntity.java index bc6dc59d1..89e61a69e 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinEntity.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinEntity.java @@ -2,7 +2,6 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import java.util.Random; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.BlockParticleOption; import net.minecraft.core.particles.ParticleTypes; diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/get_entities/MixinLevel.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/get_entities/MixinLevel.java index 93b73da51..a459b8699 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/get_entities/MixinLevel.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/get_entities/MixinLevel.java @@ -17,8 +17,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.valkyrienskies.core.impl.util.RateLimiter; +import org.valkyrienskies.core.util.RateLimiter; import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.util.BugFixUtil; @Mixin(Level.class) public class MixinLevel { @@ -28,11 +29,6 @@ public class MixinLevel { @Unique private static final RateLimiter LIMITER = new RateLimiter(Duration.ofSeconds(5)); - @Unique - private static boolean isCollisionBoxToBig(final AABB aabb) { - return aabb.getXsize() > 1000 || aabb.getYsize() > 1000 || aabb.getZsize() > 1000; - } - @ModifyVariable( method = "getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;", at = @At("HEAD"), @@ -59,7 +55,7 @@ private AABB moveAABB2(final AABB aabb) { private void check1(final EntityTypeTest entityTypeTest, final AABB area, final Predicate predicate, final CallbackInfoReturnable> cir) { - if (isCollisionBoxToBig(area)) { + if (BugFixUtil.INSTANCE.isCollisionBoxToBig(area)) { LIMITER.maybeRun(() -> LOGGER.error(new Exception( "Collision box is too big! " + area + " returning empty list! this might break things"))); @@ -76,7 +72,7 @@ private void check1(final EntityTypeTest entityTyp private void check2(@Nullable final Entity entity, final AABB area, final Predicate predicate, final CallbackInfoReturnable> cir) { - if (isCollisionBoxToBig(area)) { + if (BugFixUtil.INSTANCE.isCollisionBoxToBig(area)) { LIMITER.maybeRun(() -> LOGGER.error(new Exception( "Collision box is too big! " + area + " returning empty list! this might break things"))); diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/ladders/MixinLivingEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/ladders/MixinLivingEntity.java index 1ff482f5b..a7f724a90 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/ladders/MixinLivingEntity.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/ladders/MixinLivingEntity.java @@ -56,7 +56,7 @@ private void onClimbableMixin(final CallbackInfoReturnable cir) { // Only run this if we haven't modified cir yet if (cir.getReturnValue() != Boolean.TRUE) { // Modify the block position, then check if we can climb ladders - thisAsAccessor.setBlockPosition(new BlockPos(Mth.floor(x), Mth.floor(y), Mth.floor(z))); + thisAsAccessor.setBlockPosition(BlockPos.containing(Mth.floor(x), Mth.floor(y), Mth.floor(z))); thisAsAccessor.setFeetBlockState(null); if (onClimbable()) { cir.setReturnValue(true); diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/vs2_alpha_hud/MixinGui.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/vs2_alpha_hud/MixinGui.java index f6e51d83d..7e0a488f9 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/vs2_alpha_hud/MixinGui.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/vs2_alpha_hud/MixinGui.java @@ -41,15 +41,19 @@ private void preRenderStatusEffectOverlay(final GuiGraphics guiGraphics, final C final IntegratedServer integratedServer = this.minecraft.getSingleplayerServer(); if (integratedServer != null) { String physicsTPS = "Error"; + String loadedVoxelChunks = "Error"; try { // This is dangerous because we have to reach into the Server state from the Client, which can fail. // So, put this in a try/catch block to catch any errors that may occur. physicsTPS = " " + Math.round(VSGameUtilsKt.getVsPipeline(integratedServer).computePhysTps()); + loadedVoxelChunks = " " + VSGameUtilsKt.getVsPipeline(integratedServer).getLoadedVoxelChunks(); } catch (final Exception e) { e.printStackTrace(); } final String worldPhysicsDebugText = "VS PhysTPS: " + physicsTPS; debugText.add(worldPhysicsDebugText); + final String loadedVoxelChunkDebugText = "VS VoxelChunks: " + loadedVoxelChunks; + debugText.add(loadedVoxelChunkDebugText); } debugText.add("Using UDP: " + ValkyrienSkiesMod.getVsCore().getClientUsesUDP()); diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/IMixinDeployerHandler.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/IMixinDeployerHandler.java new file mode 100644 index 000000000..5cbe5475b --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/IMixinDeployerHandler.java @@ -0,0 +1,18 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create; + +import com.simibubi.create.content.kinetics.deployer.DeployerHandler; +import javax.annotation.Nullable; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(DeployerHandler.class) +public interface IMixinDeployerHandler { + @Invoker("shouldActivate") + static boolean invokeShouldActivate(ItemStack held, Level world, BlockPos targetPos, @Nullable Direction facing){ + throw new AssertionError(); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/IMixinDeployerMovementBehaviour.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/IMixinDeployerMovementBehaviour.java new file mode 100644 index 000000000..821f697ea --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/IMixinDeployerMovementBehaviour.java @@ -0,0 +1,12 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create; + +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.kinetics.deployer.DeployerMovementBehaviour; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(DeployerMovementBehaviour.class) +public interface IMixinDeployerMovementBehaviour { + @Invoker("tryGrabbingItem") + void invokeTryGrabbingItem(MovementContext movementContext); +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinAirCurrent.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinAirCurrent.java new file mode 100644 index 000000000..52f9d86f8 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinAirCurrent.java @@ -0,0 +1,152 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create; + +import com.simibubi.create.content.kinetics.fan.AirCurrent; +import com.simibubi.create.content.kinetics.fan.IAirCurrentSource; +import com.simibubi.create.foundation.utility.VecHelper; +import java.util.Iterator; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Vec3i; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.joml.primitives.AABBd; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; +import org.valkyrienskies.mod.common.world.RaycastUtilsKt; +import org.valkyrienskies.mod.mixinducks.mod_compat.create.IExtendedAirCurrentSource; + +@Mixin(AirCurrent.class) +public abstract class MixinAirCurrent { + + @Unique + private final float maxAcceleration = 5; + @Shadow + @Final + public IAirCurrentSource source; + @Unique + private Vec3 transformedFlow = Vec3.ZERO; + @Unique + private float acceleration; + + @Unique + private Ship getShip() { + if (source instanceof IExtendedAirCurrentSource se) + return se.getShip(); + else if (source.getAirCurrentWorld() != null) + return VSGameUtilsKt.getShipManagingPos(source.getAirCurrentWorld(), source.getAirCurrentPos()); + else + return null; + } + + @Inject(method = "getFlowLimit", at = @At("HEAD"), cancellable = true) + private static void clipFlowLimit(Level level, BlockPos start, float max, Direction facing, CallbackInfoReturnable cir) { + Ship ship = VSGameUtilsKt.getShipManagingPos(level, start); + if (ship != null) { + Vector3d startVec = ship.getTransform().getShipToWorld().transformPosition(new Vector3d(start.getX() + 0.5, start.getY() + 0.5, start.getZ() + 0.5)); + Vector3d direction = ship.getTransform().getShipToWorld().transformDirection(VectorConversionsMCKt.toJOMLD(facing.getNormal())); + startVec.add(direction.x, direction.y, direction.z); + direction.mul(max); + Vec3 mcStart = VectorConversionsMCKt.toMinecraft(startVec); + BlockHitResult result = RaycastUtilsKt.clipIncludeShips(level, + new ClipContext( + mcStart, + VectorConversionsMCKt.toMinecraft(startVec.add(direction.x, direction.y, direction.z)), + ClipContext.Block.OUTLINE, + ClipContext.Fluid.NONE, + null)); + + // Distance from start to end but, its not squared so, slow -_- + cir.setReturnValue((float) result.getLocation().distanceTo(mcStart)); + } else { + BlockPos end = start.relative(facing, (int) max); + if (VSGameUtilsKt.getShipsIntersecting(level, + new AABB(start.getX(), start.getY(), start.getZ(), + end.getX() + 1.0, end.getY() + 1.0, end.getZ() + 1.0)).iterator().hasNext()) { + Vec3 centerStart = Vec3.atCenterOf(start); + BlockHitResult result = RaycastUtilsKt.clipIncludeShips(level, + new ClipContext( + centerStart.add(facing.getStepX(), facing.getStepY(), facing.getStepZ()), + Vec3.atCenterOf(end), + ClipContext.Block.OUTLINE, + ClipContext.Fluid.NONE, + null)); + + // Distance from start to end but, its not squared so, slow -_- + cir.setReturnValue((float) result.getLocation().distanceTo(centerStart)); + } + } + } + + @Redirect(method = "tickAffectedEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/AABB;intersects(Lnet/minecraft/world/phys/AABB;)Z")) + private boolean redirectIntersects(AABB instance, AABB other) { + Ship ship = getShip(); + if (ship != null) { + AABBd thisAABB = VectorConversionsMCKt.toJOML(instance); + thisAABB.transform(ship.getWorldToShip()); + return other.intersects(thisAABB.minX, thisAABB.minY, thisAABB.minZ, thisAABB.maxX, thisAABB.maxY, thisAABB.maxZ); + } else return instance.intersects(other); + } + + @Inject( + method = "tickAffectedEntities", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/Entity;getDeltaMovement()Lnet/minecraft/world/phys/Vec3;" + ), + locals = LocalCapture.CAPTURE_FAILHARD + ) + private void harvester(Level world, Direction facing, CallbackInfo ci, Iterator iterator, Entity entity, Vec3 center, Vec3i flow, float sneakModifier, float speed, double entityDistance, float acceleration) { + Ship ship = getShip(); + if (ship != null) { + Vector3d tempVec = new Vector3d(); + ship.getTransform().getShipToWorld().transformDirection(flow.getX(), flow.getY(), flow.getZ(), tempVec); + transformedFlow = VectorConversionsMCKt.toMinecraft(tempVec); + } + this.acceleration = acceleration; + } + + @Redirect(method = "tickAffectedEntities", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V") + ) + private void redirectSetDeltaMovement(Entity instance, Vec3 motion) { + Ship ship = getShip(); + if (ship != null) { + Vec3 previousMotion = instance.getDeltaMovement(); + double xIn = Mth.clamp(transformedFlow.x * acceleration - previousMotion.x, -maxAcceleration, maxAcceleration); + double yIn = Mth.clamp(transformedFlow.y * acceleration - previousMotion.y, -maxAcceleration, maxAcceleration); + double zIn = Mth.clamp(transformedFlow.z * acceleration - previousMotion.z, -maxAcceleration, maxAcceleration); + instance.setDeltaMovement(previousMotion.add(new Vec3(xIn, yIn, zIn).scale(1 / 8f))); + } else { + instance.setDeltaMovement(motion); + } + } + + @Redirect(method = "tickAffectedEntities", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/foundation/utility/VecHelper;getCenterOf(Lnet/minecraft/core/Vec3i;)Lnet/minecraft/world/phys/Vec3;"), allow = 1) + private Vec3 redirectGetCenterOf(Vec3i pos) { + Ship ship = getShip(); + Vec3 result = VecHelper.getCenterOf(pos); + if (ship != null && this.source.getAirCurrentWorld() != null) { + Vector3d tempVec = new Vector3d(); + ship.getTransform().getShipToWorld().transformPosition(result.x, result.y, result.z, tempVec); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + return result; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinAirFlowParticle.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinAirFlowParticle.java new file mode 100644 index 000000000..623e7196c --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinAirFlowParticle.java @@ -0,0 +1,85 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create; + +import com.simibubi.create.content.kinetics.fan.AirCurrent; +import com.simibubi.create.content.kinetics.fan.AirFlowParticle; +import com.simibubi.create.content.kinetics.fan.IAirCurrentSource; +import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.SimpleAnimatedParticle; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.core.Vec3i; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; +import org.valkyrienskies.mod.mixinducks.mod_compat.create.IExtendedAirCurrentSource; + +@Mixin(AirFlowParticle.class) +public abstract class MixinAirFlowParticle extends SimpleAnimatedParticle { + + @Shadow + @Final + private IAirCurrentSource source; + + protected MixinAirFlowParticle(ClientLevel level, double x, double y, double z, SpriteSet sprites, float gravity) { + super(level, x, y, z, sprites, gravity); + } + + @Unique + private Ship getShip() { + if (source instanceof IExtendedAirCurrentSource se) + return se.getShip(); + else if (source.getAirCurrentWorld() != null) + return VSGameUtilsKt.getShipManagingPos(source.getAirCurrentWorld(), source.getAirCurrentPos()); + else + return null; + } + + @Redirect(method = "tick", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/phys/AABB;contains(DDD)Z" + )) + private boolean redirectBounds(AABB instance, double x, double y, double z) { + AirCurrent current = source.getAirCurrent(); + Level level = source.getAirCurrentWorld(); + if (current != null && level != null) { + return VSGameUtilsKt.transformAabbToWorld(level, instance).contains(x, y, z); + } + + return instance.contains(x, y, z); + } + + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/foundation/utility/VecHelper;getCenterOf(Lnet/minecraft/core/Vec3i;)Lnet/minecraft/world/phys/Vec3;"), allow = 1) + private Vec3 redirectGetCenterOf(Vec3i pos) { + Ship ship = getShip(); + Vec3 result = VecHelper.getCenterOf(pos); + if (ship != null) { + Vector3d tempVec = new Vector3d(); + ship.getTransform().getShipToWorld().transformPosition(result.x, result.y, result.z, tempVec); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + return result; + } + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;atLowerCornerOf(Lnet/minecraft/core/Vec3i;)Lnet/minecraft/world/phys/Vec3;"), allow = 1) + private Vec3 redirectToLowerCorner(Vec3i pos) { + Vec3 result = Vec3.atLowerCornerOf(pos); + Ship ship = getShip(); + if (ship != null) { + Vector3d tempVec = new Vector3d(); + ship.getTransform().getShipToWorld().transformDirection(result.x, result.y, result.z, tempVec); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + return result; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinBeltMovementHandler.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinBeltMovementHandler.java new file mode 100644 index 000000000..5ec2e0c3e --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinBeltMovementHandler.java @@ -0,0 +1,148 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create; + +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; +import com.simibubi.create.content.kinetics.belt.transport.BeltMovementHandler; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Vec3i; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.MoverType; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.joml.Quaterniond; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(BeltMovementHandler.class) +public abstract class MixinBeltMovementHandler { + + @Unique + private static Vector3d blockPos; + + @Unique + private static Level level; + + @Unique + private static Ship ship; + + @Unique + private static Direction.Axis axis; + + @Unique + private static Entity entity; + + @Inject(method = "transportEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/Direction;fromAxisAndDirection(Lnet/minecraft/core/Direction$Axis;Lnet/minecraft/core/Direction$AxisDirection;)Lnet/minecraft/core/Direction;"), locals = LocalCapture.CAPTURE_FAILHARD) + private static void injectHead(BeltBlockEntity beltTe, Entity entityIn, BeltMovementHandler.TransportedEntityInfo info, CallbackInfo ci, BlockPos pos) { + blockPos = VectorConversionsMCKt.toJOMLD(pos); + entity = entityIn; + level = beltTe.getLevel(); + if (level != null) { + ship = VSGameUtilsKt.getShipManagingPos(level, blockPos); + } + } + + @ModifyVariable(method = "transportEntity", at = @At(value = "STORE"), name = "axis") + private static Direction.Axis injectHarvestAxis(Direction.Axis value) { + axis = value; + return value; + } + + @Redirect(method = "transportEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;move(Lnet/minecraft/world/entity/MoverType;Lnet/minecraft/world/phys/Vec3;)V", ordinal = 2)) + private static void redirectMove1(Entity instance, MoverType type, Vec3 pos) { + if (ship != null) { + instance.move(type, new Vec3(pos.x * 3, 0.2, pos.z * 3)); + } else + instance.move(type, pos); + } + + @Redirect(method = "transportEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;move(Lnet/minecraft/world/entity/MoverType;Lnet/minecraft/world/phys/Vec3;)V", ordinal = 1)) + private static void redirectMove2(Entity instance, MoverType type, Vec3 pos) { + if (ship != null) { + instance.move(type, new Vec3(pos.x * 3, 0, pos.z * 3)); + } else + instance.move(type, pos); + } + + @Redirect(method = "transportEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/Direction$Axis;choose(DDD)D")) + private static double redirectChoose(Direction.Axis instance, double x, double y, double z) { + if (ship != null) { + Vec3 mul = new Vec3(0, 0, 0); + if (instance == Direction.Axis.X) { + mul = redirectGetNormal(new Vec3i(1, 0, 0)); + } + if (instance == Direction.Axis.Y) { + mul = redirectGetNormal(new Vec3i(0, 1, 0)); + } + if (instance == Direction.Axis.Z) { + mul = redirectGetNormal(new Vec3i(0, 0, 1)); + } + return Math.abs(x * mul.x) + Math.abs(y * mul.y) + Math.abs(z * mul.z); + } + return instance.choose(x, y, z); + } + + @ModifyVariable(method = "transportEntity", at = @At(value = "STORE"), name = "diffCenter") + private static double modDiffCenter(double value) { + //if (ship != null) value = value + Math.copySign(value) ); + return axis == Direction.Axis.Z ? (blockPos.x + .5 - getPos(entity).x) : (blockPos.z + .5 - getPos(entity).z); + } + + @Redirect( + method = "transportEntity", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/phys/Vec3;atLowerCornerOf(Lnet/minecraft/core/Vec3i;)Lnet/minecraft/world/phys/Vec3;" + ) + ) + private static Vec3 redirectGetNormal(Vec3i toCopy) { + Vec3 result = Vec3.atLowerCornerOf(toCopy); + if (level != null) { + if (ship != null) { + Vector3d tempVec = VectorConversionsMCKt.toJOML(result); + Quaterniond tempQuat = new Quaterniond(); + ship.getTransform().getShipToWorld().getNormalizedRotation(tempQuat); + tempVec.rotate(tempQuat); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + } + return result; + } + + @Redirect(method = "transportEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getX()D")) + private static double redirectGetX(Entity instance) { + return getPos(instance).x; + } + + @Redirect(method = "transportEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getY()D")) + private static double redirectGetY(Entity instance) { + return getPos(instance).y; + } + + @Redirect(method = "transportEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getZ()D")) + private static double redirectGetZ(Entity instance) { + return getPos(instance).z; + } + + @Unique + private static Vec3 getPos(Entity entity) { + Vec3 result = entity.position(); + if (level != null) { + if (ship != null) { + Vector3d tempVec = VectorConversionsMCKt.toJOML(result); + ship.getTransform().getWorldToShip().transformPosition(tempVec); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + } + return result; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinContraption.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinContraption.java new file mode 100644 index 000000000..4563a841b --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinContraption.java @@ -0,0 +1,26 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create; + +import com.simibubi.create.content.contraptions.Contraption; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(Contraption.class) +public class MixinContraption { + @Redirect(method = "onEntityCreated", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + private boolean wrapOp(Level level, Entity entity) { + // BlockPos anchor = blockFace.getConnectedPos(); + // movedContraption.setPos(anchor.getX() + .5f, anchor.getY(), anchor.getZ() + .5f); + // + // Derive anchor from the code above + final BlockPos anchor = BlockPos.containing((int) Math.floor(entity.getX()), (int) Math.floor(entity.getY()), (int) Math.floor(entity.getZ())); + boolean added = level.addFreshEntity(entity); + if (added) { + entity.moveTo(anchor.getX() + .5, anchor.getY(), anchor.getZ() + .5); + } + return added; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinContraptionCollider.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinContraptionCollider.java new file mode 100644 index 000000000..b22f08206 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinContraptionCollider.java @@ -0,0 +1,342 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create; + +import static org.valkyrienskies.mod.common.util.VectorConversionsMCKt.toJOML; +import static org.valkyrienskies.mod.common.util.VectorConversionsMCKt.toMinecraft; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.ContraptionCollider; +import com.simibubi.create.foundation.collision.Matrix3d; +import com.simibubi.create.foundation.utility.VecHelper; +import javax.annotation.Nullable; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.joml.Vector3d; +import org.joml.primitives.AABBd; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(ContraptionCollider.class) +public abstract class MixinContraptionCollider { + @Shadow + static Vec3 collide(Vec3 p_20273_, Entity e) { + return p_20273_; + } + + @Unique + private static final Logger LOGGER = LogManager.getLogger("Clockwork.MixinContraptionCollider"); + + @Unique + private static AbstractContraptionEntity contraptionEnt; + + @Unique + private static AABB entityGetBoundingBox(AbstractContraptionEntity abstractContraptionEntity, Entity instance) { + AABB tempAabb = instance.getBoundingBox(); + if (!VSGameUtilsKt.isBlockInShipyard(instance.getCommandSenderWorld(), instance.blockPosition()) && VSGameUtilsKt.isBlockInShipyard(contraptionEnt.getCommandSenderWorld(), BlockPos.containing(contraptionEnt.getAnchorVec()))) { + Ship ship = VSGameUtilsKt.getShipManagingPos(instance.getCommandSenderWorld(), contraptionEnt.getAnchorVec()); + if (ship != null) { + AABBd temp = new AABBd(); + temp.set(toJOML(tempAabb)).transform(ship.getWorldToShip()); + tempAabb = toMinecraft(temp); + } + } + return tempAabb; + } + + @Unique + private static Vec3 entityPosition(AbstractContraptionEntity abstractContraptionEntity, Entity instance, boolean old) { + Vec3 tempVec = old ? new Vec3(instance.xo, instance.yo, instance.zo) : instance.position(); + if (!VSGameUtilsKt.isBlockInShipyard(instance.getCommandSenderWorld(), instance.blockPosition()) && VSGameUtilsKt.isBlockInShipyard(abstractContraptionEntity.getCommandSenderWorld(), BlockPos.containing(abstractContraptionEntity.getAnchorVec()))) { + Ship ship = VSGameUtilsKt.getShipManagingPos(abstractContraptionEntity.getCommandSenderWorld(), abstractContraptionEntity.getContraption().anchor); + if (ship != null) { + Vector3d translatedPos = ship.getTransform().getWorldToShip().transformPosition(toJOML(tempVec)); + tempVec = toMinecraft(translatedPos); + } + } + return tempVec; + } + + @Unique + private static Vec3 getSetEntityDeltaMovement(AbstractContraptionEntity abstractContraptionEntity, Entity instance, @Nullable Vec3 motion) { + Vec3 tempVec = instance.getDeltaMovement(); + if (!VSGameUtilsKt.isBlockInShipyard(instance.getCommandSenderWorld(), instance.blockPosition()) && VSGameUtilsKt.isBlockInShipyard(abstractContraptionEntity.getCommandSenderWorld(), new BlockPos(abstractContraptionEntity.getContraption().anchor))) { + Ship ship = VSGameUtilsKt.getShipManagingPos(instance.getCommandSenderWorld(), abstractContraptionEntity.getContraption().anchor); + if (ship != null) { + if (motion != null) { + if (!VSGameUtilsKt.isBlockInShipyard(abstractContraptionEntity.getCommandSenderWorld(), BlockPos.containing(abstractContraptionEntity.getAnchorVec()))) { + motion = toMinecraft(ship.getWorldToShip().transformDirection(toJOML(motion))); + } else { + motion = toMinecraft(ship.getShipToWorld().transformDirection(toJOML(motion))); + } + instance.setDeltaMovement(motion); + motion = null; + } + tempVec = toMinecraft(ship.getWorldToShip().transformDirection(toJOML(tempVec))); + } + } + if (motion != null) { + instance.setDeltaMovement(motion); + } + return tempVec; + } + + @Inject(method = "collideEntities", at = @At("HEAD"), remap = false) + private static void injectHead(AbstractContraptionEntity contraptionEntity, CallbackInfo ci) { + contraptionEnt = contraptionEntity; + } + + private static void warn1(Vector3d vec3) { + LOGGER.warn("Warning setPosDistance too high ignoring setPos request [" + vec3.x + "," + vec3.y + "," + vec3.z + "]"); + } + + private static void warn2(double x, double y, double z) { + LOGGER.warn("Warning DEFAULT setPosDistance too high ignoring setPos request [" + x + "," + y + "," + z + "]"); + } + + private static void setOfPos(AbstractContraptionEntity abstractContraptionEntity, Entity instance, double x, double y, double z) { + if (VSGameUtilsKt.isBlockInShipyard(instance.getCommandSenderWorld(), BlockPos.containing(x, y, z)) && + !VSGameUtilsKt.isBlockInShipyard(instance.getCommandSenderWorld(), instance.blockPosition())) { + Ship ship = VSGameUtilsKt.getShipManagingPos(instance.getCommandSenderWorld(), abstractContraptionEntity.getContraption().anchor); + if (ship != null) { + Vector3d newPos = new Vector3d(x, y, z); + ship.getShipToWorld().transformPosition(newPos, newPos); + if (instance.position().distanceTo(toMinecraft(newPos)) < 20) { + instance.setPos(newPos.x, newPos.y, newPos.z); + } else + warn1(newPos); + } + } else { + + if (instance.position().distanceTo(new Vec3(x, y, z)) < 20) { + instance.setPos(x, y, z); + } else + warn2(x, y, z); + } + } + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setPos(DDD)V")) + private static void redirectSetPos(Entity instance, double x, double y, double z) { + setOfPos(contraptionEnt, instance, x, y, z); + } + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/AbstractContraptionEntity;getBoundingBox()Lnet/minecraft/world/phys/AABB;")) + private static AABB redirectContraptionGetBoundingBox(AbstractContraptionEntity instance) { + return VSGameUtilsKt.transformAabbToWorld(instance.getCommandSenderWorld(), instance.getBoundingBox()); + } + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getBoundingBox()Lnet/minecraft/world/phys/AABB;")) + private static AABB redirectEntityGetBoundingBox(Entity instance) { + return entityGetBoundingBox(contraptionEnt, instance); + } + + /* + @Redirect(method="collideEntities",at = @At(value="INVOKE_ASSIGN",target = "Lnet/minecraft/world/phys/AABB;getCenter()Lnet/minecraft/world/phys/Vec3;",ordinal = 3)) + private static Vec3 redirectGetCenter(AABB instance){ + if(instance) + return instance.getCenter(); + }*/ + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;position()Lnet/minecraft/world/phys/Vec3;")) + private static Vec3 redirectEntityPosition(Entity instance) { + return entityPosition(contraptionEnt, instance, false); + } + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getDeltaMovement()Lnet/minecraft/world/phys/Vec3;")) + private static Vec3 redirectEntityGetDeltaMovement(Entity instance) { + return getSetEntityDeltaMovement(contraptionEnt, instance, null); + } + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V")) + private static void redirectEntitySetDeltaMovement(Entity instance, Vec3 motion) { + getSetEntityDeltaMovement(contraptionEnt, instance, motion); + } + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getX()D")) + private static double redirectEntityGetX(Entity instance) { + return entityPosition(contraptionEnt, instance, false).x; + } + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getY()D")) + private static double redirectEntityGetY(Entity instance) { + return entityPosition(contraptionEnt, instance, false).y; + } + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getZ()D")) + private static double redirectEntityGetZ(Entity instance) { + return entityPosition(contraptionEnt, instance, false).z; + } + + + @Redirect(method = "collideEntities", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/Entity;xo:D", opcode = Opcodes.GETFIELD)) + private static double redirectEntityGetXo(Entity instance) { + return entityPosition(contraptionEnt, instance, true).x; + } + + @Redirect(method = "collideEntities", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/Entity;zo:D", opcode = Opcodes.GETFIELD)) + private static double redirectEntityGetZo(Entity instance) { + return entityPosition(contraptionEnt, instance, true).z; + } + + private static Vec3 aaaaaaaaaaaaaa(AbstractContraptionEntity abstractContraptionEntity, Entity entity, Vec3 anchorVec, Matrix3d rotationMatrix, float yawOffset) { + + if (VSGameUtilsKt.isBlockInShipyard(abstractContraptionEntity.getCommandSenderWorld(), abstractContraptionEntity.getContraption().anchor) + && !VSGameUtilsKt.isBlockInShipyard(abstractContraptionEntity.getCommandSenderWorld(), entity.blockPosition())) { + + Ship ship = VSGameUtilsKt.getShipManagingPos(abstractContraptionEntity.getCommandSenderWorld(), abstractContraptionEntity.getContraption().anchor); + if (ship != null) { + Vec3 entityPosition = entityPosition(abstractContraptionEntity, entity, false); + Vec3 centerY = new Vec3(0, entityGetBoundingBox(contraptionEnt, entity) + .getYsize() / 2, 0); + Vec3 position = entityPosition; + position = position.add(centerY); + position = position.subtract(VecHelper.CENTER_OF_ORIGIN); + position = position.subtract(anchorVec); + position = VecHelper.rotate(position, -yawOffset, Direction.Axis.Y); + position = rotationMatrix.transform(position); + position = position.add(VecHelper.CENTER_OF_ORIGIN); + position = position.subtract(centerY); + position = position.subtract(entityPosition); + + return position;//toMinecraft(ship.getShipToWorld().transformPosition(position.x, position.y, position.z, new Vector3d())); + } + } + return ContraptionCollider.getWorldToLocalTranslation(entity, anchorVec, rotationMatrix, yawOffset); + } + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/AbstractContraptionEntity;getPrevPositionVec()Lnet/minecraft/world/phys/Vec3;")) + private static Vec3 redirectGetPrevPositionVec(AbstractContraptionEntity instance) { + + Vec3 prevPos = instance.getPrevPositionVec(); + + if (VSGameUtilsKt.isBlockInShipyard(instance.level(), BlockPos.containing(instance.getAnchorVec())) && !VSGameUtilsKt.isBlockInShipyard(instance.level(), BlockPos.containing(instance.getPrevAnchorVec()))) { + Ship ship = VSGameUtilsKt.getShipManagingPos(instance.level(), instance.getAnchorVec()); + if (ship != null) { + Vec3 result = toMinecraft(ship.getWorldToShip().transformPosition(toJOML(instance.getPrevPositionVec()))); + instance.xo = result.x; + instance.yo = result.y; + instance.zo = result.z; + prevPos = result; + } + } + + + if (!VSGameUtilsKt.isBlockInShipyard(instance.getCommandSenderWorld(), BlockPos.containing(prevPos)) && VSGameUtilsKt.isBlockInShipyard(instance.getCommandSenderWorld(), BlockPos.containing(instance.position()))) { + //instance.setOldPosAndRot(); + //prevPos = instance.position(); + /* + Ship ship = VSGameUtilsKt.getShipManagingPos(instance.getCommandSenderWorld(), instance.position()); + if (ship != null) { + Vec3 transformedPrevPos = toMinecraft(ship.getWorldToShip().transformPosition(toJOML(prevPos))); + prevPos = transformedPrevPos; + }*/ + } + return prevPos; + } + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/ContraptionCollider;getWorldToLocalTranslation(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;Lcom/simibubi/create/foundation/collision/Matrix3d;F)Lnet/minecraft/world/phys/Vec3;")) + private static Vec3 redirectGetWorldToLocalTranslation(Entity entity, Vec3 anchorVec, Matrix3d rotationMatrix, float yawOffset) { + return aaaaaaaaaaaaaa(contraptionEnt, entity, anchorVec, rotationMatrix, yawOffset); + } + + @Unique + private static Vec3 adjustCollide(Vec3 contactPoint, Entity entity) { + Vec3 result = collide(contactPoint, entity); + + if (VSGameUtilsKt.isBlockInShipyard(entity.getCommandSenderWorld(), contactPoint.x, contactPoint.y, contactPoint.z) + && !VSGameUtilsKt.isBlockInShipyard(entity.getCommandSenderWorld(), entity.blockPosition())) { + Ship ship = VSGameUtilsKt.getShipManagingPos(entity.getCommandSenderWorld(), contactPoint); + if (ship != null) { + Vec3 temp = toMinecraft(ship.getShipToWorld().transformPosition(toJOML(contactPoint))); + result = collide(temp, entity); + result = toMinecraft(ship.getWorldToShip().transformPosition(toJOML(result))); + } + } else if (!VSGameUtilsKt.isBlockInShipyard(entity.getCommandSenderWorld(), contactPoint.x, contactPoint.y, contactPoint.z) + && VSGameUtilsKt.isBlockInShipyard(entity.getCommandSenderWorld(), entity.blockPosition())) { + Ship ship = VSGameUtilsKt.getShipManagingPos(entity.getCommandSenderWorld(), entity.blockPosition()); + if (ship != null) { + Vec3 temp = toMinecraft(ship.getWorldToShip().transformPosition(toJOML(contactPoint))); + result = collide(temp, entity); + result = toMinecraft(ship.getShipToWorld().transformPosition(toJOML(result))); + } + } + + return result; + } + + @Redirect(method = "collideEntities", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/ContraptionCollider;collide(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/entity/Entity;)Lnet/minecraft/world/phys/Vec3;")) + private static Vec3 redirectEntityGetBoundingBoxCollide(Vec3 contactPoint, Entity entity) { + return adjustCollide(contactPoint, entity); + } + + //@Redirect(method = "getWorldToLocalTranslation(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;Lcom/simibubi/create/foundation/collision/Matrix3d;F)Lnet/minecraft/world/phys/Vec3;", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getBoundingBox()Lnet/minecraft/world/phys/AABB;")) + private static AABB redirectEntityGetBoundingBox2(Entity instance) { + return entityGetBoundingBox(contraptionEnt, instance); + } + + //@Redirect(method = "getWorldToLocalTranslation(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;Lcom/simibubi/create/foundation/collision/Matrix3d;F)Lnet/minecraft/world/phys/Vec3;", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;position()Lnet/minecraft/world/phys/Vec3;")) + private static Vec3 redirectEntityPosition2(Entity instance) { + return entityPosition(contraptionEnt, instance, false); + } + + @Inject(method = "worldToLocalPos(Lnet/minecraft/world/phys/Vec3;Lcom/simibubi/create/content/contraptions/AbstractContraptionEntity;)Lnet/minecraft/world/phys/Vec3;", at = @At("HEAD"), cancellable = true) + private static void modPosition(Vec3 entity, AbstractContraptionEntity contraptionEntity, CallbackInfoReturnable cir) { + if (VSGameUtilsKt.isBlockInShipyard(contraptionEntity.getCommandSenderWorld(), new BlockPos(contraptionEntity.getContraption().anchor)) + && !VSGameUtilsKt.isBlockInShipyard(contraptionEntity.getCommandSenderWorld(), BlockPos.containing(entity))) { + + Ship ship = VSGameUtilsKt.getShipManagingPos(contraptionEntity.getCommandSenderWorld(), contraptionEntity.getContraption().anchor); + if (ship != null) { + cir.setReturnValue(ContraptionCollider.worldToLocalPos(entity, toMinecraft(ship.getShipToWorld().transformPosition(toJOML(contraptionEntity.getAnchorVec()))), contraptionEntity.getRotationState())); + } + } + } + + @Unique + private static AbstractContraptionEntity hDFTContraptionEntity; + + @ModifyVariable(method = "handleDamageFromTrain", at = @At("HEAD"), argsOnly = true) + private static AbstractContraptionEntity injectHandleDamageFromTrain(AbstractContraptionEntity abstractContraptionEntity) { + return hDFTContraptionEntity = abstractContraptionEntity; + } + + @Redirect(method = "handleDamageFromTrain", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getDeltaMovement()Lnet/minecraft/world/phys/Vec3;")) + private static Vec3 redirectEntityGetDeltaMovementFromTrain(Entity instance) { + return getSetEntityDeltaMovement(hDFTContraptionEntity, instance, null); + } + + @Unique + private static AbstractContraptionEntity bounceEntityContraptionEntity; + + @ModifyVariable(method = "bounceEntity", at = @At("HEAD"), argsOnly = true) + private static AbstractContraptionEntity injectBounceEntity(AbstractContraptionEntity abstractContraptionEntity) { + return bounceEntityContraptionEntity = abstractContraptionEntity; + } + + @Redirect(method = "bounceEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;position()Lnet/minecraft/world/phys/Vec3;")) + private static Vec3 redirectEntityPositionBounceEntity(Entity instance) { + return entityPosition(bounceEntityContraptionEntity, instance, false); + } + + @Redirect(method = "bounceEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getDeltaMovement()Lnet/minecraft/world/phys/Vec3;")) + private static Vec3 redirectEntityGetDeltaMovementBounceEntity(Entity instance) { + return getSetEntityDeltaMovement(bounceEntityContraptionEntity, instance, null); + } + + @Redirect(method = "bounceEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V")) + private static void redirectEntitySetDeltaMovementBounceEntity(Entity instance, Vec3 motion) { + getSetEntityDeltaMovement(bounceEntityContraptionEntity, instance, motion); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinEntityLauncher.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinEntityLauncher.java new file mode 100644 index 000000000..fea23a23b --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinEntityLauncher.java @@ -0,0 +1,51 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create; + +import com.simibubi.create.content.logistics.depot.EntityLauncher; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(EntityLauncher.class) +public abstract class MixinEntityLauncher { + + @Unique + private BlockPos launcher; + + @Inject(method = "getGlobalPos", at = @At("HEAD")) + private void harvestBlockPos(double t, Direction d, BlockPos launcher, CallbackInfoReturnable cir) { + this.launcher = launcher; + } + + @ModifyVariable(method = "getGlobalPos", at = @At("STORE"), name = "start") + private Vec3 modStart(Vec3 value) { + return new Vec3(launcher.getX() + .5, launcher.getY() + .5, launcher.getZ() + .5); + } + + @Redirect(method = "applyMotion", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setDeltaMovement(DDD)V")) + private void redirectSetDeltaMovement(Entity instance, double x, double y, double z) { + instance.setDeltaMovement(outMotion(instance, new Vec3(x, y, z))); + } + + @Unique + private Vec3 outMotion(Entity entity, Vec3 motion) { + Ship ship = VSGameUtilsKt.getShipManagingPos(entity.level(), entity.getOnPos()); + if (ship != null) { + Vector3d tempVec = VectorConversionsMCKt.toJOML(motion); + ship.getTransform().getShipToWorld().transformDirection(tempVec); + motion = VectorConversionsMCKt.toMinecraft(tempVec); + } + return motion; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinRedstoneLinkNetworkHandler.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinRedstoneLinkNetworkHandler.java new file mode 100644 index 000000000..c1b6e3afb --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinRedstoneLinkNetworkHandler.java @@ -0,0 +1,51 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create; + +import com.simibubi.create.content.redstone.link.IRedstoneLinkable; +import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(RedstoneLinkNetworkHandler.class) +public abstract class MixinRedstoneLinkNetworkHandler { + + @Unique + private static Level harvestedWorld; + + @Redirect( + method = "withinRange", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/core/BlockPos;closerThan(Lnet/minecraft/core/Vec3i;D)Z" + ) + ) + private static boolean redirectCloserThan(BlockPos instance, Vec3i vec3i, double v) { + Ship ship1 = VSGameUtilsKt.getShipManagingPos(harvestedWorld, instance); + Ship ship2 = VSGameUtilsKt.getShipManagingPos(harvestedWorld, new BlockPos(vec3i)); + Vec3 pos1 = Vec3.atLowerCornerOf(instance); + Vec3 pos2 = Vec3.atLowerCornerOf(vec3i); + if (ship1 != null) { + pos1 = VectorConversionsMCKt.toMinecraft(ship1.getShipToWorld().transformPosition(VectorConversionsMCKt.toJOML(pos1))); + } + if (ship2 != null) { + pos2 = VectorConversionsMCKt.toMinecraft(ship2.getShipToWorld().transformPosition(VectorConversionsMCKt.toJOML(pos2))); + } + return pos1.closerThan(pos2, v); + } + + @Inject(method = "updateNetworkOf", at = @At("HEAD")) + private void harvestLevel(LevelAccessor world, IRedstoneLinkable actor, CallbackInfo ci) { + harvestedWorld = (Level) world; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinSharedDepotBlockMethods.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinSharedDepotBlockMethods.java new file mode 100644 index 000000000..3832885cd --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinSharedDepotBlockMethods.java @@ -0,0 +1,28 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create; + +import com.simibubi.create.content.logistics.depot.SharedDepotBlockMethods; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(SharedDepotBlockMethods.class) +public abstract class MixinSharedDepotBlockMethods { + @Redirect(method = "onLanded", at = @At( + value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;blockPosition()Lnet/minecraft/core/BlockPos;" + )) + private static BlockPos redirectBlockPosition(Entity instance) { + BlockPos result = instance.blockPosition(); + Ship ship = VSGameUtilsKt.getShipObjectManagingPos(instance.level(), instance.getOnPos()); + if (ship != null) { + Vector3d tempVec = new Vector3d(instance.position().x, instance.position().y, instance.position().z); + ship.getWorldToShip().transformPosition(tempVec, tempVec); + result = BlockPos.containing(Math.floor(tempVec.x), Math.floor(tempVec.y), Math.floor(tempVec.z)); + } + return result; + } +} diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/Matrix3dAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/accessors/Matrix3dAccessor.java similarity index 89% rename from forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/Matrix3dAccessor.java rename to common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/accessors/Matrix3dAccessor.java index e6f6a41ab..7e7c54995 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/Matrix3dAccessor.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/accessors/Matrix3dAccessor.java @@ -1,6 +1,6 @@ -package org.valkyrienskies.mod.forge.mixin.compat.create; +package org.valkyrienskies.mod.mixin.mod_compat.create.accessors; + -/* import com.simibubi.create.foundation.collision.Matrix3d; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -34,4 +34,4 @@ public interface Matrix3dAccessor { @Accessor("m22") double getM22(); } -*/ + diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/accessors/OutlineParamsAccessor.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/accessors/OutlineParamsAccessor.java new file mode 100644 index 000000000..6c4fd3a9b --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/accessors/OutlineParamsAccessor.java @@ -0,0 +1,22 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.accessors; + +import com.simibubi.create.AllSpecialTextures; +import com.simibubi.create.foundation.outliner.Outline; +import java.util.Optional; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Outline.OutlineParams.class) +public interface OutlineParamsAccessor { + @Accessor("alpha") + float getAlpha(); + + @Accessor("alpha") + void setAlpha(float alpha); + + @Accessor + boolean getDisableCull(); + + @Accessor + Optional getFaceTexture(); +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinBlockBreakingMovementBehaviour.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinBlockBreakingMovementBehaviour.java new file mode 100644 index 000000000..8d8897327 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinBlockBreakingMovementBehaviour.java @@ -0,0 +1,61 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.behaviour; + +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(BlockBreakingMovementBehaviour.class) +public class MixinBlockBreakingMovementBehaviour { + //Region start - fix equals -0 != 0 + private Vec3 flatten(Vec3 vec3) { + if (vec3.x == -0) { + vec3 = new Vec3(0, vec3.y, vec3.z); + } + if (vec3.y == -0) { + vec3 = new Vec3(vec3.x, 0, vec3.z); + } + if (vec3.z == -0) { + vec3 = new Vec3(vec3.x, vec3.y, 0); + } + return vec3; + } + + @Redirect(method = "tickBreaker", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;equals(Ljava/lang/Object;)Z")) + private boolean redirectEquals(Vec3 instance, final Object vec3) { + Vec3 other = (Vec3) vec3; + other = flatten(other); + instance = flatten(instance); + return instance.equals(other); + } + //Region end + //Region start - fix entity throwing not being aligned to ship + @Unique + private MovementContext movementContext; + + @Inject(method = "throwEntity", at = @At("HEAD")) + private void injectThrowEntity(final MovementContext context, final Entity entity, final CallbackInfo ci) { + movementContext = context; + } + + @Redirect(method = "throwEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V")) + private void redirectSetDeltaMovement(final Entity instance, Vec3 motion) { + if (movementContext != null && VSGameUtilsKt.isBlockInShipyard(movementContext.world, movementContext.contraption.anchor)) { + Ship ship = VSGameUtilsKt.getShipManagingPos(movementContext.world, movementContext.contraption.anchor); + if (ship != null) + motion = VectorConversionsMCKt.toMinecraft(ship.getShipToWorld().transformDirection(VectorConversionsMCKt.toJOML(motion), new Vector3d())); + } + instance.setDeltaMovement(motion); + } + //Region end +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinFilteringBehaviour.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinFilteringBehaviour.java new file mode 100644 index 000000000..ae9e47bd8 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinFilteringBehaviour.java @@ -0,0 +1,43 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.behaviour; + +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(FilteringBehaviour.class) +public class MixinFilteringBehaviour { + @Redirect( + method = "testHit", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/phys/Vec3;subtract(Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;" + ) + ) + public Vec3 redirectSubtract(Vec3 instance, Vec3 vec) { + Level level = ((FilteringBehaviour) (Object) this).getWorld(); + + Vec3 pos1 = instance; + Vec3 pos2 = vec; + + if (level != null) { + Ship ship1 = VSGameUtilsKt.getShipManagingPos(level, pos1.x, pos1.y, pos1.z); + Ship ship2 = VSGameUtilsKt.getShipManagingPos(level, pos2.x, pos2.y, pos2.z); + if (ship1 != null && ship2 == null) { + pos2 = VectorConversionsMCKt.toMinecraft( + ship1.getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(pos2)) + ); + } else if (ship1 == null && ship2 != null) { + pos1 = VectorConversionsMCKt.toMinecraft( + ship2.getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(pos1)) + ); + } + } + return pos1.subtract(pos2); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinLinkBehaviour.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinLinkBehaviour.java new file mode 100644 index 000000000..5abbba6d8 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinLinkBehaviour.java @@ -0,0 +1,43 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.behaviour; + +import com.simibubi.create.content.redstone.link.LinkBehaviour; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(LinkBehaviour.class) +public class MixinLinkBehaviour { + @Redirect( + method = "testHit", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/phys/Vec3;subtract(Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;" + ) + ) + public Vec3 redirectSubtract(Vec3 instance, Vec3 vec) { + Level level = ((LinkBehaviour) (Object) this).getWorld(); + + Vec3 pos1 = instance; + Vec3 pos2 = vec; + + if (level != null) { + Ship ship1 = VSGameUtilsKt.getShipManagingPos(level, pos1.x, pos1.y, pos1.z); + Ship ship2 = VSGameUtilsKt.getShipManagingPos(level, pos2.x, pos2.y, pos2.z); + if (ship1 != null && ship2 == null) { + pos2 = VectorConversionsMCKt.toMinecraft( + ship1.getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(pos2)) + ); + } else if (ship1 == null && ship2 != null) { + pos1 = VectorConversionsMCKt.toMinecraft( + ship2.getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(pos1)) + ); + } + } + return pos1.subtract(pos2); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinScrollValueBehaviour.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinScrollValueBehaviour.java new file mode 100644 index 000000000..fc052d56d --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinScrollValueBehaviour.java @@ -0,0 +1,45 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.behaviour; + +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(ScrollValueBehaviour.class) +public class MixinScrollValueBehaviour { + + @Redirect( + method = "testHit", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/phys/Vec3;subtract(Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;" + ) + ) + public Vec3 redirectSubtract(Vec3 instance, Vec3 vec) { + Level level = ((ScrollValueBehaviour) (Object) this).getWorld(); + + Vec3 pos1 = instance; + Vec3 pos2 = vec; + + if (level != null) { + Ship ship1 = VSGameUtilsKt.getShipManagingPos(level, pos1.x, pos1.y, pos1.z); + Ship ship2 = VSGameUtilsKt.getShipManagingPos(level, pos2.x, pos2.y, pos2.z); + if (ship1 != null && ship2 == null) { + pos2 = VectorConversionsMCKt.toMinecraft( + ship1.getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(pos2)) + ); + } else if (ship1 == null && ship2 != null) { + pos1 = VectorConversionsMCKt.toMinecraft( + ship2.getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(pos1)) + ); + } + } + return pos1.subtract(pos2); + } +} + diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinSidedFilteringBehaviour.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinSidedFilteringBehaviour.java new file mode 100644 index 000000000..a9f3fee09 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/behaviour/MixinSidedFilteringBehaviour.java @@ -0,0 +1,39 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.behaviour; + +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.SidedFilteringBehaviour; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(SidedFilteringBehaviour.class) +public class MixinSidedFilteringBehaviour { + @Redirect( + method = "testHit", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/phys/Vec3;subtract(Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;" + ) + ) + public Vec3 redirectSubtract(Vec3 instance, Vec3 vec) { + Level level = ((SidedFilteringBehaviour) (Object) this).getWorld(); + + Vec3 pos1 = instance; + Vec3 pos2 = vec; + + if (level != null) { + Ship ship1 = VSGameUtilsKt.getShipManagingPos(level, pos1.x, pos1.y, pos1.z); + Ship ship2 = VSGameUtilsKt.getShipManagingPos(level, pos2.x, pos2.y, pos2.z); + if (ship1 != null && ship2 == null) { + pos2 = VectorConversionsMCKt.toMinecraft(ship1.getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(pos2))); + } else if (ship1 == null && ship2 != null) { + pos1 = VectorConversionsMCKt.toMinecraft(ship2.getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(pos1))); + } + } + return pos1.subtract(pos2); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinCrushingWheelBlock.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinCrushingWheelBlock.java new file mode 100644 index 000000000..067725275 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinCrushingWheelBlock.java @@ -0,0 +1,81 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.block; + +import com.simibubi.create.content.kinetics.crusher.CrushingWheelBlock; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(CrushingWheelBlock.class) +public class MixinCrushingWheelBlock { + + @Unique + private BlockPos blockPosInside; + @Unique + private Level levelInside; + + @Inject(method = "entityInside", at = @At("HEAD")) + void startInside( + final BlockState state, final Level worldIn, final BlockPos pos, final Entity entityIn, + final CallbackInfo info) { + blockPosInside = pos; + levelInside = worldIn; + } + + @Unique + void transform(final Vector3d in) { + final Ship ship = VSGameUtilsKt.getShipManagingPos(levelInside, blockPosInside); + if (ship != null) { + ship.getWorldToShip().transformPosition(in); + } + } + + @Redirect( + method = "entityInside", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/Entity;getX()D" + ) + ) + double getXPos(final Entity entity) { + final Vector3d vector3d = new Vector3d(entity.getX(), entity.getY(), entity.getZ()); + transform(vector3d); + return vector3d.x; + } + + @Redirect( + method = "entityInside", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/Entity;getY()D" + ) + ) + double getYPos(final Entity entity) { + final Vector3d vector3d = new Vector3d(entity.getX(), entity.getY(), entity.getZ()); + transform(vector3d); + return vector3d.x; + } + + @Redirect( + method = "entityInside", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/Entity;getZ()D" + ) + ) + double getZPos(final Entity entity) { + final Vector3d vector3d = new Vector3d(entity.getX(), entity.getY(), entity.getZ()); + transform(vector3d); + return vector3d.x; + } + +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinEjectorBlock.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinEjectorBlock.java new file mode 100644 index 000000000..f7af92f2a --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinEjectorBlock.java @@ -0,0 +1,53 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.block; + +import com.simibubi.create.content.logistics.depot.EjectorBlock; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(EjectorBlock.class) +public abstract class MixinEjectorBlock { + @Redirect(method = "updateEntityAfterFallOn", at = @At( + value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;blockPosition()Lnet/minecraft/core/BlockPos;" + )) + private BlockPos redirectBlockPosition(Entity instance) { + return instance.getOnPos(); + } + + @Redirect(method = "updateEntityAfterFallOn", at = @At( + value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;position()Lnet/minecraft/world/phys/Vec3;" + )) + private Vec3 redirectEntityPosition(Entity instance) { + Vec3 result = instance.position(); + if (VSGameUtilsKt.getShipManagingPos(instance.level(), instance.position()) == null) { + Ship ship = VSGameUtilsKt.getShipManagingPos(instance.level(), instance.getOnPos()); + if (ship != null) { + Vector3d tempVec = VectorConversionsMCKt.toJOML(result); + ship.getWorldToShip().transformPosition(tempVec, tempVec); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + } + return result; + } + + @Redirect(method = "updateEntityAfterFallOn", at = @At( + value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setPos(DDD)V" + )) + private void redirectSetPos(Entity instance, double x, double y, double z) { + Ship ship = VSGameUtilsKt.getShipManagingPos(instance.level(), instance.getOnPos()); + if (ship != null) { + Vector3d tempVec = new Vector3d(); + ship.getTransform().getShipToWorld().transformPosition(x, y, z, tempVec); + instance.setPos(tempVec.x, tempVec.y, tempVec.z); + } else { + instance.setPos(x, y, z); + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinRedstoneContactBlock.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinRedstoneContactBlock.java new file mode 100644 index 000000000..d87b25a06 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinRedstoneContactBlock.java @@ -0,0 +1,132 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.block; + +import static org.valkyrienskies.mod.common.util.VectorConversionsMCKt.toJOML; + +import com.mojang.datafixers.util.Pair; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.redstone.contact.RedstoneContactBlock; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.ticks.TickPriority; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(RedstoneContactBlock.class) +public abstract class MixinRedstoneContactBlock extends WrenchableDirectionalBlock { + + private static Map, BlockPos> contactCache = new HashMap<>(); + + @Shadow + @Final + public static BooleanProperty POWERED; + @Unique + private static final double MAX_ALIGNMENT_ANGLE = -0.93972176; //Mth.cos(20*(Mth.DEG_TO_RAD)) + + public MixinRedstoneContactBlock(Properties properties) { + super(properties); + } + + @Inject(method = "onRemove", at = @At("HEAD")) + private void injectOnRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving, CallbackInfo ci) { + if (state.getBlock() == this && newState.isAir()) { + Pair key = Pair.of(worldIn, pos); + if (state.getValue(POWERED) && contactCache.containsKey(key)) { + worldIn.scheduleTick(contactCache.get(key), AllBlocks.REDSTONE_CONTACT.get(), 2, TickPriority.NORMAL); + contactCache.remove(key); + } + } + } + + @Inject(method = "tick", at = @At(value = "INVOKE_ASSIGN", shift = At.Shift.BY, by = 2, target = "Lcom/simibubi/create/content/redstone/contact/RedstoneContactBlock;hasValidContact(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;)Z"), locals = LocalCapture.CAPTURE_FAILHARD) + private void injectTick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random, CallbackInfo ci, boolean hasValidContact) { + if (VSGameUtilsKt.isBlockInShipyard(worldIn, pos)) { + Pair key = Pair.of(worldIn, pos); + if (!hasValidContact && state.getValue(POWERED) && contactCache.containsKey(key)) { + worldIn.scheduleTick(contactCache.get(key), AllBlocks.REDSTONE_CONTACT.get(), 2, TickPriority.NORMAL); + contactCache.remove(key); + } + worldIn.scheduleTick(pos, AllBlocks.REDSTONE_CONTACT.get(), 2, TickPriority.NORMAL); + } + } + + @Unique + private static boolean hasContact(Level world, Ship ship, Vector3d searchPos, Direction direction, Ship shipItr) { + BlockState blockState = world.getBlockState(BlockPos.containing(VectorConversionsMCKt.toMinecraft(searchPos))); + if (AllBlocks.REDSTONE_CONTACT.has(blockState)) { + Vector3d worldDirection = toJOML(Vec3.atLowerCornerOf(direction.getNormal())); + Vector3d targetDirection = toJOML(Vec3.atLowerCornerOf(blockState.getValue(FACING).getNormal())); + if (ship != null) { + ship.getShipToWorld().transformDirection(worldDirection, worldDirection); + } + if (shipItr != null) { + shipItr.getShipToWorld().transformDirection(targetDirection, targetDirection); + } + double dotAngle = worldDirection.dot(targetDirection); + return dotAngle < MAX_ALIGNMENT_ANGLE; + } + return false; + } + + @Inject(method = "hasValidContact", at = @At("RETURN"), cancellable = true) + private static void injectHasValidContact(LevelAccessor world, BlockPos pos, Direction direction, CallbackInfoReturnable cir) { + boolean result = false; + Level worldLevel = (Level) world; + BlockState blockState = world.getBlockState(pos.relative(direction)); + if (AllBlocks.REDSTONE_CONTACT.has(blockState)) { + cir.setReturnValue(blockState.getValue(FACING) == direction.getOpposite()); + } else { + + AABB searchAABB = new AABB(pos.relative(direction)); + Vector3d searchPos = toJOML(Vec3.atCenterOf(pos.relative(direction))); + Ship ship = VSGameUtilsKt.getShipManagingPos(worldLevel, pos); + if (VSGameUtilsKt.isBlockInShipyard(worldLevel, pos) && ship != null) { + Vector3d tempVec = toJOML(Vec3.atCenterOf(pos.relative(direction))); + searchPos = ship.getShipToWorld().transformPosition(tempVec, new Vector3d()); + ship.getShipToWorld().transformPosition(tempVec, tempVec); + double bounds = 0.25; + searchAABB = new AABB(tempVec.x - bounds, tempVec.y - bounds, tempVec.z - bounds, + tempVec.x + bounds, tempVec.y + bounds, tempVec.z + bounds); + + result = hasContact(worldLevel, ship, searchPos, direction, null); + } + Iterator ships = VSGameUtilsKt.getShipsIntersecting(worldLevel, searchAABB).iterator(); + if (ships.hasNext() && !result) { + do { + Ship shipItr = ships.next(); + if (shipItr == ship) continue; + Vector3d newSearchPos = shipItr.getWorldToShip().transformPosition(searchPos, new Vector3d()); + result = hasContact(worldLevel, ship, newSearchPos, direction, shipItr); + if (result) searchPos = newSearchPos; + } while (ships.hasNext() && !result); + } + if (result) { + contactCache.put(Pair.of(worldLevel, pos), BlockPos.containing(VectorConversionsMCKt.toMinecraft(searchPos))); + world.scheduleTick(BlockPos.containing(VectorConversionsMCKt.toMinecraft(searchPos)), AllBlocks.REDSTONE_CONTACT.get(), 2, TickPriority.NORMAL); + } + cir.setReturnValue(result); + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinStickerBlock.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinStickerBlock.java new file mode 100644 index 000000000..b939eed99 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/block/MixinStickerBlock.java @@ -0,0 +1,41 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.block; + +import com.simibubi.create.content.contraptions.chassis.StickerBlock; +import com.simibubi.create.content.contraptions.chassis.StickerBlockEntity; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.mod.mixinducks.mod_compat.create.IMixinStickerTileEntity; + +@Mixin(StickerBlock.class) +public abstract class MixinStickerBlock extends WrenchableDirectionalBlock implements IBE { + + public MixinStickerBlock(Properties properties) { + super(properties); + } + + @Override + public void onRemove(@NotNull BlockState state, @NotNull Level world, @NotNull BlockPos pos, @NotNull BlockState newState, boolean isMoving) { + IBE.onRemove(state, world, pos, newState); + } + + @Inject(method = "neighborChanged", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;getValue(Lnet/minecraft/world/level/block/state/properties/Property;)Ljava/lang/Comparable;", ordinal = 0), cancellable = true) + private void injectNeighbourChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving, CallbackInfo ci) { + StickerBlockEntity ste = getBlockEntity(worldIn, pos); + if (ste != null && ((IMixinStickerTileEntity) ste).isAlreadyPowered(false)) { + if (!worldIn.hasNeighborSignal(pos)) { + ci.cancel(); + } else { + ((IMixinStickerTileEntity) ste).isAlreadyPowered(true); + } + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/IMixinMechanicalBearingTileEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/IMixinMechanicalBearingTileEntity.java new file mode 100644 index 000000000..a27061283 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/IMixinMechanicalBearingTileEntity.java @@ -0,0 +1,10 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.blockentity; + +import com.simibubi.create.content.contraptions.bearing.MechanicalBearingBlockEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(MechanicalBearingBlockEntity.class) +public interface IMixinMechanicalBearingTileEntity { + @Accessor boolean isAssembleNextTick(); +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/MixinCrushingWheelControllerTileEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/MixinCrushingWheelControllerTileEntity.java new file mode 100644 index 000000000..6bbbe1c1a --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/MixinCrushingWheelControllerTileEntity.java @@ -0,0 +1,114 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.blockentity; + +import com.simibubi.create.content.kinetics.crusher.CrushingWheelControllerBlock; +import com.simibubi.create.content.kinetics.crusher.CrushingWheelControllerBlockEntity; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.function.Predicate; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.joml.primitives.AABBd; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(CrushingWheelControllerBlockEntity.class) +public abstract class MixinCrushingWheelControllerTileEntity { + + @Shadow + public float crushingspeed; + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntities(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;)Ljava/util/List;")) + private List redirectBounds(Level instance, Entity entity, AABB area, Predicate predicate) { + if (instance != null) { + area = VSGameUtilsKt.transformAabbToWorld(instance, area); + return instance.getEntities(entity, area, predicate); + } + return new ArrayList(); + } + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/AABB;intersects(Lnet/minecraft/world/phys/AABB;)Z")) + private boolean redirectIntersects(AABB instance, AABB other) { + Level level = ((CrushingWheelControllerBlockEntity) (Object) this).getLevel(); + if (level != null) { + Iterator ships = VSGameUtilsKt.getShipsIntersecting(level, instance).iterator(); + if (ships.hasNext()) { + AABBd result = new AABBd(); + VectorConversionsMCKt.toJOML(instance).transform(ships.next().getTransform().getWorldToShip(), result); + instance = VectorConversionsMCKt.toMinecraft(result); + } + } + return instance.intersects(other); + } + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V")) + private void redirectSetDeltaMovement(Entity instance, Vec3 motion) { + + BlockPos worldPosition = ((CrushingWheelControllerBlockEntity) (Object) this).getBlockPos(); + Direction facing = ((CrushingWheelControllerBlockEntity) (Object) this) + .getBlockState().getValue(CrushingWheelControllerBlock.FACING); + Vec3 transformedPos = getTransformedPosition(instance); + double xMotion = ((worldPosition.getX() + .5) - transformedPos.x) / 2; + double zMotion = ((worldPosition.getZ() + .5) - transformedPos.z) / 2; + + if (instance.isShiftKeyDown()) + xMotion = zMotion = 0; + double movement = Math.max(-(this.crushingspeed * 4) / 4f, -.5f) * -facing.getAxisDirection().getStep(); + + Vec3 transformedDirection = directionShip2World(instance, + new Vec3( + facing.getAxis() == Direction.Axis.X ? movement : xMotion, + facing.getAxis() == Direction.Axis.Y ? movement : 0f, + facing.getAxis() == Direction.Axis.Z ? movement : zMotion + )); + + instance.setDeltaMovement(transformedDirection); + } + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getX()D")) + private double redirectEntityGetX(Entity instance) { + return getTransformedPosition(instance).x; + } + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getY()D")) + private double redirectEntityGetY(Entity instance) { + return getTransformedPosition(instance).y; + } + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getZ()D")) + private double redirectEntityGetZ(Entity instance) { + return getTransformedPosition(instance).z; + } + + private Vec3 getTransformedPosition(Entity instance) { + Vec3 result = instance.position(); + Ship ship = VSGameUtilsKt.getShipManagingPos(instance.level(), ((CrushingWheelControllerBlockEntity) (Object) this).getBlockPos()); + if (ship != null) { + Vector3d tempVec = new Vector3d(); + ship.getTransform().getWorldToShip().transformPosition(result.x, result.y, result.z, tempVec); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + return result; + } + + private Vec3 directionShip2World(Entity instance, Vec3 direction) { + Vec3 result = direction; + Ship ship = VSGameUtilsKt.getShipManagingPos(instance.level(), ((CrushingWheelControllerBlockEntity) (Object) this).getBlockPos()); + if (ship != null) { + Vector3d tempVec = new Vector3d(); + ship.getTransform().getShipToWorld().transformDirection(result.x, result.y, result.z, tempVec); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + return result; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/MixinEjectorTileEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/MixinEjectorTileEntity.java new file mode 100644 index 000000000..1504ce54e --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/MixinEjectorTileEntity.java @@ -0,0 +1,69 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.blockentity; + +import com.simibubi.create.content.logistics.depot.EjectorBlockEntity; +import java.util.List; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(EjectorBlockEntity.class) +public abstract class MixinEjectorTileEntity { + @ModifyVariable(method = "*", at = @At("STORE"), name = "ejectVec") + private Vec3 modEjectVec(Vec3 ejectVec) { + Vec3 result = ejectVec; + Level level = ((EjectorBlockEntity) (Object) this).getLevel(); + if (level != null) { + Ship ship = VSGameUtilsKt.getShipManagingPos(level, ((EjectorBlockEntity) (Object) this).getBlockPos()); + if (ship != null) { + Vector3d tempVec = new Vector3d(); + ship.getTransform().getShipToWorld().transformPosition(result.x, result.y, result.z, tempVec); + result = new Vec3(tempVec.x, tempVec.y, tempVec.z); + } + } + return result; + } + + @ModifyVariable(method = "*", at = @At("STORE"), name = "ejectMotionVec") + private Vec3 modEjectMotionVec(Vec3 ejectMotionVec) { + Vec3 result = ejectMotionVec; + Level level = ((EjectorBlockEntity) (Object) this).getLevel(); + if (level != null) { + Ship ship = VSGameUtilsKt.getShipManagingPos(level, ((EjectorBlockEntity) (Object) this).getBlockPos()); + if (ship != null) { + Vector3d tempVec = new Vector3d(); + ship.getTransform().getShipToWorld().transformDirection(result.x, result.y, result.z, tempVec); + result = new Vec3(tempVec.x, tempVec.y, tempVec.z); + } + } + return result; + } + + @Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")) + private List redirectGetEntitiesOfClass(Level instance, Class aClass, AABB aabb) { + return instance.getEntitiesOfClass(aClass, VSGameUtilsKt.transformAabbToWorld(instance, aabb)); + } + + @Redirect(method = "activateDeferred", at = @At( + value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setPos(DDD)V" + )) + private void redirectSetPos(Entity instance, double x, double y, double z) { + Ship ship = VSGameUtilsKt.getShipManagingPos(instance.level(), ((EjectorBlockEntity) (Object) this).getBlockPos()); + if (ship != null) { + BlockPos temp = ((EjectorBlockEntity) (Object) this).getBlockPos(); + Vector3d tempVec = new Vector3d(temp.getX() + .5, temp.getY() + 1, temp.getZ() + .5); + ship.getTransform().getShipToWorld().transformPosition(tempVec, tempVec); + instance.setPos(tempVec.x, tempVec.y, tempVec.z); + } else { + instance.setPos(x, y, z); + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/MixinEncasedFanTileEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/MixinEncasedFanTileEntity.java new file mode 100644 index 000000000..2c317a400 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/blockentity/MixinEncasedFanTileEntity.java @@ -0,0 +1,37 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.blockentity; + +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.fan.EncasedFanBlockEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.mixinducks.mod_compat.create.IExtendedAirCurrentSource; + +@Mixin(EncasedFanBlockEntity.class) +public abstract class MixinEncasedFanTileEntity extends KineticBlockEntity implements IExtendedAirCurrentSource { + @Unique + private Ship ship = null; + + public MixinEncasedFanTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + } + + @Override + public void setLevel(@NotNull Level level) { + super.setLevel(level); + ship = VSGameUtilsKt.getShipManagingPos(level, getBlockPos()); + } + + @Override + public Ship getShip() { + return ship; + } + + +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/cannons/MixinCannonMount.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/cannons/MixinCannonMount.java new file mode 100644 index 000000000..593834577 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/cannons/MixinCannonMount.java @@ -0,0 +1,152 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.cannons; + +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import org.joml.Vector3d; +import org.joml.Vector3dc; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.LoadedServerShip; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; +import rbasamoyai.createbigcannons.cannon_control.ControlPitchContraption; +import rbasamoyai.createbigcannons.cannon_control.cannon_mount.CannonMountBlockEntity; + +@Mixin(CannonMountBlockEntity.class) +public abstract class MixinCannonMount extends KineticBlockEntity implements ControlPitchContraption.Block { + + private Integer cannonID = null; + private boolean alreadyAdded = false; + + Vector3d recoilVec = null; + double recoilForce = 0; + + public MixinCannonMount(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + } + + /*TODO? + @Override + public void cacheRecoilVector(Vec3 vector, AbstractContraptionEntity cannon) { + recoilVec = VectorConversionsMCKt.toJOML(vector); + } + */ + + @Unique + private void handleAssembly() { + LoadedServerShip ship = null; + if (!level.isClientSide) { + if (VSGameUtilsKt.getShipObjectManagingPos(level, getBlockPos()) != null) { + ship = VSGameUtilsKt.getShipObjectManagingPos((ServerLevel) level, getBlockPos()); + } + } + + if (ship != null) { + if (!alreadyAdded && cannonID == null) { + Vector3dc pos = VectorConversionsMCKt.toJOMLD(worldPosition); + //final CannonCreateData data = new CannonCreateData(pos); + //cannonID = CannonController.getOrCreate(ship).addCannon(data); + alreadyAdded = true; + } + } + } + + @Unique + private void handleDisassembly() { + LoadedServerShip ship = null; + if (!level.isClientSide) { + if (VSGameUtilsKt.getShipObjectManagingPos(level, getBlockPos()) != null) { + ship = VSGameUtilsKt.getShipObjectManagingPos((ServerLevel) level, getBlockPos()); + } + } + if (cannonID != null) { + //CannonController.getOrCreate(ship).removeCannon(cannonID); + cannonID = null; + alreadyAdded = false; + recoilVec = null; + } + + } + + @Unique + private void handleController() { + //do stuff here (I like to have the inject call to a separate function so the breakpoint will work properly for this function) + + LoadedServerShip ship = null; + if (!level.isClientSide) { + if (VSGameUtilsKt.getShipObjectManagingPos(level, getBlockPos()) != null) { + ship = VSGameUtilsKt.getShipObjectManagingPos((ServerLevel) level, getBlockPos()); + } + } + if (ship != null) { + if (alreadyAdded && cannonID != null) { + if (recoilVec != null) { + //final CannonUpdateData data = new CannonUpdateData(recoilVec); + //CannonController.getOrCreate(ship).updateCannon(cannonID, data); + } + } + if (this.isRemoved()) { + if (cannonID != null) { + //CannonController.getOrCreate(ship).removeCannon(cannonID); + cannonID = null; + alreadyAdded = false; + } + } + } + } + @Inject(method = "tick", at = @At("HEAD"), remap = false) + private void injectTick(CallbackInfo ci) { + handleController(); + } + + @Inject(method = "assemble", at = @At("RETURN"), remap = false) + private void injectAssemble(CallbackInfo ci) { + handleAssembly(); + } + + @Inject(method = "disassemble", at = @At("HEAD"), remap = false) + private void injectDisassemble(CallbackInfo ci) { + handleDisassembly(); + } + + @Unique + private CompoundTag writeToCompound(CompoundTag compound, boolean clientPacket){ + //write here + compound.putBoolean("alreadyAdded", alreadyAdded); + if (cannonID != null) { + compound.putInt("cannonID", cannonID); + } + return compound; + } + @Inject(method = "write", at = @At("HEAD"), cancellable = true, remap = false) + private void injectWrite(CompoundTag compound, boolean clientPacket, CallbackInfo ci) { + compound = writeToCompound(compound,clientPacket); + super.write(compound, clientPacket); + ci.cancel(); + } + + @Unique + private CompoundTag readFromCompound(CompoundTag compound, boolean clientPacket){ + //read (and remove before it passes up?) here + alreadyAdded = compound.getBoolean("alreadyAdded"); + if (compound.contains("cannonID")) { + cannonID = compound.getInt("cannonID"); + } + return compound; + } + @Inject(method = "read", at = @At("HEAD"), cancellable = true, remap = false) + private void injectRead(CompoundTag compound, boolean clientPacket, CallbackInfo ci) { + compound = readFromCompound(compound,clientPacket); + super.read(compound, clientPacket); + ci.cancel(); + } + +} + diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinAABBOutline.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinAABBOutline.java new file mode 100644 index 000000000..e0ef100a8 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinAABBOutline.java @@ -0,0 +1,76 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.foundation.outliner.AABBOutline; +import com.simibubi.create.foundation.outliner.Outline; +import com.simibubi.create.foundation.render.RenderTypes; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import net.minecraft.client.Minecraft; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3dc; +import org.joml.Vector3f; +import org.joml.Vector4f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.core.api.ships.properties.ShipTransform; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; +import org.valkyrienskies.mod.mixin.mod_compat.create.accessors.OutlineParamsAccessor; + +@Mixin(AABBOutline.class) +public abstract class MixinAABBOutline extends Outline { + @Shadow + protected abstract void renderBoxFaces(PoseStack ms, SuperRenderTypeBuffer buffer, boolean cull, Direction highlightedFace, Vector3f minPos, Vector3f maxPos, Vector4f color, int lightmap); + + @Shadow + protected abstract void renderBoxEdges(PoseStack ms, VertexConsumer consumer, Vector3f minPos, Vector3f maxPos, float lineWidth, Vector4f color, int lightmap, boolean disableNormals); + + @Inject(method = "renderBox", at = @At("HEAD"), cancellable = true) + private void preRenderBox(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera, AABB box, Vector4f color, int lightmap, boolean disableLineNormals, CallbackInfo ci) { + final Level level = Minecraft.getInstance().level; + if (level != null) { + final Vector3dc average = VectorConversionsMCKt.toJOML(box.getCenter()); + final ClientShip ship = (ClientShip) VSGameUtilsKt.getShipManagingPos(level, average); + if (ship != null) { + final ShipTransform renderTransform = ship.getRenderTransform(); + Vector3f minPos = new Vector3f(); + Vector3f maxPos = new Vector3f(); + + final Vector3dc cameraInShip = renderTransform.getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(camera)); + + boolean cameraInside = box.contains(VectorConversionsMCKt.toMinecraft(cameraInShip)); + boolean cull = !cameraInside && !((OutlineParamsAccessor) params).getDisableCull(); + float inflate = cameraInside ? -1 / 128f : 1 / 128f; + + final AABB boxRelShipCenter = box.move(-renderTransform.getPositionInShip().x(), -renderTransform.getPositionInShip().y(), -renderTransform.getPositionInShip().z()); + + minPos.set((float) boxRelShipCenter.minX - inflate, (float) boxRelShipCenter.minY - inflate, (float) boxRelShipCenter.minZ - inflate); + maxPos.set((float) boxRelShipCenter.maxX + inflate, (float) boxRelShipCenter.maxY + inflate, (float) boxRelShipCenter.maxZ + inflate); + + ms.pushPose(); + ms.translate(renderTransform.getPositionInWorld().x() - camera.x, renderTransform.getPositionInWorld().y() - camera.y, renderTransform.getPositionInWorld().z() - camera.z); + ms.scale((float) renderTransform.getShipToWorldScaling().x(), (float) renderTransform.getShipToWorldScaling().y(), (float) renderTransform.getShipToWorldScaling().z()); + ms.mulPose(VectorConversionsMCKt.toFloat(renderTransform.getShipToWorldRotation())); + renderBoxFaces(ms, buffer, cull, params.getHighlightedFace(), minPos, maxPos, color, lightmap); + + float lineWidth = params.getLineWidth(); + if (lineWidth == 0) + return; + + VertexConsumer consumer = buffer.getBuffer(RenderTypes.getOutlineSolid()); + renderBoxEdges(ms, consumer, minPos, maxPos, lineWidth, color, lightmap, disableLineNormals); + + ms.popPose(); + ci.cancel(); + } + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinBlockClusterOutline.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinBlockClusterOutline.java new file mode 100644 index 000000000..f47164dcb --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinBlockClusterOutline.java @@ -0,0 +1,152 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllSpecialTextures; +import com.simibubi.create.foundation.outliner.BlockClusterOutline; +import com.simibubi.create.foundation.outliner.Outline; +import com.simibubi.create.foundation.render.RenderTypes; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import java.util.Iterator; +import java.util.Optional; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3f; +import org.joml.Vector4f; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.core.api.ships.properties.ShipTransform; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; +import org.valkyrienskies.mod.mixin.mod_compat.create.accessors.OutlineParamsAccessor; +import org.valkyrienskies.mod.mixinducks.mod_compat.create.CWCluster; + +@Mixin(BlockClusterOutline.class) +public abstract class MixinBlockClusterOutline extends Outline { + @Unique + private CWCluster cw$cluster = null; + + @Shadow + @Final + protected Vector3f originTemp; + + @Shadow + protected abstract void bufferBlockFace(PoseStack.Pose pose, VertexConsumer consumer, BlockPos pos, Direction face, Vector4f color, int lightmap); + + @Inject(method = "", at = @At("RETURN")) + private void postInit(final Iterable positions, final CallbackInfo ci) { + final Iterator iterator = positions.iterator(); + final BlockPos firstPos = iterator.hasNext() ? iterator.next() : null; + if (firstPos != null) { + final Level level = Minecraft.getInstance().level; + if (level != null && VSGameUtilsKt.getShipManagingPos(level, firstPos) != null) { + // Only generate cw$cluster if we're on a ship + cw$cluster = new CWCluster(); + positions.forEach(cw$cluster::include); + } + } + } + + @Inject(method = "renderFaces", at = @At("HEAD"), cancellable = true) + private void preRenderFaces(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera, float pt, Vector4f color, int lightmap, CallbackInfo ci) { + if (cw$cluster != null) { + final BlockPos anchorPos = cw$cluster.anchor; + if (anchorPos == null) { + return; + } + final Level level = Minecraft.getInstance().level; + final ClientShip ship = (ClientShip) VSGameUtilsKt.getShipManagingPos(level, anchorPos); + if (ship != null) { + Optional optionalFaceTexture = ((OutlineParamsAccessor) params).getFaceTexture(); + if (optionalFaceTexture.isEmpty()) + return; + + final ShipTransform renderTransform = ship.getRenderTransform(); + + ms.pushPose(); + ms.translate(renderTransform.getPositionInWorld().x() - camera.x, renderTransform.getPositionInWorld().y() - camera.y, renderTransform.getPositionInWorld().z() - camera.z); + ms.scale((float) renderTransform.getShipToWorldScaling().x(), (float) renderTransform.getShipToWorldScaling().y(), (float) renderTransform.getShipToWorldScaling().z()); + ms.mulPose(VectorConversionsMCKt.toFloat(renderTransform.getShipToWorldRotation())); + ms.translate( + cw$cluster.anchor.getX() - renderTransform.getPositionInShip().x(), + cw$cluster.anchor.getY() - renderTransform.getPositionInShip().y(), + cw$cluster.anchor.getZ() - renderTransform.getPositionInShip().z() + ); + + AllSpecialTextures faceTexture = optionalFaceTexture.get(); + PoseStack.Pose pose = ms.last(); + RenderType renderType = RenderTypes.getOutlineTranslucent(faceTexture.getLocation(), true); + VertexConsumer consumer = buffer.getLateBuffer(renderType); + + cw$cluster.visibleFaces.forEach((face, axisDirection) -> { + Direction direction = Direction.get(axisDirection, face.axis); + BlockPos pos = face.pos; + if (axisDirection == Direction.AxisDirection.POSITIVE) + pos = pos.relative(direction.getOpposite()); + + bufferBlockFace(pose, consumer, pos, direction, color, lightmap); + }); + + ms.popPose(); + ci.cancel(); + } + } + } + + @Inject(method = "renderEdges", at = @At("HEAD"), cancellable = true) + private void preRenderEdges(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera, float pt, Vector4f color, int lightmap, boolean disableNormals, CallbackInfo ci) { + if (cw$cluster != null) { + final BlockPos anchorPos = cw$cluster.anchor; + if (anchorPos == null) { + return; + } + final Level level = Minecraft.getInstance().level; + final ClientShip ship = (ClientShip) VSGameUtilsKt.getShipManagingPos(level, anchorPos); + if (ship != null) { + float lineWidth = params.getLineWidth(); + if (lineWidth == 0) + return; + if (cw$cluster.isEmpty()) + return; + + final ShipTransform renderTransform = ship.getRenderTransform(); + + ms.pushPose(); + ms.translate(renderTransform.getPositionInWorld().x() - camera.x, renderTransform.getPositionInWorld().y() - camera.y, renderTransform.getPositionInWorld().z() - camera.z); + ms.scale((float) renderTransform.getShipToWorldScaling().x(), (float) renderTransform.getShipToWorldScaling().y(), (float) renderTransform.getShipToWorldScaling().z()); + ms.mulPose(VectorConversionsMCKt.toFloat(renderTransform.getShipToWorldRotation())); + ms.translate( + cw$cluster.anchor.getX() - renderTransform.getPositionInShip().x(), + cw$cluster.anchor.getY() - renderTransform.getPositionInShip().y(), + cw$cluster.anchor.getZ() - renderTransform.getPositionInShip().z() + ); + + PoseStack.Pose pose = ms.last(); + VertexConsumer consumer = buffer.getBuffer(RenderTypes.getOutlineSolid()); + + cw$cluster.visibleEdges.forEach(edge -> { + BlockPos pos = edge.pos; + Vector3f origin = originTemp; + origin.set(pos.getX(), pos.getY(), pos.getZ()); + Direction direction = Direction.get(Direction.AxisDirection.POSITIVE, edge.axis); + bufferCuboidLine(pose, consumer, origin, direction, 1, lineWidth, color, lightmap, disableNormals); + }); + + ms.popPose(); + + ci.cancel(); + } + } + } +} + diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinCarriageContraptionInstance.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinCarriageContraptionInstance.java new file mode 100644 index 000000000..ce5aa7f14 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinCarriageContraptionInstance.java @@ -0,0 +1,68 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance; +import com.jozufozu.flywheel.util.AnimationTickHolder; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.CarriageContraptionInstance; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.joml.Matrix4d; +import org.joml.Matrix4f; +import org.joml.Vector3d; +import org.joml.Vector3f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.core.api.ships.properties.ShipTransform; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(CarriageContraptionInstance.class) +public abstract class MixinCarriageContraptionInstance extends EntityInstance { + + public MixinCarriageContraptionInstance(MaterialManager materialManager, Entity entity) { + super(materialManager, entity); + } + + @WrapOperation(remap = false, + method = "beginFrame", at = @At(value = "INVOKE", + target = "Lcom/jozufozu/flywheel/util/transform/TransformStack;translate(Lorg/joml/Vector3f;)Ljava/lang/Object;") + ) + private Object redirectTranslate(final TransformStack instance, final Vector3f vector3f, Operation operation) { + + final float partialTicks = AnimationTickHolder.getPartialTicks(); + final Level level = this.world; + final ClientShip ship = + (ClientShip) VSGameUtilsKt.getShipObjectManagingPos(level, vector3f.x(), vector3f.y(), vector3f.z()); + + if (ship != null) { + final CarriageContraptionEntity carriageContraptionEntity = (CarriageContraptionEntity) this.entity; + final Vector3d origin = VectorConversionsMCKt.toJOMLD(this.materialManager.getOriginCoordinate()); + final Vec3 pos = carriageContraptionEntity.position(); + final Vector3d newPosition = + new Vector3d( + Mth.lerp(partialTicks, carriageContraptionEntity.xOld, pos.x), + Mth.lerp(partialTicks, carriageContraptionEntity.yOld, pos.y), + Mth.lerp(partialTicks, carriageContraptionEntity.zOld, pos.z) + ); + final ShipTransform transform = ship.getRenderTransform(); + Matrix4d renderMatrix = new Matrix4d() + .translate(origin.mul(-1)) + .mul(transform.getShipToWorld()) + .translate(newPosition); + Matrix4f mat4f = new Matrix4f(renderMatrix); + ((PoseStack) instance).last().pose().mul(mat4f); + } else { + operation.call(instance, vector3f); + //instance.translate(vector3f); + } + return null; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinCogwheelBlockItem.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinCogwheelBlockItem.java new file mode 100644 index 000000000..644e81581 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinCogwheelBlockItem.java @@ -0,0 +1,37 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(targets = { + "com.simibubi.create.content.kinetics.simpleRelays.CogwheelBlockItem$SmallCogHelper", + "com.simibubi.create.content.kinetics.simpleRelays.CogwheelBlockItem$LargeCogHelper", + "com.simibubi.create.content.kinetics.simpleRelays.CogwheelBlockItem$DiagonalCogHelper", + "com.simibubi.create.content.kinetics.simpleRelays.CogwheelBlockItem$IntegratedLargeCogHelper", + "com.simibubi.create.content.kinetics.simpleRelays.CogwheelBlockItem$IntegratedSmallCogHelper" +}) +public class MixinCogwheelBlockItem { + @Redirect(method = "getOffset", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/BlockHitResult;getLocation()Lnet/minecraft/world/phys/Vec3;")) + private Vec3 redirectGetLocation(BlockHitResult instance) { + Vec3 result = instance.getLocation(); + Level world = Minecraft.getInstance().level; + if (world != null) { + Ship ship = VSGameUtilsKt.getShipManagingPos(world, instance.getBlockPos()); + if (ship != null && !VSGameUtilsKt.isBlockInShipyard(world, result.x, result.y, result.z)) { + Vector3d tempVec = VectorConversionsMCKt.toJOML(result); + ship.getWorldToShip().transformPosition(tempVec, tempVec); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + } + return result; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinCogwheelBlockItemHitOnShaft.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinCogwheelBlockItemHitOnShaft.java new file mode 100644 index 000000000..bb68b92d0 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinCogwheelBlockItemHitOnShaft.java @@ -0,0 +1,33 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(targets = { + "com.simibubi.create.content.kinetics.simpleRelays.CogwheelBlockItem$DiagonalCogHelper" +}) +public class MixinCogwheelBlockItemHitOnShaft { + @Redirect(method = "hitOnShaft", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/BlockHitResult;getLocation()Lnet/minecraft/world/phys/Vec3;")) + private Vec3 redirectGetLocation(BlockHitResult instance) { + Vec3 result = instance.getLocation(); + Level world = Minecraft.getInstance().level; + if(world!=null) { + Ship ship = VSGameUtilsKt.getShipManagingPos(world, instance.getBlockPos()); + if (ship != null && !VSGameUtilsKt.isBlockInShipyard(world, result.x, result.y, result.z)) { + Vector3d tempVec = VectorConversionsMCKt.toJOML(result); + ship.getWorldToShip().transformPosition(tempVec, tempVec); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + } + return result; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinContraptionRenderDispatcher.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinContraptionRenderDispatcher.java new file mode 100644 index 000000000..17ec80da9 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinContraptionRenderDispatcher.java @@ -0,0 +1,26 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import net.minecraft.core.Vec3i; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.mod.common.VSClientGameUtils; + +@Mixin(ContraptionRenderDispatcher.class) +public abstract class MixinContraptionRenderDispatcher { + + @Redirect( + method = "renderActors", + at = @At( + value = "INVOKE", + target = "Lcom/jozufozu/flywheel/util/transform/TransformStack;translate(Lnet/minecraft/core/Vec3i;)Ljava/lang/Object;" + ) + ) + private static Object redirectTranslate(final TransformStack instance, final Vec3i vec3i) { + VSClientGameUtils.transformRenderIfInShipyard((PoseStack) instance, vec3i.getX(), vec3i.getY(), vec3i.getZ()); + return instance; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinContraptionRenderInfo.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinContraptionRenderInfo.java new file mode 100644 index 000000000..b24a697b0 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinContraptionRenderInfo.java @@ -0,0 +1,53 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderInfo; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.minecraft.util.Mth; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.mod.common.VSClientGameUtils; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(ContraptionRenderInfo.class) +public class MixinContraptionRenderInfo { + + @Shadow + @Final + public Contraption contraption; + @Shadow + @Final + private ContraptionMatrices matrices; + + @Inject(method = "setupMatrices", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V"), cancellable = true) + private void injectAndDoTransformation(PoseStack viewProjection, double camX, double camY, double camZ, CallbackInfo ci) { + AbstractContraptionEntity entity = contraption.entity; + + if (VSGameUtilsKt.getShipManaging(entity) instanceof final ClientShip ship) { + viewProjection.pushPose(); + + double partialTick = AnimationTickHolder.getPartialTicks(); + VSClientGameUtils.transformRenderWithShip( + ship.getRenderTransform(), + viewProjection, + Mth.lerp(partialTick, entity.xOld, entity.getX()), + Mth.lerp(partialTick, entity.yOld, entity.getY()), + Mth.lerp(partialTick, entity.zOld, entity.getZ()), + camX, + camY, + camZ + ); + matrices.setup(viewProjection, entity); + viewProjection.popPose(); + ci.cancel(); + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinElevatorControlsHandler.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinElevatorControlsHandler.java new file mode 100644 index 000000000..0d200f69b --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinElevatorControlsHandler.java @@ -0,0 +1,29 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.elevator.ElevatorControlsHandler; +import net.minecraft.client.Minecraft; +import net.minecraft.world.phys.AABB; +import org.joml.primitives.AABBdc; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(ElevatorControlsHandler.class) +public class MixinElevatorControlsHandler { + // Fixes raytracing contraptions on ships + @WrapOperation(method = "onScroll", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/AbstractContraptionEntity;getBoundingBox()Lnet/minecraft/world/phys/AABB;")) + private static AABB onScrollGetBoundingBox(final AbstractContraptionEntity instance, final Operation getBoundingBox) { + final ClientShip clientShip = VSGameUtilsKt.getShipObjectManagingPos(Minecraft.getInstance().level, instance.getAnchorVec().x, instance.getAnchorVec().y, instance.getAnchorVec().z); + if (clientShip != null) { + final AABB original = getBoundingBox.call(instance); + final AABBdc modified = VectorConversionsMCKt.toJOML(original).transform(clientShip.getRenderTransform().getShipToWorld()); + return VectorConversionsMCKt.toMinecraft(modified); + } + return getBoundingBox.call(instance); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinFilteringRenderer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinFilteringRenderer.java new file mode 100644 index 000000000..352bcf2c2 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinFilteringRenderer.java @@ -0,0 +1,31 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringRenderer; +import net.minecraft.client.Minecraft; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(FilteringRenderer.class) +public class MixinFilteringRenderer { + + @Redirect( + method = "tick", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;subtract(Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;") + ) + private static Vec3 redirectSubtract(Vec3 instance, Vec3 vec) { + Vec3 result = VSGameUtilsKt.toShipRenderCoordinates(Minecraft.getInstance().level, vec, instance); + return result.subtract(vec); + } + + @Redirect( + method = "renderOnBlockEntity", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;distanceToSqr(Lnet/minecraft/world/phys/Vec3;)D") + ) + private static double redirectDistanceToSqr(Vec3 instance, Vec3 vec) { + Vec3 result = VSGameUtilsKt.toShipRenderCoordinates(Minecraft.getInstance().level, vec, instance); + return result.distanceToSqr(vec); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinGhostBlockRenderer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinGhostBlockRenderer.java new file mode 100644 index 000000000..cbf095eaa --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinGhostBlockRenderer.java @@ -0,0 +1,21 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.mojang.blaze3d.vertex.PoseStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.mod.common.VSClientGameUtils; + +@Mixin(targets = {"com.simibubi.create.foundation.utility.ghost.GhostBlockRenderer$DefaultGhostBlockRenderer", + "com.simibubi.create.foundation.utility.ghost.GhostBlockRenderer$TransparentGhostBlockRenderer"}) +public class MixinGhostBlockRenderer { + + @Redirect( + method = "render", + at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;translate(DDD)V", ordinal = 0) + ) + private void redirectTranslate( + final PoseStack instance, final double pose, final double d, final double e) { + VSClientGameUtils.transformRenderIfInShipyard(instance, pose, d, e); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinLinkRenderer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinLinkRenderer.java new file mode 100644 index 000000000..8178ff275 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinLinkRenderer.java @@ -0,0 +1,21 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.simibubi.create.content.redstone.link.LinkRenderer; +import net.minecraft.client.Minecraft; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(LinkRenderer.class) +public class MixinLinkRenderer { + @Redirect( + method = "renderOnBlockEntity", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;distanceToSqr(Lnet/minecraft/world/phys/Vec3;)D") + ) + private static double redirectDistanceToSqr(Vec3 instance, Vec3 vec) { + Vec3 result = VSGameUtilsKt.toShipRenderCoordinates(Minecraft.getInstance().level, vec, instance); + return result.distanceToSqr(vec); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinMinecartInstance.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinMinecartInstance.java new file mode 100644 index 000000000..e2b878848 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinMinecartInstance.java @@ -0,0 +1,59 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance; +import com.jozufozu.flywheel.util.AnimationTickHolder; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.jozufozu.flywheel.vanilla.MinecartInstance; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import org.joml.Matrix4d; +import org.joml.Matrix4f; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.core.api.ships.properties.ShipTransform; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(MinecartInstance.class) +public abstract class MixinMinecartInstance extends EntityInstance { + + + public MixinMinecartInstance(MaterialManager materialManager, Entity entity) { + super(materialManager, entity); + } + + @Redirect( + method = "beginFrame", at = @At(value = "INVOKE", + target = "Lcom/jozufozu/flywheel/util/transform/TransformStack;translate(DDD)Ljava/lang/Object;", ordinal = 0), + remap = false + ) + private Object redirectTranslate(TransformStack instance, double x, double y, double z) { + final float partialTicks = AnimationTickHolder.getPartialTicks(); + if (VSGameUtilsKt.getShipManaging(entity) instanceof ClientShip ship) { + final Vector3d origin = VectorConversionsMCKt.toJOMLD(materialManager.getOriginCoordinate()); + final Vec3 pos = entity.position(); + final Vector3d newPosition = + new Vector3d( + Mth.lerp(partialTicks, entity.xOld, pos.x), + Mth.lerp(partialTicks, entity.yOld, pos.y), + Mth.lerp(partialTicks, entity.zOld, pos.z) + ); + final ShipTransform transform = ship.getRenderTransform(); + Matrix4d renderMatrix = new Matrix4d() + .translate(origin.mul(-1)) + .mul(transform.getShipToWorld()) + .translate(newPosition); + Matrix4f mat4f = new Matrix4f(renderMatrix); + ((PoseStack) instance).last().pose().mul(mat4f); + } else { + instance.translate(x, y, z); + } + return null; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinMultiplePlacementHelpers.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinMultiplePlacementHelpers.java new file mode 100644 index 000000000..609047cc0 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinMultiplePlacementHelpers.java @@ -0,0 +1,48 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.simibubi.create.foundation.placement.PlacementOffset; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(targets = { + "com.simibubi.create.content.contraptions.bearing.SailBlock$PlacementHelper", + "com.simibubi.create.foundation.placement.PoleHelper", + "com.simibubi.create.content.decoration.girder.GirderPlacementHelper", + "com.simibubi.create.content.trains.display.FlapDisplayBlock$PlacementHelper" +}) +public class MixinMultiplePlacementHelpers { + + @Unique + private Level world; + + @Inject(method = "getOffset", at = @At("HEAD")) + private void harvestWorld(Player player, Level world, BlockState state, BlockPos pos, BlockHitResult ray, CallbackInfoReturnable cir) { + this.world = world; + } + + @Redirect(method = "getOffset", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/BlockHitResult;getLocation()Lnet/minecraft/world/phys/Vec3;")) + private Vec3 redirectGetLocation(BlockHitResult instance) { + Vec3 result = instance.getLocation(); + Ship ship = VSGameUtilsKt.getShipManagingPos(world, instance.getBlockPos()); + if (ship != null && !VSGameUtilsKt.isBlockInShipyard(world,result.x,result.y,result.z)) { + Vector3d tempVec = VectorConversionsMCKt.toJOML(result); + ship.getWorldToShip().transformPosition(tempVec, tempVec); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + return result; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinOrientedContraptionEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinOrientedContraptionEntity.java new file mode 100644 index 000000000..6b3a0ad4c --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinOrientedContraptionEntity.java @@ -0,0 +1,66 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import org.joml.Quaterniond; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(OrientedContraptionEntity.class) +public class MixinOrientedContraptionEntity { + + @Shadow + private Vec3 getCartOffset(float partialTicks, Entity ridingEntity) { + return Vec3.ZERO; + } + + @Redirect(method = "applyLocalTransforms", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/OrientedContraptionEntity;repositionOnCart(Lcom/mojang/blaze3d/vertex/PoseStack;FLnet/minecraft/world/entity/Entity;)V")) + private void redirectRepositionOnCart(OrientedContraptionEntity instance, PoseStack matrixStack, float partialTicks, Entity ridingEntity) { + + Vec3 cartPos = getCartOffset(partialTicks, ridingEntity); + if (cartPos != Vec3.ZERO) matrixStack.translate(cartPos.x, cartPos.y, cartPos.z); + + ClientShip ship = (ClientShip) VSGameUtilsKt.getShipManagingPos(instance.getCommandSenderWorld(), ridingEntity.blockPosition()); + if (ship != null) { + Quaterniond quaternion = new Quaterniond(); + ship.getRenderTransform().getShipToWorld().getNormalizedRotation(quaternion); + TransformStack.cast(matrixStack).rotateCentered(VectorConversionsMCKt.toFloat(quaternion)); + } + } + + @Redirect(method = "repositionOnContraption", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;translate(DDD)V", ordinal = 0)) + private void redirectTranslate(final PoseStack instance, final double pose, final double d, final double e) { + instance.translate(pose, d, e); + + ClientShip ship = (ClientShip) VSGameUtilsKt.getShipManagingPos(Minecraft.getInstance().level, ((AbstractContraptionEntity) (Object) this).getVehicle().blockPosition()); + if (ship != null) { + Quaterniond quaternion = new Quaterniond(); + ship.getRenderTransform().getShipToWorld().getNormalizedRotation(quaternion); + TransformStack.cast(instance).rotateCentered(VectorConversionsMCKt.toFloat(quaternion)); + } + } + + @Redirect(method = "getContraptionOffset", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/AbstractContraptionEntity;getPassengerPosition(Lnet/minecraft/world/entity/Entity;F)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 redirectGetPassengerPosition(AbstractContraptionEntity instance, Entity passenger, float partialTicks) { + Vec3 result = instance.getPassengerPosition(passenger, partialTicks); + + ClientShip ship = (ClientShip) VSGameUtilsKt.getShipManagingPos(instance.getCommandSenderWorld(), instance.position()); + if (ship != null) { + Vector3d dest = new Vector3d(); + ship.getRenderTransform().getShipToWorld().transformPosition(VectorConversionsMCKt.toJOML(result), dest); + result = VectorConversionsMCKt.toMinecraft(dest); + } + return result; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinOutline.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinOutline.java new file mode 100644 index 000000000..760a4dd13 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinOutline.java @@ -0,0 +1,421 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.foundation.outliner.Outline; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.joml.Matrix4d; +import org.joml.Matrix4dc; +import org.joml.Vector3d; +import org.joml.Vector3dc; +import org.joml.Vector3f; +import org.joml.Vector4f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.core.api.ships.properties.ShipTransform; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(Outline.class) +public abstract class MixinOutline { + @Shadow + public abstract void bufferCuboidLine(PoseStack poseStack, VertexConsumer consumer, Vec3 camera, Vector3d start, Vector3d end, float width, Vector4f color, int lightmap, boolean disableNormals); + + @Shadow + public abstract void bufferQuad(PoseStack.Pose pose, VertexConsumer consumer, Vector3f pos0, Vector3f pos1, Vector3f pos2, Vector3f pos3, Vector4f color, float minU, float minV, float maxU, float maxV, int lightmap, Vector3f normal); + + @Inject(method = "bufferCuboidLine(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/world/phys/Vec3;Lorg/joml/Vector3d;Lorg/joml/Vector3d;FLorg/joml/Vector4f;IZ)V", at = @At("HEAD"), cancellable = true) + private void preBufferCuboidLine0(PoseStack poseStack, VertexConsumer consumer, Vec3 camera, Vector3d start, Vector3d end, float width, Vector4f color, int lightmap, boolean disableNormals, CallbackInfo ci) { + final Level level = Minecraft.getInstance().level; + if (level != null) { + final Vector3dc average = new Vector3d((start.x + end.x) / 2.0, (start.y + end.y) / 2.0, (start.z + end.z) / 2.0); + final ClientShip ship = (ClientShip) VSGameUtilsKt.getShipManagingPos(level, average); + if (ship != null) { + final ShipTransform transform = ship.getRenderTransform(); + final Vector3dc startTransformed = transform.getShipToWorld().transformPosition(new Vector3d(start.x, start.y, start.z)); + final Vector3dc endTransformed = transform.getShipToWorld().transformPosition(new Vector3d(end.x, end.y, end.z)); + float scaledWidth = (float) (width * transform.getShipToWorldScaling().x()); + bufferCuboidLine(poseStack, consumer, camera, new Vector3d(startTransformed.x(), startTransformed.y(), startTransformed.z()), new Vector3d(endTransformed.x(), endTransformed.y(), endTransformed.z()), scaledWidth, color, lightmap, disableNormals); + ci.cancel(); + } + } + } + + @Inject(method = "bufferCuboid", at = @At("HEAD"), cancellable = true) + private void preBufferCuboid(PoseStack.Pose pose, VertexConsumer consumer, Vector3f minPos, Vector3f maxPos, Vector4f color, int lightmap, boolean disableNormals, CallbackInfo ci) { + final Level level = Minecraft.getInstance().level; + if (level != null) { + final Vector3dc average = new Vector3d((minPos.x() + maxPos.x()) / 2.0, (minPos.y() + maxPos.y()) / 2.0, (minPos.z() + maxPos.z()) / 2.0); + final ClientShip ship = (ClientShip) VSGameUtilsKt.getShipManagingPos(level, average); + if (ship != null) { + final ShipTransform transform = ship.getRenderTransform(); + + final Vector3d temp = new Vector3d(); + + float minX = minPos.x(); + float minY = minPos.y(); + float minZ = minPos.z(); + float maxX = maxPos.x(); + float maxY = maxPos.y(); + float maxZ = maxPos.z(); + + final Matrix4dc newPosMatrix = new Matrix4d(pose.pose()).mul(transform.getShipToWorld());// VectorConversionsMCKt.toJOML(pose.pose()).mul(transform.getShipToWorld()); + + temp.set(minX, minY, maxZ); + newPosMatrix.transformPosition(temp); + double x0 = temp.x(); + double y0 = temp.y(); + double z0 = temp.z(); + //System.out.println("temp is " + temp); + + temp.set(minX, minY, minZ); + newPosMatrix.transformPosition(temp); + double x1 = temp.x(); + double y1 = temp.y(); + double z1 = temp.z(); + + temp.set(maxX, minY, minZ); + newPosMatrix.transformPosition(temp); + double x2 = temp.x(); + double y2 = temp.y(); + double z2 = temp.z(); + + temp.set(maxX, minY, maxZ); + newPosMatrix.transformPosition(temp); + double x3 = temp.x(); + double y3 = temp.y(); + double z3 = temp.z(); + + temp.set(minX, maxY, minZ); + newPosMatrix.transformPosition(temp); + double x4 = temp.x(); + double y4 = temp.y(); + double z4 = temp.z(); + + temp.set(minX, maxY, maxZ); + newPosMatrix.transformPosition(temp); + double x5 = temp.x(); + double y5 = temp.y(); + double z5 = temp.z(); + + temp.set(maxX, maxY, maxZ); + newPosMatrix.transformPosition(temp); + double x6 = temp.x(); + double y6 = temp.y(); + double z6 = temp.z(); + + temp.set(maxX, maxY, minZ); + newPosMatrix.transformPosition(temp); + double x7 = temp.x(); + double y7 = temp.y(); + double z7 = temp.z(); + + float r = color.x(); + float g = color.y(); + float b = color.z(); + float a = color.w(); + + // down + + if (disableNormals) { + temp.set(0, 1, 0); + } else { + temp.set(0, -1, 0); + } + newPosMatrix.transformDirection(temp).normalize(); + float nx0 = (float) temp.x(); + float ny0 = (float) temp.y(); + float nz0 = (float) temp.z(); + + consumer.vertex(x0, y0, z0) + .color(r, g, b, a) + .uv(0, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx0, ny0, nz0) + .endVertex(); + + consumer.vertex(x1, y1, z1) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx0, ny0, nz0) + .endVertex(); + + consumer.vertex(x2, y2, z2) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx0, ny0, nz0) + .endVertex(); + + consumer.vertex(x3, y3, z3) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx0, ny0, nz0) + .endVertex(); + + // up + + temp.set(0, 1, 0); + newPosMatrix.transformDirection(temp).normalize(); + float nx1 = (float) temp.x(); + float ny1 = (float) temp.y(); + float nz1 = (float) temp.z(); + + consumer.vertex(x4, y4, z4) + .color(r, g, b, a) + .uv(0, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx1, ny1, nz1) + .endVertex(); + + consumer.vertex(x5, y5, z5) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx1, ny1, nz1) + .endVertex(); + + consumer.vertex(x6, y6, z6) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx1, ny1, nz1) + .endVertex(); + + consumer.vertex(x7, y7, z7) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx1, ny1, nz1) + .endVertex(); + + // north + + if (disableNormals) { + temp.set(0, 1, 0); + } else { + temp.set(0, 0, -1); + } + newPosMatrix.transformDirection(temp).normalize(); + float nx2 = (float) temp.x(); + float ny2 = (float) temp.y(); + float nz2 = (float) temp.z(); + + consumer.vertex(x7, y7, z7) + .color(r, g, b, a) + .uv(0, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx2, ny2, nz2) + .endVertex(); + + consumer.vertex(x2, y2, z2) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx2, ny2, nz2) + .endVertex(); + + consumer.vertex(x1, y1, z1) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx2, ny2, nz2) + .endVertex(); + + consumer.vertex(x4, y4, z4) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx2, ny2, nz2) + .endVertex(); + + // south + + if (disableNormals) { + temp.set(0, 1, 0); + } else { + temp.set(0, 0, 1); + } + newPosMatrix.transformDirection(temp).normalize(); + float nx3 = (float) temp.x(); + float ny3 = (float) temp.y(); + float nz3 = (float) temp.z(); + + consumer.vertex(x5, y5, z5) + .color(r, g, b, a) + .uv(0, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx3, ny3, nz3) + .endVertex(); + + consumer.vertex(x0, y0, z0) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx3, ny3, nz3) + .endVertex(); + + consumer.vertex(x3, y3, z3) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx3, ny3, nz3) + .endVertex(); + + consumer.vertex(x6, y6, z6) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx3, ny3, nz3) + .endVertex(); + + // west + + if (disableNormals) { + temp.set(0, 1, 0); + } else { + temp.set(-1, 0, 0); + } + newPosMatrix.transformDirection(temp).normalize(); + float nx4 = (float) temp.x(); + float ny4 = (float) temp.y(); + float nz4 = (float) temp.z(); + + consumer.vertex(x4, y4, z4) + .color(r, g, b, a) + .uv(0, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx4, ny4, nz4) + .endVertex(); + + consumer.vertex(x1, y1, z1) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx4, ny4, nz4) + .endVertex(); + + consumer.vertex(x0, y0, z0) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx4, ny4, nz4) + .endVertex(); + + consumer.vertex(x5, y5, z5) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx4, ny4, nz4) + .endVertex(); + + // east + + if (disableNormals) { + temp.set(0, 1, 0); + } else { + temp.set(1, 0, 0); + } + newPosMatrix.transformDirection(temp).normalize(); + float nx5 = (float) temp.x(); + float ny5 = (float) temp.y(); + float nz5 = (float) temp.z(); + + consumer.vertex(x6, y6, z6) + .color(r, g, b, a) + .uv(0, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx5, ny5, nz5) + .endVertex(); + + consumer.vertex(x3, y3, z3) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx5, ny5, nz5) + .endVertex(); + + consumer.vertex(x2, y2, z2) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx5, ny5, nz5) + .endVertex(); + + consumer.vertex(x7, y7, z7) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx5, ny5, nz5) + .endVertex(); + + ci.cancel(); + } + } + } + + @Inject(method = "bufferQuad(Lcom/mojang/blaze3d/vertex/PoseStack$Pose;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lorg/joml/Vector3f;Lorg/joml/Vector3f;Lorg/joml/Vector3f;Lorg/joml/Vector3f;Lorg/joml/Vector4f;FFFFILorg/joml/Vector3f;)V", at = @At("HEAD"), cancellable = true) + private void preBufferQuad(PoseStack.Pose pose, VertexConsumer consumer, Vector3f pos0, Vector3f pos1, Vector3f pos2, Vector3f pos3, Vector4f color, float minU, float minV, float maxU, float maxV, int lightmap, Vector3f normal, CallbackInfo ci) { + final Level level = Minecraft.getInstance().level; + if (level != null) { + final Vector3dc average = new Vector3d((pos0.x() + pos1.x() + pos2.x() + pos3.x()) / 4.0, (pos0.y() + pos1.y() + pos2.y() + pos3.y()) / 4.0, (pos0.z() + pos1.z() + pos2.z() + pos3.z()) / 4.0); + final ClientShip ship = (ClientShip) VSGameUtilsKt.getShipManagingPos(level, average); + if (ship != null) { + final ShipTransform transform = ship.getRenderTransform(); + final Vector3dc pos0Transformed = transform.getShipToWorld().transformPosition(new Vector3d(pos0.x(), pos0.y(), pos0.z())); + final Vector3dc pos1Transformed = transform.getShipToWorld().transformPosition(new Vector3d(pos1.x(), pos1.y(), pos1.z())); + final Vector3dc pos2Transformed = transform.getShipToWorld().transformPosition(new Vector3d(pos2.x(), pos2.y(), pos2.z())); + final Vector3dc pos3Transformed = transform.getShipToWorld().transformPosition(new Vector3d(pos3.x(), pos3.y(), pos3.z())); + final Vector3dc normalTransformed = transform.getShipToWorld().transformDirection(new Vector3d(normal.x(), normal.y(), normal.z())); + bufferQuad( + pose, + consumer, + new Vector3f((float) pos0Transformed.x(), (float) pos0Transformed.y(), (float) pos0Transformed.z()), + new Vector3f((float) pos1Transformed.x(), (float) pos1Transformed.y(), (float) pos1Transformed.z()), + new Vector3f((float) pos2Transformed.x(), (float) pos2Transformed.y(), (float) pos2Transformed.z()), + new Vector3f((float) pos3Transformed.x(), (float) pos3Transformed.y(), (float) pos3Transformed.z()), + color, + minU, + minV, + maxU, + maxV, + lightmap, + new Vector3f((float) normalTransformed.x(), (float) normalTransformed.y(), (float) normalTransformed.z()) + ); + ci.cancel(); + } + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinPlacementHelpers.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinPlacementHelpers.java new file mode 100644 index 000000000..093fe2061 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinPlacementHelpers.java @@ -0,0 +1,30 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.client.Minecraft; +import net.minecraft.core.Vec3i; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(PlacementHelpers.class) +public class MixinPlacementHelpers { + @Redirect(method = "drawDirectionIndicator", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/foundation/utility/VecHelper;getCenterOf(Lnet/minecraft/core/Vec3i;)Lnet/minecraft/world/phys/Vec3;")) + private static Vec3 redirectGetCenterOf(Vec3i pos) { + Vec3 result = VecHelper.getCenterOf(pos); + Level world = Minecraft.getInstance().level; + if (world != null && VSGameUtilsKt.isBlockInShipyard(world, pos.getX(),pos.getY(),pos.getZ()) && VSGameUtilsKt.getShipManagingPos(world, pos.getX(),pos.getY(),pos.getZ()) instanceof ClientShip ship) { + Vector3d tempVec = new Vector3d(pos.getX() + .5, pos.getY() + .5, pos.getZ() + .5); + ship.getShipToWorld().transformPosition(tempVec, tempVec); + result = VectorConversionsMCKt.toMinecraft(tempVec); + } + return result; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinSoundScapes.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinSoundScapes.java new file mode 100644 index 000000000..6a0433474 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinSoundScapes.java @@ -0,0 +1,43 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.simibubi.create.foundation.sound.SoundScapes; +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(SoundScapes.class) +public abstract class MixinSoundScapes { + + @Redirect(method = "outOfRange", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;closerThan(Lnet/minecraft/core/Vec3i;D)Z")) + private static boolean redirectCloserThan(BlockPos instance, Vec3i vec3i, double v) { + Vec3 newVec3 = new Vec3(vec3i.getX(), vec3i.getY(), vec3i.getZ()); + Level world = Minecraft.getInstance().player.level(); + final Ship ship = VSGameUtilsKt.getShipManagingPos(world, newVec3); + if (ship != null) { + newVec3 = VSGameUtilsKt.toWorldCoordinates(ship, newVec3); + } + return new Vec3(instance.getX(), instance.getY(), instance.getZ()).closerThan(newVec3, v); + } + + @ModifyVariable(method = "play", at = @At("HEAD"), index = 1, argsOnly = true) + private static BlockPos modBlockPos(BlockPos value) { + BlockPos result = value; + Level world = Minecraft.getInstance().player.level(); + final Ship ship = VSGameUtilsKt.getShipManagingPos(world, value); + if (ship != null) { + Vector3d tempVec = new Vector3d(); + ship.getTransform().getShipToWorld().transformPosition(value.getX(), value.getY(), value.getZ(), tempVec); + result = BlockPos.containing(tempVec.x, tempVec.y, tempVec.z); + } + return result; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinTileEntityRenderHelper.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinTileEntityRenderHelper.java new file mode 100644 index 000000000..1486cf9c7 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinTileEntityRenderHelper.java @@ -0,0 +1,25 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.render.BlockEntityRenderHelper; +import net.minecraft.core.Vec3i; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.mod.common.VSClientGameUtils; + +@Mixin(BlockEntityRenderHelper.class) +public abstract class MixinTileEntityRenderHelper { + @Redirect( + method = "renderBlockEntities(Lnet/minecraft/world/level/Level;Lcom/jozufozu/flywheel/core/virtual/VirtualRenderWorld;Ljava/lang/Iterable;Lcom/mojang/blaze3d/vertex/PoseStack;Lorg/joml/Matrix4f;Lnet/minecraft/client/renderer/MultiBufferSource;F)V", + at = @At( + value = "INVOKE", + target = "Lcom/jozufozu/flywheel/util/transform/TransformStack;translate(Lnet/minecraft/core/Vec3i;)Ljava/lang/Object;" + ) + ) + private static Object redirectTranslate(final TransformStack instance, final Vec3i vec3i) { + VSClientGameUtils.transformRenderIfInShipyard((PoseStack) instance, vec3i.getX(), vec3i.getY(), vec3i.getZ()); + return instance; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinTrackBlockOutline.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinTrackBlockOutline.java new file mode 100644 index 000000000..57496850d --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinTrackBlockOutline.java @@ -0,0 +1,84 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.simibubi.create.content.trains.track.TrackBlockOutline; +import com.simibubi.create.foundation.utility.RaycastHelper; +import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult.Type; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(TrackBlockOutline.class) +public class MixinTrackBlockOutline { + @Unique + private static boolean isShip = false; + @Unique + private static BlockPos shipBlockPos; + + @Inject( + method = "pickCurves", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/player/LocalPlayer;getEyePosition(F)Lnet/minecraft/world/phys/Vec3;" + ), locals = LocalCapture.CAPTURE_FAILHARD + ) + private static void stuff(final CallbackInfo ci, final Minecraft mc) { + if (mc.hitResult != null && mc.level != null && mc.hitResult.getType() == Type.BLOCK) { + shipBlockPos = ((BlockHitResult) mc.hitResult).getBlockPos(); + + final List + ships = VSGameUtilsKt.transformToNearbyShipsAndWorld(mc.level, shipBlockPos.getX(), shipBlockPos.getY(), + shipBlockPos.getZ(), 10); + isShip = !ships.isEmpty(); + } + } + + @Redirect( + method = "pickCurves()V", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/player/LocalPlayer;getEyePosition(F)Lnet/minecraft/world/phys/Vec3;" + ) + ) + private static Vec3 redirectedOrigin(final LocalPlayer instance, final float v) { + final Vec3 eyePos = instance.getEyePosition(v); + if (isShip) { + final List + ships = VSGameUtilsKt.transformToNearbyShipsAndWorld(instance.level(), eyePos.x, eyePos.y, eyePos.z, 10); + if (ships.isEmpty()) { + return eyePos; + } + final Vector3d tempVec = ships.get(0); + return new Vec3(tempVec.x, tempVec.y, tempVec.z); + } else { + return eyePos; + } + } + + @Redirect( + method = "pickCurves()V", + at = @At( + value = "INVOKE", + target = "Lcom/simibubi/create/foundation/utility/RaycastHelper;getTraceTarget(Lnet/minecraft/world/entity/player/Player;DLnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;" + ) + ) + private static Vec3 redirectedTarget(final Player playerIn, final double range, final Vec3 origin) { + if (isShip) { + return new Vec3(shipBlockPos.getX(), shipBlockPos.getY(), shipBlockPos.getZ()); + } else { + return RaycastHelper.getTraceTarget(playerIn, range, origin); + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinTrainRelocator.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinTrainRelocator.java new file mode 100644 index 000000000..5503b227b --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/client/MixinTrainRelocator.java @@ -0,0 +1,27 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.client; + +import com.simibubi.create.content.trains.entity.TrainRelocator; +import net.minecraft.client.Minecraft; +import net.minecraft.core.Position; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(TrainRelocator.class) +public abstract class MixinTrainRelocator { + + @Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;closerThan(Lnet/minecraft/core/Position;D)Z")) + private static boolean redirectCloserThan(final Vec3 instance, final Position arg, final double d) { + Vec3 newVec3 = (Vec3) arg; + Level world = Minecraft.getInstance().player.level(); + final Ship ship = VSGameUtilsKt.getShipManagingPos(world, arg); + if (ship != null) { + newVec3 = VSGameUtilsKt.toWorldCoordinates(ship, (Vec3) arg); + } + return instance.closerThan(newVec3, d); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinAbstractContraptionEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinAbstractContraptionEntity.java new file mode 100644 index 000000000..23a368f65 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinAbstractContraptionEntity.java @@ -0,0 +1,326 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.entity; + +import static org.valkyrienskies.mod.common.util.VectorConversionsMCKt.toJOML; +import static org.valkyrienskies.mod.common.util.VectorConversionsMCKt.toMinecraft; + +import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.contraptions.actors.harvester.HarvesterMovementBehaviour; +import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; +import com.simibubi.create.content.kinetics.deployer.DeployerMovementBehaviour; +import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraft.world.phys.Vec3; +import org.apache.commons.lang3.tuple.MutablePair; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.NotNull; +import org.joml.Matrix3d; +import org.joml.Matrix4d; +import org.joml.Matrix4dc; +import org.joml.Vector3d; +import org.joml.Vector3dc; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.valkyrienskies.core.api.ships.ContraptionWingProvider; +import org.valkyrienskies.core.api.ships.LoadedServerShip; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.core.api.ships.WingManager; +import org.valkyrienskies.mod.common.CompatUtil; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; +import org.valkyrienskies.mod.compat.CreateConversionsKt; +import org.valkyrienskies.mod.mixinducks.mod_compat.create.MixinAbstractContraptionEntityDuck; + +@Mixin(AbstractContraptionEntity.class) +public abstract class MixinAbstractContraptionEntity extends Entity implements MixinAbstractContraptionEntityDuck, + ContraptionWingProvider { + + public MixinAbstractContraptionEntity(EntityType entityType, Level level) { + super(entityType, level); + } + + @Shadow + protected abstract StructureTransform makeStructureTransform(); + + public StructureTransform getStructureTransform() { + return this.makeStructureTransform(); + } + + @Unique + private static final Logger LOGGER = LogManager.getLogger("Clockwork.MixinAbstractContraptionEntity"); + + @Unique + private int wingGroupId = -1; + + @Shadow(remap = false) + protected Contraption contraption; + + @Shadow + public abstract Vec3 getPassengerPosition(Entity passenger, float partialTicks); + + @Shadow + public abstract Vec3 applyRotation(Vec3 localPos, float partialTicks); + + @Shadow + public abstract Vec3 getAnchorVec(); + + @Shadow + public abstract Vec3 getPrevAnchorVec(); + + //Region start - fix being sent to the ̶s̶h̶a̶d̶o̶w̶r̶e̶a̶l̶m̶ shipyard on ship contraption disassembly + @Redirect(method = "moveCollidedEntitiesOnDisassembly", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setPos(DDD)V")) + private void redirectSetPos(Entity instance, double x, double y, double z) { + Vec3 result = CompatUtil.INSTANCE.toSameSpaceAs(instance.getCommandSenderWorld(), x, y, z, instance.position()); + if (instance.position().distanceTo(result) < 20) { + instance.setPos(result.x, result.y, result.z); + } else LOGGER.warn("Warning distance too high ignoring setPos request"); + } + + @Redirect(method = "moveCollidedEntitiesOnDisassembly", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleportTo(DDD)V")) + private void redirectTeleportTo(Entity instance, double x, double y, double z) { + Vec3 result = CompatUtil.INSTANCE.toSameSpaceAs(instance.getCommandSenderWorld(), x, y, z, instance.position()); + if (instance.position().distanceTo(result) < 20) { + if (VSGameUtilsKt.isBlockInShipyard(instance.getCommandSenderWorld(), result.x, result.y, result.z) && instance instanceof AbstractMinecart) { + result.add(0, 0.5, 0); + } + instance.teleportTo(result.x, result.y, result.z); + } else { + LOGGER.warn("Warning distance too high ignoring teleportTo request"); + } + } + + //Region end + //Region start - fix entity rider position on ship contraptions + @Override + public void positionRider(@NotNull Entity passenger, MoveFunction callback) { + if (!hasPassenger(passenger)) + return; + Vec3 riderPos = getPassengerPosition(passenger, 1); + if (riderPos == null) + return; + if (!(passenger instanceof OrientedContraptionEntity)) { + Ship ship = VSGameUtilsKt.getShipManagingPos(passenger.level(), riderPos.x, riderPos.y, riderPos.z); + riderPos.add(0, SeatEntity.getCustomEntitySeatOffset(passenger) - 1 / 8f, 0); + if (ship != null) { + riderPos = toMinecraft(ship.getShipToWorld().transformPosition(toJOML(riderPos))); + } + } + passenger.setPos(riderPos); + } + + @Inject(method = "toGlobalVector(Lnet/minecraft/world/phys/Vec3;FZ)Lnet/minecraft/world/phys/Vec3;", + at = @At("HEAD"), cancellable = true) + private void redirectToGlobalVector(Vec3 localVec, final float partialTicks, final boolean prevAnchor, final CallbackInfoReturnable cir) { + if (partialTicks != 1 && !prevAnchor) { + final Vec3 anchor = getAnchorVec(); + final Vec3 oldAnchor = getPrevAnchorVec(); + final Vec3 lerpedAnchor = + new Vec3( + Mth.lerp(partialTicks, oldAnchor.x, anchor.x), + Mth.lerp(partialTicks, oldAnchor.y, anchor.y), + Mth.lerp(partialTicks, oldAnchor.z, anchor.z) + ); + final Vec3 rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO); + localVec = localVec.subtract(rotationOffset); + localVec = applyRotation(localVec, partialTicks); + localVec = localVec.add(rotationOffset) + .add(lerpedAnchor); + cir.setReturnValue(localVec); + } + } + + //Region end + //Region start - Ship contraption actors affecting world + @Shadow + public abstract Vec3 toGlobalVector(Vec3 localVec, float partialTicks); + + @Shadow + public abstract Vec3 getPrevPositionVec(); + + @Unique + private boolean vs$shouldMod(final MovementBehaviour moveBehaviour) { + return ((moveBehaviour instanceof BlockBreakingMovementBehaviour) || (moveBehaviour instanceof HarvesterMovementBehaviour) || (moveBehaviour instanceof DeployerMovementBehaviour)); + } + + @Unique + private BlockPos vs$getTargetPos(final MovementBehaviour instance, final MovementContext context, final BlockPos pos, final Vec3 actorPosition) { + if (vs$shouldMod(instance) && context.world.getBlockState(pos).isAir() && VSGameUtilsKt.isBlockInShipyard(context.world, pos)) { + final Ship ship = VSGameUtilsKt.getShipManagingPos(context.world, pos); + if (ship != null) { + final Vector3dc actorPosInWorld = ship.getTransform().getShipToWorld().transformPosition(toJOML(actorPosition)); + return BlockPos.containing(actorPosInWorld.x(), actorPosInWorld.y(), actorPosInWorld.z()); + } + } + return pos; + } + + @Unique + private boolean vs$forceStall = false; + + @Shadow + private boolean skipActorStop; + + @Shadow + @Final + private static EntityDataAccessor STALLED; + + @Shadow + public abstract boolean isStalled(); + + @Shadow + protected abstract boolean shouldActorTrigger(MovementContext context, StructureBlockInfo blockInfo, MovementBehaviour actor, Vec3 actorPosition, BlockPos gridPosition); + + @Shadow + protected abstract boolean isActorActive(MovementContext context, MovementBehaviour actor); + + @Shadow + protected abstract void onContraptionStalled(); + + @Inject(method = "tickActors", at = @At("HEAD"), cancellable = true, remap = false) + private void preTickActors(final CallbackInfo ci) { + ci.cancel(); + + final boolean stalledPreviously = contraption.stalled; + + if (!level().isClientSide) + contraption.stalled = vs$forceStall; + + skipActorStop = true; + for (final MutablePair pair : contraption.getActors()) { + final MovementContext context = pair.right; + final StructureBlockInfo blockInfo = pair.left; + final MovementBehaviour actor = AllMovementBehaviours.getBehaviour(blockInfo.state()); + + if (actor == null) + continue; + + final Vec3 oldMotion = context.motion; + final Vec3 actorPosition = toGlobalVector(VecHelper.getCenterOf(blockInfo.pos()) + .add(actor.getActiveAreaOffset(context)), 1); + final BlockPos gridPosition = vs$getTargetPos(actor, context, BlockPos.containing(actorPosition), actorPosition); // BlockPos.containing(actorPosition); + final boolean newPosVisited = + !context.stall && shouldActorTrigger(context, blockInfo, actor, actorPosition, gridPosition); + + context.rotation = v -> applyRotation(v, 1); + context.position = actorPosition; + if (!isActorActive(context, actor) && !actor.mustTickWhileDisabled()) + continue; + if (newPosVisited && !context.stall) { + actor.visitNewPosition(context, gridPosition); + if (!isAlive()) + break; + context.firstMovement = false; + } + if (!oldMotion.equals(context.motion)) { + actor.onSpeedChanged(context, oldMotion, context.motion); + if (!isAlive()) + break; + } + actor.tick(context); + if (!isAlive()) + break; + contraption.stalled |= context.stall; + } + if (!isAlive()) { + contraption.stop(level()); + return; + } + skipActorStop = false; + + for (final Entity entity : getPassengers()) { + if (!(entity instanceof final OrientedContraptionEntity orientedCE)) + continue; + if (contraption.getBearingPosOf(entity.getUUID()) == null) + continue; + if (orientedCE.getContraption() != null && orientedCE.getContraption().stalled) { + contraption.stalled = true; + break; + } + } + + if (!level().isClientSide) { + if (!stalledPreviously && contraption.stalled) + onContraptionStalled(); + entityData.set(STALLED, contraption.stalled); + return; + } + + contraption.stalled = isStalled(); + } + + @Override + public void vs$setForceStall(final boolean forceStall) { + this.vs$forceStall = forceStall; + } + + //Region end + //Region start - Contraption Entity Collision + @Inject(method = "getContactPointMotion", at = @At("HEAD")) + private void modGetContactPointMotion(Vec3 globalContactPoint, CallbackInfoReturnable cir) { + if (VSGameUtilsKt.isBlockInShipyard(level(), getAnchorVec().x, getAnchorVec().y, getAnchorVec().z) != VSGameUtilsKt.isBlockInShipyard(level(), getPrevAnchorVec().x, getPrevAnchorVec().y, getPrevAnchorVec().z)) { + Ship ship = VSGameUtilsKt.getShipManagingPos(level(), getAnchorVec()); + if (ship != null) { + Vec3 result = toMinecraft(ship.getWorldToShip().transformPosition(toJOML(getPrevPositionVec()))); + xo = result.x; + yo = result.y; + zo = result.z; + } + } + } + //Region end + + @Override + public int getWingGroupId() { + return wingGroupId; + } + + @Override + public void setWingGroupId(final int wingGroupId) { + this.wingGroupId = wingGroupId; + } + + @Inject(method = "tick", at = @At("HEAD")) + private void postTick(final CallbackInfo ci) { + final AbstractContraptionEntity thisAsAbstractContraptionEntity = AbstractContraptionEntity.class.cast(this); + final Level level = thisAsAbstractContraptionEntity.level(); + if (wingGroupId != -1 && level instanceof final ServerLevel serverLevel) { + final LoadedServerShip ship = VSGameUtilsKt.getShipObjectManagingPos(serverLevel, + VectorConversionsMCKt.toJOML(thisAsAbstractContraptionEntity.position())); + if (ship != null) { + // This can happen if a player moves a train contraption from ship to world using a wrench + ship.getAttachment(WingManager.class).setWingGroupTransform(wingGroupId, computeContraptionWingTransform()); + } + } + } + + @NotNull + @Override + public Matrix4dc computeContraptionWingTransform() { + final AbstractContraptionEntity thisAsAbstractContraptionEntity = AbstractContraptionEntity.class.cast(this); + final Matrix3d rotationMatrix = CreateConversionsKt.toJOML(thisAsAbstractContraptionEntity.getRotationState().asMatrix()); + final Vector3d pos = VectorConversionsMCKt.toJOML(thisAsAbstractContraptionEntity.getAnchorVec()); + return new Matrix4d(rotationMatrix).setTranslation(pos); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinCarriageContraptionEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinCarriageContraptionEntity.java new file mode 100644 index 000000000..aeb7c87af --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinCarriageContraptionEntity.java @@ -0,0 +1,51 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.entity; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import java.util.Collection; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Position; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(CarriageContraptionEntity.class) +public abstract class MixinCarriageContraptionEntity { + @Unique + private Level vs$world; + + @Inject( + method = "control", + at = @At("HEAD"), locals = LocalCapture.CAPTURE_FAILHARD + ) + private void injectCaptureLevel( + final BlockPos controlsLocalPos, final Collection heldControls, final Player player, + final CallbackInfoReturnable cir) { + this.vs$world = player.level(); + } + + @WrapOperation( + method = "control", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/phys/Vec3;closerThan(Lnet/minecraft/core/Position;D)Z" + ) + ) + private boolean wrapCloserThan(final Vec3 instance, final Position arg, final double d, final Operation closerThan) { + Vec3 newVec3 = instance; + if (VSGameUtilsKt.isBlockInShipyard(this.vs$world, BlockPos.containing(instance.x, instance.y, instance.z))) { + final Ship ship = VSGameUtilsKt.getShipManagingPos(this.vs$world, instance); + newVec3 = VSGameUtilsKt.toWorldCoordinates(ship, instance); + } + return closerThan.call(newVec3, arg, d); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinControlledContraptionEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinControlledContraptionEntity.java new file mode 100644 index 000000000..c8edbc7cc --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinControlledContraptionEntity.java @@ -0,0 +1,49 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.entity; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.IControlContraption; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.mod.mixinducks.mod_compat.create.IMixinControlledContraptionEntity; + +@Mixin(ControlledContraptionEntity.class) +public abstract class MixinControlledContraptionEntity extends AbstractContraptionEntity implements + IMixinControlledContraptionEntity { + @Shadow protected abstract IControlContraption getController(); + + public MixinControlledContraptionEntity(EntityType entityTypeIn, Level worldIn) { + super(entityTypeIn, worldIn); + } + + //Region start - fix equals -0 != 0 + private Vec3 flatten(Vec3 vec3) { + if (vec3.x == -0) + vec3 = new Vec3(0, vec3.y, vec3.z); + if (vec3.y == -0) + vec3 = new Vec3(vec3.x, 0, vec3.z); + if (vec3.z == -0) + vec3 = new Vec3(vec3.x, vec3.y, 0); + return vec3; + } + + @Redirect(method = "shouldActorTrigger", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;equals(Ljava/lang/Object;)Z")) + private boolean redirectEquals(Vec3 instance, Object vec3) { + Vec3 other = (Vec3) vec3; + other = flatten(other); + instance = flatten(instance); + return instance.equals(other); + } + + //Region end + + @Override + public IControlContraption grabController(){ + return getController(); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinSeatEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinSeatEntity.java new file mode 100644 index 000000000..6e894f544 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/entity/MixinSeatEntity.java @@ -0,0 +1,32 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.entity; + +import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(SeatEntity.class) +public abstract class MixinSeatEntity extends Entity { + public MixinSeatEntity(final EntityType entityType, final Level level) { + super(entityType, level); + } + + /** + * @author Triode + * @reason Fix dismount position when ship or seat is destroyed + */ + @Overwrite + public @NotNull Vec3 getDismountLocationForPassenger(final @NotNull LivingEntity livingEntity) { + if (VSGameUtilsKt.isBlockInShipyard(level(), position()) && VSGameUtilsKt.getShipManagingPos(level(), position()) == null) { + // Don't teleport to the ship if we can't find the ship + return livingEntity.position(); + } + return super.getDismountLocationForPassenger(livingEntity).add(0, 0.5f, 0); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinControlsInputPacket.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinControlsInputPacket.java new file mode 100644 index 000000000..e2c886363 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinControlsInputPacket.java @@ -0,0 +1,47 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.packets; + +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsInputPacket; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Position; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(ControlsInputPacket.class) +public abstract class MixinControlsInputPacket { + @Unique + private Level level; + + @Redirect( + method = "lambda$handle$0", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/phys/Vec3;closerThan(Lnet/minecraft/core/Position;D)Z" + ) + ) + private boolean redirectCloserThan(final Vec3 instance, final Position arg, final double d) { + Vec3 newVec3 = instance; + if (VSGameUtilsKt.isBlockInShipyard(this.level, BlockPos.containing(instance.x, instance.y, instance.z))) { + final Ship ship = VSGameUtilsKt.getShipManagingPos(this.level, instance); + newVec3 = VSGameUtilsKt.toWorldCoordinates(ship, instance); + } + return newVec3.closerThan(arg, d); + } + + @Redirect( + method = "lambda$handle$0", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerPlayer;getCommandSenderWorld()Lnet/minecraft/world/level/Level;" + ) + ) + private Level stealLevel(ServerPlayer player) { + return (level = player.getCommandSenderWorld()); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinCurvedTrackDestroyPacket.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinCurvedTrackDestroyPacket.java new file mode 100644 index 000000000..46540454d --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinCurvedTrackDestroyPacket.java @@ -0,0 +1,49 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.packets; + +import com.simibubi.create.content.trains.track.CurvedTrackDestroyPacket; +import com.simibubi.create.content.trains.track.TrackBlockEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(CurvedTrackDestroyPacket.class) +public abstract class MixinCurvedTrackDestroyPacket { + @Unique + private Level world; + + @Redirect( + method = "applySettings(Lnet/minecraft/server/level/ServerPlayer;Lcom/simibubi/create/content/trains/track/TrackBlockEntity;)V", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/core/BlockPos;closerThan(Lnet/minecraft/core/Vec3i;D)Z" + ) + ) + private boolean redirectCloserThan(final BlockPos instance, final Vec3i vec3i, final double v) { + BlockPos blockPos = instance; + if (VSGameUtilsKt.isBlockInShipyard(this.world, instance)) { + final Ship ship = VSGameUtilsKt.getShipManagingPos(this.world, instance); + final Vector3d tempVec = VSGameUtilsKt.toWorldCoordinates(ship, instance); + blockPos = BlockPos.containing(tempVec.x, tempVec.y, tempVec.z); + } + return blockPos.closerThan(vec3i, v); + } + + @Inject( + method = "applySettings(Lnet/minecraft/server/level/ServerPlayer;Lcom/simibubi/create/content/trains/track/TrackBlockEntity;)V", + at = @At("HEAD"), locals = LocalCapture.CAPTURE_FAILHARD + ) + private void injectCaptureLevel(final ServerPlayer player, final TrackBlockEntity te, final CallbackInfo ci) { + this.world = player.level(); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinSuperGlueRemovalPacket.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinSuperGlueRemovalPacket.java new file mode 100644 index 000000000..51201bd99 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinSuperGlueRemovalPacket.java @@ -0,0 +1,28 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.packets; + +import com.simibubi.create.content.contraptions.glue.SuperGlueRemovalPacket; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(SuperGlueRemovalPacket.class) +public abstract class MixinSuperGlueRemovalPacket { + @Redirect(method = "lambda$handle$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;distanceToSqr(Lnet/minecraft/world/phys/Vec3;)D")) + private double redirectPlayerDistanceToSqr(final ServerPlayer instance, final Vec3 vec3) { + Vec3 newVec3 = vec3; + if (VSGameUtilsKt.isBlockInShipyard(instance.level(), BlockPos.containing(vec3.x, vec3.y, vec3.z))) { + final Ship ship = VSGameUtilsKt.getShipManagingPos(instance.level(), vec3); + if (ship != null) { + newVec3 = VectorConversionsMCKt.toMinecraft(ship.getShipToWorld().transformPosition(new Vector3d(vec3.x, vec3.y, vec3.z))); + } + } + return instance.distanceToSqr(newVec3); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinTileEntityConfigurationPacket.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinTileEntityConfigurationPacket.java new file mode 100644 index 000000000..c60ce8636 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinTileEntityConfigurationPacket.java @@ -0,0 +1,48 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.packets; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.world.level.Level; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(BlockEntityConfigurationPacket.class) +public abstract class MixinTileEntityConfigurationPacket { + @Unique + private Level _clockworkLevel; + + @Redirect( + method = "lambda$handle$0", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/core/BlockPos;closerThan(Lnet/minecraft/core/Vec3i;D)Z" + ) + ) + private boolean redirectCloserThan(final BlockPos instance, final Vec3i vec3i, final double v) { + BlockPos blockPos = instance; + if (VSGameUtilsKt.isBlockInShipyard(this._clockworkLevel, instance)) { + final Ship ship = VSGameUtilsKt.getShipManagingPos(this._clockworkLevel, instance); + final Vector3d tempVec = VSGameUtilsKt.toWorldCoordinates(ship, instance); + blockPos = BlockPos.containing(tempVec.x, tempVec.y, tempVec.z); + } + return blockPos.closerThan(vec3i, v); + } + + @Redirect( + method = "lambda$handle$0", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/Level;isLoaded(Lnet/minecraft/core/BlockPos;)Z" + ) + ) + private boolean injectCaptureLevel(final Level instance, final BlockPos pos) { + this._clockworkLevel = instance; + return instance.isLoaded(pos); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinTrainRelocationPacket.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinTrainRelocationPacket.java new file mode 100644 index 000000000..c46630797 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/packets/MixinTrainRelocationPacket.java @@ -0,0 +1,34 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.packets; + +import com.simibubi.create.content.trains.entity.TrainRelocationPacket; +import net.minecraft.core.Position; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(TrainRelocationPacket.class) +public abstract class MixinTrainRelocationPacket { + @Unique + private Level level; + + @Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;closerThan(Lnet/minecraft/core/Position;D)Z")) + private boolean redirectCloserThan(final Vec3 instance, final Position arg, final double d) { + Vec3 newVec3 = (Vec3) arg; + final Ship ship = VSGameUtilsKt.getShipManagingPos(this.level, arg); + if (ship != null) { + newVec3 = VSGameUtilsKt.toWorldCoordinates(ship, (Vec3) arg); + } + return instance.closerThan(newVec3, d); + } + + @Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntity(I)Lnet/minecraft/world/entity/Entity;")) + private Entity stealLevel(Level instance, int i) { + return (level = instance).getEntity(i); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/pr/MixinSeatBlock.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/pr/MixinSeatBlock.java new file mode 100644 index 000000000..5da93a395 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/pr/MixinSeatBlock.java @@ -0,0 +1,64 @@ +package org.valkyrienskies.mod.mixin.mod_compat.create.pr; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.simibubi.create.content.contraptions.actors.seat.SeatBlock; +import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import org.joml.Vector3d; +import org.joml.Vector3dc; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.EntityDraggingInformation; +import org.valkyrienskies.mod.common.util.IEntityDraggingInformationProvider; + +@Mixin(SeatBlock.class) +public abstract class MixinSeatBlock extends Block { + public MixinSeatBlock(final Properties properties) { + super(properties); + } + + /** + * Use doubles instead of floats when invoking setPos() + */ + @WrapOperation(method = "sitDown", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/actors/seat/SeatEntity;setPos(DDD)V")) + private static void wrapSitDownSetPos(final SeatEntity seatEntity, final double origX, final double origY, final double origZ, final Operation setPosOperation, final Level world, final BlockPos pos, final Entity entity) { + setPosOperation.call(seatEntity, pos.getX() + .5, (double) pos.getY(), pos.getZ() + .5); + } + + /** + * @author Triode + * @reason Fix entities not sitting in seats on ships + */ + @WrapOperation( + method = "updateEntityAfterFallOn", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/Entity;blockPosition()Lnet/minecraft/core/BlockPos;" + ), + remap = false + ) + private BlockPos wrapBlockPosInUpdateEntityAfterFallOn( + final Entity entity, + final Operation getBlockPosition + ) { + final EntityDraggingInformation draggingInformation = ((IEntityDraggingInformationProvider) entity).getDraggingInformation(); + if (draggingInformation.isEntityBeingDraggedByAShip()) { + final Long shipStandingOnId = draggingInformation.getLastShipStoodOn(); + if (shipStandingOnId != null) { + final Ship ship = VSGameUtilsKt.getShipObjectWorld(entity.level).getLoadedShips().getById(shipStandingOnId); + if (ship != null) { + final Vector3dc posInShip = ship.getTransform().getWorldToShip() + .transformPosition(entity.getX(), entity.getY(), entity.getZ(), new Vector3d()); + return new BlockPos(posInShip.x(), posInShip.y(), posInShip.z()); + } + } + } + return getBlockPosition.call(entity); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create_big_cannons/MixinAbstractCannonProjectile.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create_big_cannons/MixinAbstractCannonProjectile.java deleted file mode 100644 index 3100dcd9d..000000000 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create_big_cannons/MixinAbstractCannonProjectile.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.valkyrienskies.mod.mixin.mod_compat.create_big_cannons; - -/* -import net.minecraft.world.entity.projectile.Projectile; -import net.minecraft.world.phys.Vec3; -import org.joml.primitives.AABBd; -import org.joml.primitives.AABBdc; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Pseudo; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.valkyrienskies.core.api.ships.Ship; -import org.valkyrienskies.mod.common.VSGameUtilsKt; -import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; - -/** - * Make this pseudo so that we don't need CBC as a compile-dependency - */ -/* -@Pseudo -@Mixin(targets = "rbasamoyai.createbigcannons.munitions.AbstractCannonProjectile") -public abstract class MixinAbstractCannonProjectile { - - @Shadow - protected abstract void clipAndDamage(Vec3 start, Vec3 end); - - @Unique - private void shipClipAndDamage(final Vec3 startInWorld, final Vec3 endInWorld, - final Projectile projectile) { - final AABBdc pathAABB = new AABBd(VectorConversionsMCKt.toJOML(startInWorld), - VectorConversionsMCKt.toJOML(endInWorld)).correctBounds(); - - for (final Ship ship : VSGameUtilsKt.getShipsIntersecting(projectile.level, pathAABB)) { - final Vec3 start = VectorConversionsMCKt.toMinecraft( - ship.getTransform().getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(startInWorld))); - final Vec3 end = VectorConversionsMCKt.toMinecraft( - ship.getTransform().getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(endInWorld))); - clipAndDamage(start, end); - } - } - - @Inject(method = "clipAndDamage", at = @At("HEAD"), remap = false) - protected void vsClipAndDamage(final Vec3 start, final Vec3 end, final CallbackInfo ci) { - shipClipAndDamage(start, end, Projectile.class.cast(this)); - } -} -*/ diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create_big_cannons/MixinPitchOrientedContraptionEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create_big_cannons/MixinPitchOrientedContraptionEntity.java index 6aea9cb99..bc569f5ee 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create_big_cannons/MixinPitchOrientedContraptionEntity.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create_big_cannons/MixinPitchOrientedContraptionEntity.java @@ -1,7 +1,6 @@ package org.valkyrienskies.mod.mixin.mod_compat.create_big_cannons; -/* -import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; @@ -19,7 +18,6 @@ import org.valkyrienskies.mod.common.VSGameUtilsKt; import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; - @Pseudo @Mixin(targets = "rbasamoyai.createbigcannons.cannon_control.contraption.PitchOrientedContraptionEntity") public abstract class MixinPitchOrientedContraptionEntity extends OrientedContraptionEntity { @@ -39,7 +37,7 @@ protected void vsProcesssRiderPositionHook( if (original != null && controllerPos != null) { final Vector3d editOriginal = VectorConversionsMCKt.toJOML(original); - final Ship ship = VSGameUtilsKt.getShipObjectManagingPos(level, controllerPos); + final Ship ship = VSGameUtilsKt.getShipObjectManagingPos(level(), controllerPos); if (ship != null) { ship.getShipToWorld().transformPosition(editOriginal); @@ -51,4 +49,3 @@ protected void vsProcesssRiderPositionHook( } } } -*/ diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinBlockEntityInstanceManager.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinBlockEntityInstanceManager.java index 6a252f0b2..6b06bb20f 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinBlockEntityInstanceManager.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinBlockEntityInstanceManager.java @@ -5,6 +5,7 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; +import com.jozufozu.flywheel.backend.instancing.RenderDispatcher; import com.jozufozu.flywheel.backend.instancing.batching.BatchingEngine; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine; @@ -24,7 +25,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.valkyrienskies.core.api.ships.ClientShip; -import org.valkyrienskies.core.api.world.LevelYRange; import org.valkyrienskies.mod.common.VSGameUtilsKt; import org.valkyrienskies.mod.mixinducks.MixinBlockEntityInstanceManagerDuck; @@ -34,12 +34,8 @@ public abstract class MixinBlockEntityInstanceManager extends InstanceManager implements MixinBlockEntityInstanceManagerDuck { - public WeakHashMap getShipMaterialManagers() { - return shipMaterialManagers; - } - @Unique - private final WeakHashMap shipMaterialManagers = + private final WeakHashMap vs$shipMaterialManagers = new WeakHashMap<>(); public MixinBlockEntityInstanceManager(final MaterialManager materialManager) { @@ -58,18 +54,31 @@ void preCreateRaw(final BlockEntity blockEntity, final CallbackInfoReturnable createMaterialManager()); + vs$shipMaterialManagers.computeIfAbsent(ship, k -> vs$createMaterialManager()); final Vector3i c = - ship.getChunkClaim().getCenterBlockCoordinates(new LevelYRange(0, 0), new Vector3i()); - ((InstancingEngineAccessor) manager).setOriginCoordinate(new BlockPos(c.x, c.y, c.z)); + ship.getChunkClaim().getCenterBlockCoordinates(VSGameUtilsKt.getYRange(nullableLevel), new Vector3i()); + ((InstancingEngineAccessor) manager).setOriginCoordinate(BlockPos.containing(c.x, c.y, c.z)); cir.setReturnValue(InstancedRenderRegistry.createInstance(manager, blockEntity)); } } } + @Override + public WeakHashMap vs$getShipMaterialManagers() { + return vs$shipMaterialManagers; + } + + @Override + public void vs$removeShipManager(final ClientShip clientShip) { + final MaterialManager removed = vs$shipMaterialManagers.remove(clientShip); + if (removed instanceof final RenderDispatcher removedRenderer) { + removedRenderer.delete(); + } + } + @Unique - private MaterialManager createMaterialManager() { + private MaterialManager vs$createMaterialManager() { if (Backend.getBackendType() == BackendType.INSTANCING) { return InstancingEngine.builder(Contexts.WORLD).build(); } else if (Backend.getBackendType() == BackendType.BATCHING) { diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinInstanceWorld.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinInstanceWorld.java index 52116092d..8631440b1 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinInstanceWorld.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinInstanceWorld.java @@ -23,6 +23,7 @@ import org.valkyrienskies.core.api.ships.ClientShip; import org.valkyrienskies.mod.common.VSClientGameUtils; import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; +import org.valkyrienskies.mod.compat.FlywheelEvents; import org.valkyrienskies.mod.mixinducks.MixinBlockEntityInstanceManagerDuck; import org.valkyrienskies.mod.mixinducks.MixinInstancingEngineDuck; @@ -49,17 +50,15 @@ void renderShipTiles(final RenderLayerEvent event, final CallbackInfo ci) { //not sure if restoreState stuff should be here or in the ((MixinInstancingEngineDuck) manager).render() method final GlStateTracker.State restoreState = GlStateTracker.getRestoreState(); final var shipManagers = - ((MixinBlockEntityInstanceManagerDuck) blockEntityInstanceManager).getShipMaterialManagers(); + ((MixinBlockEntityInstanceManagerDuck) blockEntityInstanceManager).vs$getShipMaterialManagers(); - shipManagers.forEach((ship, manager) -> { - render(ship, manager, event); - }); + shipManagers.forEach((ship, manager) -> vs$render(ship, manager, event)); restoreState.restore(); } @Unique - void render(final ClientShip ship, final MaterialManager manager, final RenderLayerEvent event) { - if (manager instanceof InstancingEngine engine) { + private void vs$render(final ClientShip ship, final MaterialManager manager, final RenderLayerEvent event) { + if (manager instanceof final InstancingEngine engine) { final Vector3d origin = VectorConversionsMCKt.toJOMLD(engine.getOriginCoordinate()); final Matrix4d viewProjection = new Matrix4d(event.viewProjection); @@ -76,14 +75,14 @@ void render(final ClientShip ship, final MaterialManager manager, final RenderLa final Matrix4f fnlProj = new Matrix4f(finalProjection); - ((MixinInstancingEngineDuck) engine).render( + ((MixinInstancingEngineDuck) engine).vs$render( fnlProj, camInShipLocal.x, camInShipLocal.y, camInShipLocal.z, event.layer ); - } else if (manager instanceof BatchingEngine engine) { + } else if (manager instanceof final BatchingEngine engine) { event.stack.pushPose(); VSClientGameUtils.multiplyWithShipToWorld(event.stack, ship); engine.render(taskEngine, event); @@ -92,4 +91,14 @@ void render(final ClientShip ship, final MaterialManager manager, final RenderLa throw new IllegalArgumentException("unrecognized engine"); } } + + @Inject(method = "", at = @At("RETURN")) + private void postInit(final CallbackInfo ci) { + FlywheelEvents.onInstanceWorldLoad(InstanceWorld.class.cast(this)); + } + + @Inject(method = "delete", at = @At("RETURN")) + private void postDelete(final CallbackInfo ci) { + FlywheelEvents.onInstanceWorldUnload(InstanceWorld.class.cast(this)); + } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinInstancingEngine.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinInstancingEngine.java index f72100a66..fdc0f2f6b 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinInstancingEngine.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/flywheel/MixinInstancingEngine.java @@ -5,30 +5,22 @@ import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine; import com.jozufozu.flywheel.core.shader.WorldProgram; import java.util.stream.Stream; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.valkyrienskies.mod.mixinducks.MixinInstancingEngineDuck; @Pseudo @Mixin(value = InstancingEngine.class, remap = false) public abstract class MixinInstancingEngine

implements MixinInstancingEngineDuck { - @Unique - private static final Logger LOGGER = LogManager.getLogger("VS2 flywheel.client.MixinInstancingEngine"); - @Shadow protected abstract Stream> getGroupsToRender(@Nullable RenderLayer layer); @Override - public void render(final Matrix4f viewProjection, final double camX, final double camY, final double camZ, + public void vs$render(final Matrix4f viewProjection, final double camX, final double camY, final double camZ, final RenderLayer layer) { - this.getGroupsToRender(layer).forEach(g -> { - g.render(viewProjection, camX, camY, camZ, layer); - }); + this.getGroupsToRender(layer).forEach(g -> g.render(viewProjection, camX, camY, camZ, layer)); } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/ftb_chunks/MixinClaimedChunkManager.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/ftb_chunks/MixinClaimedChunkManager.java index 3090ef55c..4767bfcd9 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/ftb_chunks/MixinClaimedChunkManager.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/ftb_chunks/MixinClaimedChunkManager.java @@ -41,7 +41,7 @@ public abstract class MixinClaimedChunkManager { return pos; } - final Level level = entity.level; + final Level level = entity.level(); final Ship ship = VSGameUtilsKt.getShipManagingPos(level, pos); if (ship == null) { @@ -49,7 +49,7 @@ public abstract class MixinClaimedChunkManager { } final Vector3d vec = ship.getShipToWorld().transformPosition(new Vector3d(pos.getX(), pos.getY(), pos.getZ())); - final BlockPos newPos = new BlockPos(VectorConversionsMCKt.toMinecraft(vec)); + final BlockPos newPos = BlockPos.containing(VectorConversionsMCKt.toMinecraft(vec)); if ( (newPos.getY() > level.getMaxBuildHeight() || newPos.getY() < level.getMinBuildHeight()) && diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine/MixinLevelRendererOptifine.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine/MixinLevelRendererOptifine.java index 0590494e2..1e1543233 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine/MixinLevelRendererOptifine.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine/MixinLevelRendererOptifine.java @@ -115,7 +115,7 @@ // final VboRegion vboRegion, final CallbackInfo ci // ) { // final ClientShip shipObject = -// VSGameUtilsKt.getShipObjectManagingPos(level, new BlockPos(regionX, regionY, regionZ)); +// VSGameUtilsKt.getShipObjectManagingPos(level, BlockPos.containing(regionX, regionY, regionZ)); // if (shipObject != null) { // final Matrix4d chunkTransformMatrix = new Matrix4d() // .translate(-xIn, -yIn, -zIn) @@ -165,7 +165,7 @@ // private void addShipVisibleChunksForBlockEntitiesAndEntities( // final Camera camera, final Frustum frustum, final boolean hasForcedFrustum, final int frame, // final boolean spectator, final CallbackInfo ci) { -// final BlockPos.MutableBlockPos tempPos = new BlockPos.MutableBlockPos(); +// final BlockPos.MutableBlockPos tempPos = BlockPos.containing.MutableBlockPos(); // final ViewAreaAccessor chunkStorageAccessor = (ViewAreaAccessor) viewArea; // for (final ClientShip shipObject : VSGameUtilsKt.getShipObjectWorld(level).getLoadedShips()) { // // Don't bother rendering the ship if its AABB isn't visible to the frustum diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine/MixinViewAreaOptifine.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine/MixinViewAreaOptifine.java index 965d69457..b2b130a69 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine/MixinViewAreaOptifine.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine/MixinViewAreaOptifine.java @@ -1,150 +1,152 @@ -package org.valkyrienskies.mod.mixin.mod_compat.optifine; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import java.util.Map; -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.ViewArea; -import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; -import net.minecraft.core.BlockPos; -import net.minecraft.util.Mth; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.optifine.Config; -import net.optifine.render.VboRegion; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.valkyrienskies.mod.common.VSGameUtilsKt; -import org.valkyrienskies.mod.mixinducks.client.render.IVSViewAreaMethods; +//package org.valkyrienskies.mod.mixin.mod_compat.optifine; +// +//import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +//import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; +//import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +//import java.util.Map; +//import net.minecraft.client.renderer.LevelRenderer; +//import net.minecraft.client.renderer.ViewArea; +//import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; +//import net.minecraft.core.BlockPos; +//import net.minecraft.util.Mth; +//import net.minecraft.world.level.ChunkPos; +//import net.minecraft.world.level.Level; +//import net.optifine.Config; +//import net.optifine.render.VboRegion; +//import org.spongepowered.asm.mixin.Final; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Shadow; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.Inject; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +//import org.valkyrienskies.mod.common.VSGameUtilsKt; +//import org.valkyrienskies.mod.mixinducks.client.render.IVSViewAreaMethods; +// +///** +// * The purpose of this mixin is to allow {@link ViewArea} to render ship chunks. +// */ +//@Mixin(ViewArea.class) +//public abstract class MixinViewAreaOptifine implements IVSViewAreaMethods { +// +// // Maps chunk position to an array of BuiltChunk, indexed by the y value. +// private final Long2ObjectMap vs$shipRenderChunks = +// new Long2ObjectOpenHashMap<>(); +// @Shadow +// @Final +// protected Level level; +// @Shadow +// protected int chunkGridSizeY; +// // This creates render chunks +// private ChunkRenderDispatcher vs$chunkBuilder; +// +// /** +// * This mixin stores the [chunkBuilder] object from the constructor. It is used to create new render chunks. +// */ +// @Inject(method = "", at = @At("TAIL")) +// private void postInit(final ChunkRenderDispatcher chunkBuilder, final Level world, final int viewDistance, +// final LevelRenderer worldRenderer, final CallbackInfo callbackInfo) { +// +// this.vs$chunkBuilder = chunkBuilder; +// } +// +// @Shadow(remap = false) +// protected abstract void updateVboRegion(ChunkRenderDispatcher.RenderChunk renderChunk); +// +// /** +// * This mixin creates render chunks for ship chunks. +// */ +// @Inject(method = "setDirty", at = @At("HEAD"), cancellable = true) +// private void preScheduleRebuild(final int x, final int y, final int z, final boolean important, +// final CallbackInfo callbackInfo) { +// +// if (y < 0 || y >= chunkGridSizeY) { +// return; // Weird, but just ignore it +// } +// if (VSGameUtilsKt.isChunkInShipyard(level, x, z)) { +// final long chunkPosAsLong = ChunkPos.asLong(x, z); +// final ChunkRenderDispatcher.RenderChunk[] renderChunksArray = +// vs$shipRenderChunks.computeIfAbsent(chunkPosAsLong, +// k -> new ChunkRenderDispatcher.RenderChunk[chunkGridSizeY]); +// +// if (renderChunksArray[y] == null) { +// final ChunkRenderDispatcher.RenderChunk builtChunk = +// vs$chunkBuilder.new RenderChunk(0, x << 4, y << 4, z << 4); +// renderChunksArray[y] = builtChunk; +// if (Config.isVbo() && Config.isRenderRegions()) { +// updateVboRegion(renderChunksArray[y]); +// } +// } +// +// renderChunksArray[y].setDirty(important); +// callbackInfo.cancel(); +// } +// } +// +// /** +// * This mixin allows {@link ViewArea} to return the render chunks for ships. +// */ +// @Inject(method = "getRenderChunkAt", at = @At("HEAD"), cancellable = true) +// private void preGetRenderedChunk(final BlockPos pos, +// final CallbackInfoReturnable callbackInfoReturnable) { +// final int chunkX = Mth.floorDiv(pos.getX(), 16); +// final int chunkY = Mth.floorDiv(pos.getY(), 16); +// final int chunkZ = Mth.floorDiv(pos.getZ(), 16); +// +// if (chunkY < 0 || chunkY >= chunkGridSizeY) { +// return; // Weird, but ignore it +// } +// +// if (VSGameUtilsKt.isChunkInShipyard(level, chunkX, chunkZ)) { +// final long chunkPosAsLong = ChunkPos.asLong(chunkX, chunkZ); +// final ChunkRenderDispatcher.RenderChunk[] renderChunksArray = vs$shipRenderChunks.get(chunkPosAsLong); +// if (renderChunksArray == null) { +// callbackInfoReturnable.setReturnValue(null); +// return; +// } +// final ChunkRenderDispatcher.RenderChunk renderChunk = renderChunksArray[chunkY]; +// callbackInfoReturnable.setReturnValue(renderChunk); +// } +// } +// +// @Shadow(remap = false) +// private Map mapVboRegions; +// +// @Override +// public void unloadChunk(final int chunkX, final int chunkZ) { +// if (VSGameUtilsKt.isChunkInShipyard(level, chunkX, chunkZ)) { +// final ChunkRenderDispatcher.RenderChunk[] chunks = +// vs$shipRenderChunks.remove(ChunkPos.asLong(chunkX, chunkZ)); +// if (chunks != null) { +// for (final ChunkRenderDispatcher.RenderChunk chunk : chunks) { +// chunk.releaseBuffers(); +// } +// } +// final VboRegion[] vboRegions = mapVboRegions.remove(new ChunkPos(chunkX, chunkZ)); +// if (vboRegions != null) { +// for (final VboRegion vboRegion : vboRegions) { +// if (vboRegion != null) { +// vboRegion.deleteGlBuffers(); +// } +// } +// } +// } +// } +// +// /** +// * Clear VS ship render chunks so that we don't leak memory +// */ +// @Inject(method = "releaseAllBuffers", at = @At("HEAD")) +// private void postReleaseAllBuffers(final CallbackInfo ci) { +// for (final Entry entry : vs$shipRenderChunks.long2ObjectEntrySet()) { +// for (final ChunkRenderDispatcher.RenderChunk renderChunk : entry.getValue()) { +// if (renderChunk != null) { +// renderChunk.releaseBuffers(); +// } +// } +// } +// vs$shipRenderChunks.clear(); +// } +//} -/** - * The purpose of this mixin is to allow {@link ViewArea} to render ship chunks. - */ -@Mixin(ViewArea.class) -public abstract class MixinViewAreaOptifine implements IVSViewAreaMethods { - - // Maps chunk position to an array of BuiltChunk, indexed by the y value. - private final Long2ObjectMap vs$shipRenderChunks = - new Long2ObjectOpenHashMap<>(); - @Shadow - @Final - protected Level level; - @Shadow - protected int chunkGridSizeY; - // This creates render chunks - private ChunkRenderDispatcher vs$chunkBuilder; - - /** - * This mixin stores the [chunkBuilder] object from the constructor. It is used to create new render chunks. - */ - @Inject(method = "", at = @At("TAIL")) - private void postInit(final ChunkRenderDispatcher chunkBuilder, final Level world, final int viewDistance, - final LevelRenderer worldRenderer, final CallbackInfo callbackInfo) { - - this.vs$chunkBuilder = chunkBuilder; - } - - @Shadow(remap = false) - protected abstract void updateVboRegion(ChunkRenderDispatcher.RenderChunk renderChunk); - - /** - * This mixin creates render chunks for ship chunks. - */ - @Inject(method = "setDirty", at = @At("HEAD"), cancellable = true) - private void preScheduleRebuild(final int x, final int y, final int z, final boolean important, - final CallbackInfo callbackInfo) { - - if (y < 0 || y >= chunkGridSizeY) { - return; // Weird, but just ignore it - } - if (VSGameUtilsKt.isChunkInShipyard(level, x, z)) { - final long chunkPosAsLong = ChunkPos.asLong(x, z); - final ChunkRenderDispatcher.RenderChunk[] renderChunksArray = - vs$shipRenderChunks.computeIfAbsent(chunkPosAsLong, - k -> new ChunkRenderDispatcher.RenderChunk[chunkGridSizeY]); - - if (renderChunksArray[y] == null) { - final ChunkRenderDispatcher.RenderChunk builtChunk = - vs$chunkBuilder.new RenderChunk(0, x << 4, y << 4, z << 4); - renderChunksArray[y] = builtChunk; - if (Config.isVbo() && Config.isRenderRegions()) { - updateVboRegion(renderChunksArray[y]); - } - } - - renderChunksArray[y].setDirty(important); - callbackInfo.cancel(); - } - } - - /** - * This mixin allows {@link ViewArea} to return the render chunks for ships. - */ - @Inject(method = "getRenderChunkAt", at = @At("HEAD"), cancellable = true) - private void preGetRenderedChunk(final BlockPos pos, - final CallbackInfoReturnable callbackInfoReturnable) { - final int chunkX = Mth.floorDiv(pos.getX(), 16); - final int chunkY = Mth.floorDiv(pos.getY(), 16); - final int chunkZ = Mth.floorDiv(pos.getZ(), 16); - - if (chunkY < 0 || chunkY >= chunkGridSizeY) { - return; // Weird, but ignore it - } - - if (VSGameUtilsKt.isChunkInShipyard(level, chunkX, chunkZ)) { - final long chunkPosAsLong = ChunkPos.asLong(chunkX, chunkZ); - final ChunkRenderDispatcher.RenderChunk[] renderChunksArray = vs$shipRenderChunks.get(chunkPosAsLong); - if (renderChunksArray == null) { - callbackInfoReturnable.setReturnValue(null); - return; - } - final ChunkRenderDispatcher.RenderChunk renderChunk = renderChunksArray[chunkY]; - callbackInfoReturnable.setReturnValue(renderChunk); - } - } - - @Shadow(remap = false) - private Map mapVboRegions; - - @Override - public void unloadChunk(final int chunkX, final int chunkZ) { - if (VSGameUtilsKt.isChunkInShipyard(level, chunkX, chunkZ)) { - final ChunkRenderDispatcher.RenderChunk[] chunks = - vs$shipRenderChunks.remove(ChunkPos.asLong(chunkX, chunkZ)); - if (chunks != null) { - for (final ChunkRenderDispatcher.RenderChunk chunk : chunks) { - chunk.releaseBuffers(); - } - } - final VboRegion[] vboRegions = mapVboRegions.remove(new ChunkPos(chunkX, chunkZ)); - if (vboRegions != null) { - for (final VboRegion vboRegion : vboRegions) { - if (vboRegion != null) { - vboRegion.deleteGlBuffers(); - } - } - } - } - } - - /** - * Clear VS ship render chunks so that we don't leak memory - */ - @Inject(method = "releaseAllBuffers", at = @At("HEAD")) - private void postReleaseAllBuffers(final CallbackInfo ci) { - for (final Entry entry : vs$shipRenderChunks.long2ObjectEntrySet()) { - for (final ChunkRenderDispatcher.RenderChunk renderChunk : entry.getValue()) { - if (renderChunk != null) { - renderChunk.releaseBuffers(); - } - } - } - vs$shipRenderChunks.clear(); - } -} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine_vanilla/MixinLevelRenderer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine_vanilla/MixinLevelRenderer.java index 9f727d691..8e58f1908 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine_vanilla/MixinLevelRenderer.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/optifine_vanilla/MixinLevelRenderer.java @@ -48,7 +48,7 @@ public abstract class MixinLevelRenderer { ) ) private void afterRefresh(final CallbackInfo ci) { - ((ClientChunkCacheDuck) this.level.getChunkSource()).vs_getShipChunks().forEach((pos, chunk) -> { + ((ClientChunkCacheDuck) this.level.getChunkSource()).vs$getShipChunks().forEach((pos, chunk) -> { for (int y = level.getMinSection(); y < level.getMaxSection(); y++) { viewArea.setDirty(ChunkPos.getX(pos), y, ChunkPos.getZ(pos), false); } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/reachentityattributes/MixinReachEntityAttributes.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/reachentityattributes/MixinReachEntityAttributes.java new file mode 100644 index 000000000..d6f48d905 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/reachentityattributes/MixinReachEntityAttributes.java @@ -0,0 +1,41 @@ +package org.valkyrienskies.mod.mixin.mod_compat.reachentityattributes; + +import com.jamieswhiteshirt.reachentityattributes.ReachEntityAttributes; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.Shadow; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Pseudo +@Mixin(ReachEntityAttributes.class) +public class MixinReachEntityAttributes { + @Shadow + public static double getReachDistance(final LivingEntity entity, final double baseReachDistance) { + return 0.0; + } + + /** + * @author Triode + * @reason Fix getting players within reach of ship blocks + */ + @Overwrite + public static List getPlayersWithinReach(final Predicate viewerPredicate, final Level world, final int x, final int y, final int z, final double baseReachDistance) { + final List playersWithinReach = new ArrayList<>(0); + for (final Player player : world.players()) { + if (viewerPredicate.test(player)) { + final var reach = getReachDistance(player, baseReachDistance); + if (VSGameUtilsKt.squaredDistanceBetweenInclShips(world, x + 0.5, y + 0.5, z + 0.5, player.getX(), player.getEyeY(), player.getZ()) <= (reach * reach)) { + playersWithinReach.add(player); + } + } + } + return playersWithinReach; + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/sodium/MixinSodiumWorldRenderer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/sodium/MixinSodiumWorldRenderer.java index a70ed2137..fd894a38a 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/sodium/MixinSodiumWorldRenderer.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/sodium/MixinSodiumWorldRenderer.java @@ -18,7 +18,9 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.valkyrienskies.core.api.ships.ClientShip; import org.valkyrienskies.mod.common.VSGameUtilsKt; @@ -48,4 +50,13 @@ private void renderShipChunkBlockEntity(final BlockEntityRenderDispatcher instan instance.render(blockEntity, tickDelta, matrixStack, buffer); } + /** + * Fix entities in ships not rendering when Sodium is installed + */ + @Inject(method = "doesChunkHaveFlag", at = @At("HEAD"), cancellable = true, remap = false) + private void preDoesChunkHaveFlag(final int x, final int z, final int status, final CallbackInfoReturnable cir) { + if (VSGameUtilsKt.isChunkInShipyard(world, x, z)) { + cir.setReturnValue(true); + } + } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java index 847509901..6294d134f 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java @@ -1,15 +1,32 @@ package org.valkyrienskies.mod.mixin.server; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; -import java.util.function.BooleanSupplier; import java.util.stream.Collectors; import kotlin.Unit; +import net.minecraft.BlockUtil; +import net.minecraft.BlockUtil.FoundRectangle; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.players.PlayerList; +import net.minecraft.world.entity.EntityDimensions; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.border.WorldBorder; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.portal.PortalShape; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -18,6 +35,8 @@ import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.properties.IShipActiveChunksSet; +import org.valkyrienskies.core.apigame.GameServer; import org.valkyrienskies.core.apigame.world.IPlayer; import org.valkyrienskies.core.apigame.world.ServerShipWorldCore; import org.valkyrienskies.core.apigame.world.VSPipeline; @@ -25,13 +44,16 @@ import org.valkyrienskies.mod.common.ShipSavedData; import org.valkyrienskies.mod.common.VSGameUtilsKt; import org.valkyrienskies.mod.common.ValkyrienSkiesMod; +import org.valkyrienskies.mod.common.config.MassDatapackResolver; import org.valkyrienskies.mod.common.hooks.VSGameEvents; import org.valkyrienskies.mod.common.util.EntityDragger; +import org.valkyrienskies.mod.common.util.VSLevelChunk; +import org.valkyrienskies.mod.common.util.VSServerLevel; import org.valkyrienskies.mod.common.world.ChunkManagement; import org.valkyrienskies.mod.util.KrunchSupport; @Mixin(MinecraftServer.class) -public abstract class MixinMinecraftServer implements IShipObjectWorldServerProvider { +public abstract class MixinMinecraftServer implements IShipObjectWorldServerProvider, GameServer { @Shadow private PlayerList playerList; @@ -47,8 +69,12 @@ public abstract class MixinMinecraftServer implements IShipObjectWorldServerProv @Unique private VSPipeline vsPipeline; + @Unique private Set loadedLevels = new HashSet<>(); + @Unique + private final Map dimensionToLevelMap = new HashMap<>(); + @Inject( at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;initServer()Z"), method = "runServer" @@ -62,17 +88,6 @@ private void afterStopServer(final CallbackInfo ci) { ValkyrienSkiesMod.setCurrentServer(null); } - @Inject( - at = @At("HEAD"), - method = "tickServer" - ) - public void onTick(final BooleanSupplier booleanSupplier, final CallbackInfo ci) { - final Set vsPlayers = playerList.getPlayers().stream() - .map(VSGameUtilsKt::getPlayerWrapper).collect(Collectors.toSet()); - - shipWorld.setPlayers(vsPlayers); - } - @Nullable @Override public ServerShipWorldCore getShipObjectWorld() { @@ -113,9 +128,22 @@ private void postCreateLevels(final CallbackInfo ci) { // Create ship world and VS Pipeline vsPipeline = shipSavedData.getPipeline(); + // Register blocks + if (!MassDatapackResolver.INSTANCE.getRegisteredBlocks()) { + final List blockStateList = new ArrayList<>(Block.BLOCK_STATE_REGISTRY.size()); + Block.BLOCK_STATE_REGISTRY.forEach((blockStateList::add)); + MassDatapackResolver.INSTANCE.registerAllBlockStates(blockStateList); + } + vsPipeline.registerBlocks( + MassDatapackResolver.INSTANCE.getSolidBlockStates(), + MassDatapackResolver.INSTANCE.getLiquidBlockStates(), + MassDatapackResolver.INSTANCE.getBlockStateData() + ); + KrunchSupport.INSTANCE.setKrunchSupported(!vsPipeline.isUsingDummyPhysics()); shipWorld = vsPipeline.getShipWorld(); + shipWorld.setGameServer(this); VSGameEvents.INSTANCE.getRegistriesCompleted().emit(Unit.INSTANCE); @@ -130,10 +158,17 @@ private void postCreateLevels(final CallbackInfo ci) { at = @At("HEAD") ) private void preTick(final CallbackInfo ci) { + final Set vsPlayers = playerList.getPlayers().stream() + .map(VSGameUtilsKt::getPlayerWrapper).collect(Collectors.toSet()); + + shipWorld.setPlayers(vsPlayers); + // region Tell the VS world to load new levels, and unload deleted ones final Map newLoadedLevels = new HashMap<>(); for (final ServerLevel level : getAllLevels()) { - newLoadedLevels.put(VSGameUtilsKt.getDimensionId(level), level); + final String dimensionId = VSGameUtilsKt.getDimensionId(level); + newLoadedLevels.put(dimensionId, level); + dimensionToLevelMap.put(dimensionId, level); } /* for (final var entry : newLoadedLevels.entrySet()) { @@ -147,6 +182,7 @@ private void preTick(final CallbackInfo ci) { for (final String oldLoadedLevelId : loadedLevels) { if (!newLoadedLevels.containsKey(oldLoadedLevelId)) { shipWorld.removeDimension(oldLoadedLevelId); + dimensionToLevelMap.remove(oldLoadedLevelId); } } loadedLevels = newLoadedLevels.keySet(); @@ -170,6 +206,12 @@ private void preConnectionTick(final CallbackInfo ci) { ChunkManagement.tickChunkLoading(shipWorld, MinecraftServer.class.cast(this)); } + @Shadow + public abstract ServerLevel getLevel(ResourceKey resourceKey); + + @Shadow + public abstract boolean isNetherEnabled(); + @Inject( method = "tickServer", at = @At("TAIL") @@ -180,6 +222,135 @@ private void postTick(final CallbackInfo ci) { for (final ServerLevel level : getAllLevels()) { EntityDragger.INSTANCE.dragEntitiesWithShips(level.getAllEntities()); } + + //TODO must reimplement + // handleShipPortals(); + } +/* TODO must redo + @Unique + private void handleShipPortals() { + // Teleport ships that touch portals + final ArrayList loadedShipsCopy = new ArrayList<>(shipWorld.getLoadedShips()); + for (final LoadedServerShip shipObject : loadedShipsCopy) { + if (!ShipSettingsKt.getSettings(shipObject).getChangeDimensionOnTouchPortals()) { + // Only send ships through portals if it's enabled in settings + continue; + } + final ServerLevel level = dimensionToLevelMap.get(shipObject.getChunkClaimDimension()); + final Vector3dc shipPos = shipObject.getTransform().getPositionInWorld(); + final double bbRadius = 0.5; + final BlockPos blockPos = BlockPos.containing(shipPos.x() - bbRadius, shipPos.y() - bbRadius, shipPos.z() - bbRadius); + final BlockPos blockPos2 = BlockPos.containing(shipPos.x() + bbRadius, shipPos.y() + bbRadius, shipPos.z() + bbRadius); + // Only run this code if the chunks between blockPos and blockPos2 are loaded + if (level.hasChunksAt(blockPos, blockPos2)) { + shipObject.decayPortalCoolDown(); + + final BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + for (int i = blockPos.getX(); i <= blockPos2.getX(); ++i) { + for (int j = blockPos.getY(); j <= blockPos2.getY(); ++j) { + for (int k = blockPos.getZ(); k <= blockPos2.getZ(); ++k) { + mutableBlockPos.set(i, j, k); + final BlockState blockState = level.getBlockState(mutableBlockPos); + if (blockState.getBlock() == Blocks.NETHER_PORTAL) { + // Handle nether portal teleport + if (!shipObject.isOnPortalCoolDown()) { + // Move the ship between dimensions + final ServerLevel destLevel = getLevel(level.dimension() == Level.NETHER ? Level.OVERWORLD : Level.NETHER); + // TODO: Do we want portal time? + if (destLevel != null && isNetherEnabled()) { // && this.portalTime++ >= i) { + level.getProfiler().push("portal"); + shipChangeDimension(level, destLevel, mutableBlockPos, shipObject); + level.getProfiler().pop(); + } + } + shipObject.handleInsidePortal(); + } else if (blockState.getBlock() == Blocks.END_PORTAL) { + // Handle end portal teleport + final ServerLevel destLevel = level.getServer().getLevel(level.dimension() == Level.END ? Level.OVERWORLD : Level.END); + if (destLevel == null) { + return; + } + shipChangeDimension(level, destLevel, null, shipObject); + } + } + } + } + } + } + } + + */ +/* TODO Must redo + @Unique + private void shipChangeDimension(@NotNull final ServerLevel srcLevel, @NotNull final ServerLevel destLevel, @Nullable final BlockPos portalEntrancePos, @NotNull final LoadedServerShip shipObject) { + final PortalInfo portalInfo = findDimensionEntryPoint(srcLevel, destLevel, portalEntrancePos, shipObject.getTransform().getPositionInWorld()); + if (portalInfo == null) { + // Getting portal info failed? Don't teleport. + return; + } + final ShipTeleportData shipTeleportData = new ShipTeleportDataImpl( + VectorConversionsMCKt.toJOML(portalInfo.pos), + shipObject.getTransform().getShipToWorldRotation(), + new Vector3d(), + new Vector3d(), + VSGameUtilsKt.getDimensionId(destLevel), + null + ); + shipWorld.teleportShip(shipObject, shipTeleportData); + } + + @Unique + @Nullable + private PortalInfo findDimensionEntryPoint(@NotNull final ServerLevel srcLevel, @NotNull final ServerLevel destLevel, @Nullable final BlockPos portalEntrancePos, @NotNull final Vector3dc shipPos) { + final boolean bl = srcLevel.dimension() == Level.END && destLevel.dimension() == Level.OVERWORLD; + final boolean bl2 = destLevel.dimension() == Level.END; + final Vec3 deltaMovement = Vec3.ZERO; + final EntityDimensions entityDimensions = new EntityDimensions(1.0f, 1.0f, true); + if (bl || bl2) { + final BlockPos blockPos = bl2 ? ServerLevel.END_SPAWN_POINT : destLevel.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destLevel.getSharedSpawnPos()); + return new PortalInfo(new Vec3((double)blockPos.getX() + 0.5, blockPos.getY(), (double)blockPos.getZ() + 0.5), deltaMovement, 0f, 0f); + } + final boolean bl3 = destLevel.dimension() == Level.NETHER; + if (srcLevel.dimension() != Level.NETHER && !bl3) { + return null; + } + final WorldBorder worldBorder = destLevel.getWorldBorder(); + final double d = DimensionType.getTeleportationScale(srcLevel.dimensionType(), destLevel.dimensionType()); + final BlockPos blockPos2 = worldBorder.clampToBounds(shipPos.x() * d, shipPos.y(), shipPos.z() * d); + return this.getExitPortal(destLevel, blockPos2, bl3, worldBorder).map(foundRectangle -> { + final Vec3 vec3; + final Direction.Axis axis; + if (portalEntrancePos != null) { + final BlockState blockState = srcLevel.getBlockState(portalEntrancePos); + if (blockState.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { + axis = blockState.getValue(BlockStateProperties.HORIZONTAL_AXIS); + final BlockUtil.FoundRectangle foundRectangle2 = + BlockUtil.getLargestRectangleAround(portalEntrancePos, axis, 21, Direction.Axis.Y, 21, + blockPos -> srcLevel.getBlockState(blockPos) == blockState); + vec3 = this.getRelativePortalPosition(axis, foundRectangle2, entityDimensions, + VectorConversionsMCKt.toMinecraft(shipPos)); + } else { + axis = Direction.Axis.X; + vec3 = new Vec3(0.5, 0.0, 0.0); + } + } else { + axis = Direction.Axis.X; + vec3 = new Vec3(0.5, 0.0, 0.0); + } + return PortalShape.createPortalInfo(destLevel, foundRectangle, axis, vec3, entityDimensions, deltaMovement, 0.0f, 0.0f); + }).orElse(null); + } + + */ + + @Unique + private Vec3 getRelativePortalPosition(final Direction.Axis axis, final BlockUtil.FoundRectangle foundRectangle, final EntityDimensions entityDimensions, final Vec3 position) { + return PortalShape.getRelativePosition(foundRectangle, axis, position, entityDimensions); + } + + @Unique + private Optional getExitPortal(final ServerLevel serverLevel, final BlockPos blockPos, final boolean bl, final WorldBorder worldBorder) { + return serverLevel.getPortalForcer().findPortalAround(blockPos, bl, worldBorder); } @Inject( @@ -189,7 +360,46 @@ private void postTick(final CallbackInfo ci) { private void preStopServer(final CallbackInfo ci) { if (vsPipeline != null) { vsPipeline.setDeleteResources(true); + vsPipeline.setArePhysicsRunning(true); } + dimensionToLevelMap.clear(); + shipWorld.setGameServer(null); shipWorld = null; } + + @NotNull + private ServerLevel getLevelFromDimensionId(@NotNull final String dimensionId) { + return dimensionToLevelMap.get(dimensionId); + } + + @Override + public void moveTerrainAcrossDimensions( + @NotNull final IShipActiveChunksSet shipChunks, + @NotNull final String srcDimension, + @NotNull final String destDimension + ) { + final ServerLevel srcLevel = getLevelFromDimensionId(srcDimension); + final ServerLevel destLevel = getLevelFromDimensionId(destDimension); + + // Copy ship chunks from srcLevel to destLevel + shipChunks.forEach((final int x, final int z) -> { + final LevelChunk srcChunk = srcLevel.getChunk(x, z); + + // This is a hack, but it fixes destLevel being in the wrong state + ((VSServerLevel) destLevel).removeChunk(x, z); + + final LevelChunk destChunk = destLevel.getChunk(x, z); + ((VSLevelChunk) destChunk).copyChunkFromOtherDimension((VSLevelChunk) srcChunk); + }); + + // Delete ship chunks from srcLevel + shipChunks.forEach((final int x, final int z) -> { + final LevelChunk srcChunk = srcLevel.getChunk(x, z); + ((VSLevelChunk) srcChunk).clearChunk(); + + final ChunkPos chunkPos = srcChunk.getPos(); + srcLevel.getChunkSource().updateChunkForced(chunkPos, false); + ((VSServerLevel) srcLevel).removeChunk(x, z); + }); + } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinPlayerList.java b/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinPlayerList.java index 0db15dee0..fdeafbfad 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinPlayerList.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinPlayerList.java @@ -52,10 +52,10 @@ private void afterPlayerJoin(final Connection netManager, final ServerPlayer pla if (!KrunchSupport.INSTANCE.isKrunchSupported()) { player.sendSystemMessage( Component.literal( - "VS 2 physics are disabled on this server, because Krunch is not supported on this server! " + + "VS2 physics are disabled on this server, because Krunch is not supported on this server!" + " Current supported platforms are:" + " Windows x86-64, Linux x86-64, Linux aarch64, Macos x86-64, Macos arm64") - .withStyle(ChatFormatting.RED, ChatFormatting.BOLD)); + .withStyle(ChatFormatting.RED, ChatFormatting.BOLD)); } VSEntityManager.INSTANCE.syncHandlers(wrapped); } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/server/command/MixinCommands.java b/common/src/main/java/org/valkyrienskies/mod/mixin/server/command/MixinCommands.java index 75c1170ca..976b8534b 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/server/command/MixinCommands.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/server/command/MixinCommands.java @@ -15,8 +15,7 @@ public class MixinCommands { at = @At("TAIL"), method = "" ) - public void onInit( - final CommandSelection commandSelection, final CommandBuildContext commandBuildContext, final CallbackInfo ci) { + public void onInit(CommandSelection commandSelection, CommandBuildContext commandBuildContext, CallbackInfo ci) { } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/server/command/level/MixinServerPlayer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/server/command/level/MixinServerPlayer.java index 4a95a677f..dd6a239e3 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/server/command/level/MixinServerPlayer.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/server/command/level/MixinServerPlayer.java @@ -1,7 +1,7 @@ package org.valkyrienskies.mod.mixin.server.command.level; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; import org.joml.Vector3d; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -13,6 +13,8 @@ @Mixin(ServerPlayer.class) public abstract class MixinServerPlayer { + + @Shadow public abstract void teleportTo(double d, double e, double f); @@ -22,7 +24,8 @@ public abstract class MixinServerPlayer { cancellable = true ) private void beforeTeleportTo(final double x, final double y, final double z, final CallbackInfo ci) { - final Ship ship = VSGameUtilsKt.getShipManagingPos(Entity.class.cast(this).level(), x, y, z); + ServerLevel level = ((ServerPlayer) (Object) this).serverLevel(); + final Ship ship = VSGameUtilsKt.getShipManagingPos(level, x, y, z); if (ship != null) { ci.cancel(); final Vector3d inWorld = VSGameUtilsKt.toWorldCoordinates(ship, x, y, z); @@ -36,7 +39,8 @@ private void beforeTeleportTo(final double x, final double y, final double z, fi cancellable = true ) private void beforeDismountTo(final double x, final double y, final double z, final CallbackInfo ci) { - final Ship ship = VSGameUtilsKt.getShipManagingPos(Entity.class.cast(this).level(), x, y, z); + ServerLevel level = ((ServerPlayer) (Object) this).serverLevel(); + final Ship ship = VSGameUtilsKt.getShipManagingPos(level, x, y, z); if (ship != null) { ci.cancel(); final Vector3d inWorld = VSGameUtilsKt.toWorldCoordinates(ship, x, y, z); diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/server/network/MixinServerGamePacketListenerImpl.java b/common/src/main/java/org/valkyrienskies/mod/mixin/server/network/MixinServerGamePacketListenerImpl.java index 0036e4536..efdce9a08 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/server/network/MixinServerGamePacketListenerImpl.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/server/network/MixinServerGamePacketListenerImpl.java @@ -78,6 +78,20 @@ private Vec3 skipDistanceCheck2(final Vec3 instance, final Vec3 vec3, final Oper return VSGameUtilsKt.toWorldCoordinates(player.level(), subtract.call(instance, vec3)); } + /* + @WrapOperation( + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/level/ChunkPos;getChessboardDistance(Lnet/minecraft/world/level/ChunkPos;)I" + ), + method = "handleUseItemOn" + ) + private int skipDistanceCheck(final ChunkPos instance, final ChunkPos chunkPos, final Operation getChessboardDistance) { + return 0; + } + + */ + @WrapOperation( method = "handleMovePlayer", at = @At( diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/server/world/MixinChunkMap.java b/common/src/main/java/org/valkyrienskies/mod/mixin/server/world/MixinChunkMap.java index 70646bddc..dadf8a84d 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/server/world/MixinChunkMap.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/server/world/MixinChunkMap.java @@ -4,20 +4,13 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Optional; import java.util.Set; -import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; -import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; -import net.minecraft.world.level.chunk.storage.ChunkSerializer; import net.minecraft.world.level.storage.DimensionDataStorage; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -25,11 +18,9 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.valkyrienskies.core.api.ships.ServerShip; import org.valkyrienskies.core.apigame.world.IPlayer; import org.valkyrienskies.mod.common.VSGameUtilsKt; import org.valkyrienskies.mod.common.util.MinecraftPlayer; -import org.valkyrienskies.mod.common.util.ShipSettingsKt; @Mixin(ChunkMap.class) public abstract class MixinChunkMap { @@ -42,9 +33,6 @@ public abstract class MixinChunkMap { @Final private Supplier overworldDataStorage; - @Shadow - protected abstract CompoundTag upgradeChunkTag(CompoundTag compoundTag); - /** * Force the game to generate empty chunks in the shipyard. * @@ -53,30 +41,32 @@ public abstract class MixinChunkMap { * * @author Tri0de */ + /* @Inject(method = "readChunk", at = @At("HEAD"), cancellable = true) - private void preReadChunk(final ChunkPos chunkPos, - final CallbackInfoReturnable>> cir) { + private void preReadChunk(final ChunkPos chunkPos, final CallbackInfoReturnable cir) + throws IOException { final ChunkMap self = ChunkMap.class.cast(this); + final CompoundTag compoundTag = self.read(chunkPos); + final CompoundTag originalToReturn = compoundTag == null ? null : + self.upgradeChunkTag(this.level.dimension(), this.overworldDataStorage, compoundTag, Optional.empty()); - cir.setReturnValue(self.read(chunkPos).thenApplyAsync(compoundTag -> { - if (compoundTag.isEmpty()) { - final ServerShip ship = VSGameUtilsKt.getShipManagingPos(level, chunkPos.x, chunkPos.z); - // If its in a ship and it shouldn't generate chunks OR if there is no ship but its happening in the shipyard - if ((ship == null && VSGameUtilsKt.isChunkInShipyard(level, chunkPos.x, chunkPos.z)) || - (ship != null && !ShipSettingsKt.getSettings(ship).getShouldGenerateChunks())) { - // The chunk doesn't yet exist and is in the shipyard. Make a new empty chunk - // Generate the chunk to be nothing - final LevelChunk generatedChunk = new LevelChunk(level, - new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, - level.registryAccess().registryOrThrow(Registries.BIOME), null), null); - // Its wasteful to serialize just for this to be deserialized, but it will work for now. - return Optional.of(ChunkSerializer.write(level, generatedChunk)); - } + cir.setReturnValue(originalToReturn); + if (originalToReturn == null) { + final ServerShip ship = VSGameUtilsKt.getShipManagingPos(level, chunkPos.x, chunkPos.z); + // If its in a ship and it shouldn't generate chunks OR if there is no ship but its happening in the shipyard + if ((ship == null && VSGameUtilsKt.isChunkInShipyard(level, chunkPos.x, chunkPos.z)) || + (ship != null && !ShipSettingsKt.getSettings(ship).getShouldGenerateChunks())) { + // The chunk doesn't yet exist and is in the shipyard. Make a new empty chunk + // Generate the chunk to be nothing + final LevelChunk generatedChunk = new LevelChunk(level, + new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, + level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null), null); + // Its wasteful to serialize just for this to be deserialized, but it will work for now. + cir.setReturnValue(ChunkSerializer.write(level, generatedChunk)); } - return compoundTag.map(this::upgradeChunkTag); - })); - + } } + */ /** * Force the game send chunk update packets to players watching ship chunks. diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/server/world/MixinServerLevel.java b/common/src/main/java/org/valkyrienskies/mod/mixin/server/world/MixinServerLevel.java index 5696e1570..3971c68fd 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/server/world/MixinServerLevel.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/server/world/MixinServerLevel.java @@ -4,6 +4,7 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -21,6 +22,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; import org.jetbrains.annotations.NotNull; @@ -31,6 +33,7 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -42,12 +45,13 @@ import org.valkyrienskies.mod.common.IShipObjectWorldServerProvider; import org.valkyrienskies.mod.common.VSGameUtilsKt; import org.valkyrienskies.mod.common.block.WingBlock; +import org.valkyrienskies.mod.common.util.VSServerLevel; import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; -import org.valkyrienskies.mod.mixin.accessors.server.world.ChunkMapAccessor; +import org.valkyrienskies.mod.mixin.accessors.server.level.ChunkMapAccessor; +import org.valkyrienskies.mod.mixin.accessors.server.level.DistanceManagerAccessor; @Mixin(ServerLevel.class) -public abstract class MixinServerLevel implements IShipObjectWorldServerProvider { - +public abstract class MixinServerLevel implements IShipObjectWorldServerProvider, VSServerLevel { @Shadow @Final private ServerChunkCache chunkSource; @@ -57,7 +61,16 @@ public abstract class MixinServerLevel implements IShipObjectWorldServerProvider public abstract MinecraftServer getServer(); // Map from ChunkPos to the list of voxel chunks that chunk owns - private final Map> knownChunks = new HashMap<>(); + @Unique + private final Map> vs$knownChunks = new HashMap<>(); + + // Maps chunk pos to number of ticks we have considered unloading the chunk + @Unique + private final Long2LongOpenHashMap vs$chunksToUnload = new Long2LongOpenHashMap(); + + // How many ticks we wait before unloading a chunk + @Unique + private static final long VS$CHUNK_UNLOAD_THRESHOLD = 100; @Nullable @Override @@ -67,6 +80,7 @@ public ServerShipWorldCore getShipObjectWorld() { @Inject(method = "", at = @At("RETURN")) void onInit(final CallbackInfo ci) { + // This only happens when overworld gets loaded on startup, we have a mixin in MixinMinecraftServer for this specific case if (getShipObjectWorld() != null) { getShipObjectWorld().addDimension(VSGameUtilsKt.getDimensionId((ServerLevel) (Object) this), @@ -103,6 +117,70 @@ private boolean includeShipsInParticleDistanceCheck( return posInWorld.distanceSquared(player.getX(), player.getY(), player.getZ()) < distance * distance; } + @Unique + private void vs$loadChunk(@NotNull final ChunkAccess worldChunk, final List voxelShapeUpdates) { + // Remove the chunk pos from vs$chunksToUnload if its present + vs$chunksToUnload.remove(worldChunk.getPos().toLong()); + if (!vs$knownChunks.containsKey(worldChunk.getPos())) { + final List voxelChunkPositions = new ArrayList<>(); + + final int chunkX = worldChunk.getPos().x; + final int chunkZ = worldChunk.getPos().z; + + final LevelChunkSection[] chunkSections = worldChunk.getSections(); + + for (int sectionY = 0; sectionY < chunkSections.length; sectionY++) { + final LevelChunkSection chunkSection = chunkSections[sectionY]; + final Vector3ic chunkPos = + new Vector3i(chunkX, worldChunk.getSectionYFromSectionIndex(sectionY), chunkZ); + voxelChunkPositions.add(chunkPos); + + if (chunkSection != null && !chunkSection.hasOnlyAir()) { + // Add this chunk to the ground rigid body + final TerrainUpdate voxelShapeUpdate = + VSGameUtilsKt.toDenseVoxelUpdate(chunkSection, chunkPos); + voxelShapeUpdates.add(voxelShapeUpdate); + + // region Detect wings + final ServerLevel thisAsLevel = ServerLevel.class.cast(this); + final LoadedServerShip + ship = VSGameUtilsKt.getShipObjectManagingPos(thisAsLevel, chunkX, chunkZ); + if (ship != null) { + // Sussy cast, but I don't want to expose this directly through the vs-core api + final WingManager shipAsWingManager = ship.getAttachment(WingManager.class); + final MutableBlockPos mutableBlockPos = new MutableBlockPos(); + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + final BlockState blockState = chunkSection.getBlockState(x, y, z); + final int posX = (chunkX << 4) + x; + final int posY = worldChunk.getMinBuildHeight() + y; + final int posZ = (chunkZ << 4) + z; + if (blockState.getBlock() instanceof WingBlock) { + mutableBlockPos.set(posX, posY, posZ); + final Wing wing = + ((WingBlock) blockState.getBlock()).getWing(thisAsLevel, + mutableBlockPos, blockState); + if (wing != null) { + shipAsWingManager.setWing(shipAsWingManager.getFirstWingGroupId(), + posX, posY, posZ, wing); + } + } + } + } + } + } + // endregion + } else { + final TerrainUpdate emptyVoxelShapeUpdate = getVsCore() + .newEmptyVoxelShapeUpdate(chunkPos.x(), chunkPos.y(), chunkPos.z(), true); + voxelShapeUpdates.add(emptyVoxelShapeUpdate); + } + } + vs$knownChunks.put(worldChunk.getPos(), voxelChunkPositions); + } + } + @Inject(method = "tick", at = @At("TAIL")) private void postTick(final BooleanSupplier shouldKeepTicking, final CallbackInfo ci) { final ServerLevel self = ServerLevel.class.cast(this); @@ -113,84 +191,38 @@ private void postTick(final BooleanSupplier shouldKeepTicking, final CallbackInf // Create DenseVoxelShapeUpdate for new loaded chunks // Also mark the chunks as loaded in the ship objects final List voxelShapeUpdates = new ArrayList<>(); + final DistanceManagerAccessor distanceManagerAccessor = (DistanceManagerAccessor) chunkSource.chunkMap.getDistanceManager(); for (final ChunkHolder chunkHolder : chunkMapAccessor.callGetChunks()) { final Optional worldChunkOptional = chunkHolder.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).left(); - if (worldChunkOptional.isPresent()) { + // Only load chunks that are present and that have tickets + if (worldChunkOptional.isPresent() && distanceManagerAccessor.getTickets().containsKey(chunkHolder.getPos().toLong())) { + // Only load chunks that have a ticket final LevelChunk worldChunk = worldChunkOptional.get(); - if (!knownChunks.containsKey(worldChunk.getPos())) { - final List voxelChunkPositions = new ArrayList<>(); - - final int chunkX = worldChunk.getPos().x; - final int chunkZ = worldChunk.getPos().z; - - final LevelChunkSection[] chunkSections = worldChunk.getSections(); - - for (int sectionY = 0; sectionY < chunkSections.length; sectionY++) { - final LevelChunkSection chunkSection = chunkSections[sectionY]; - final Vector3ic chunkPos = - new Vector3i(chunkX, worldChunk.getSectionYFromSectionIndex(sectionY), chunkZ); - voxelChunkPositions.add(chunkPos); - - if (chunkSection != null && !chunkSection.hasOnlyAir()) { - // Add this chunk to the ground rigid body - final TerrainUpdate voxelShapeUpdate = - VSGameUtilsKt.toDenseVoxelUpdate(chunkSection, chunkPos); - voxelShapeUpdates.add(voxelShapeUpdate); - - // region Detect wings - final ServerLevel thisAsLevel = ServerLevel.class.cast(this); - final LoadedServerShip - ship = VSGameUtilsKt.getShipObjectManagingPos(thisAsLevel, chunkX, chunkZ); - if (ship != null) { - // Sussy cast, but I don't want to expose this directly through the vs-core api - final WingManager shipAsWingManager = ship.getAttachment(WingManager.class); - final MutableBlockPos mutableBlockPos = new MutableBlockPos(); - for (int x = 0; x < 16; x++) { - for (int y = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - final BlockState blockState = chunkSection.getBlockState(x, y, z); - final int posX = (chunkX << 4) + x; - final int posY = (sectionY << 4) + worldChunk.getMinBuildHeight() + y; - final int posZ = (chunkZ << 4) + z; - if (blockState.getBlock() instanceof WingBlock) { - mutableBlockPos.set(posX, posY, posZ); - final Wing wing = - ((WingBlock) blockState.getBlock()).getWing(thisAsLevel, - mutableBlockPos, blockState); - if (wing != null) { - shipAsWingManager.setWing(shipAsWingManager.getFirstWingGroupId(), - posX, posY, posZ, wing); - } - } - } - } - } - } - // endregion - } else { - final TerrainUpdate emptyVoxelShapeUpdate = getVsCore() - .newEmptyVoxelShapeUpdate(chunkPos.x(), chunkPos.y(), chunkPos.z(), true); - voxelShapeUpdates.add(emptyVoxelShapeUpdate); - } - } - knownChunks.put(worldChunk.getPos(), voxelChunkPositions); - } + vs$loadChunk(worldChunk, voxelShapeUpdates); } } - final Iterator>> knownChunkPosIterator = knownChunks.entrySet().iterator(); + final Iterator>> knownChunkPosIterator = vs$knownChunks.entrySet().iterator(); while (knownChunkPosIterator.hasNext()) { final Entry> knownChunkPosEntry = knownChunkPosIterator.next(); - if (chunkMapAccessor.callGetVisibleChunkIfPresent(knownChunkPosEntry.getKey().toLong()) == null) { - // Delete this chunk - for (final Vector3ic unloadedChunk : knownChunkPosEntry.getValue()) { - final TerrainUpdate deleteVoxelShapeUpdate = - getVsCore().newDeleteTerrainUpdate(unloadedChunk.x(), unloadedChunk.y(), unloadedChunk.z()); - voxelShapeUpdates.add(deleteVoxelShapeUpdate); + final long chunkPos = knownChunkPosEntry.getKey().toLong(); + // Unload chunks if they don't have tickets or if they're not in the visible chunks + if ((!distanceManagerAccessor.getTickets().containsKey(chunkPos) || chunkMapAccessor.callGetVisibleChunkIfPresent(chunkPos) == null)) { + final long ticksWaitingToUnload = vs$chunksToUnload.getOrDefault(chunkPos, 0L); + if (ticksWaitingToUnload > VS$CHUNK_UNLOAD_THRESHOLD) { + // Unload this chunk + for (final Vector3ic unloadedChunk : knownChunkPosEntry.getValue()) { + final TerrainUpdate deleteVoxelShapeUpdate = + getVsCore().newDeleteTerrainUpdate(unloadedChunk.x(), unloadedChunk.y(), unloadedChunk.z()); + voxelShapeUpdates.add(deleteVoxelShapeUpdate); + } + knownChunkPosIterator.remove(); + vs$chunksToUnload.remove(chunkPos); + } else { + vs$chunksToUnload.put(chunkPos, ticksWaitingToUnload + 1); } - knownChunkPosIterator.remove(); } } @@ -201,4 +233,9 @@ private void postTick(final BooleanSupplier shouldKeepTicking, final CallbackInf ); } + @Override + public void removeChunk(final int chunkX, final int chunkZ) { + final ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ); + vs$knownChunks.remove(chunkPos); + } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/world/chunk/MixinLevelChunk.java b/common/src/main/java/org/valkyrienskies/mod/mixin/world/chunk/MixinLevelChunk.java index fa35410b0..6ef89c925 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/world/chunk/MixinLevelChunk.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/world/chunk/MixinLevelChunk.java @@ -1,27 +1,151 @@ package org.valkyrienskies.mod.mixin.world.chunk; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.ProtoChunk; +import net.minecraft.world.level.chunk.storage.ChunkSerializer; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.Heightmap.Types; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.ticks.LevelChunkTicks; +import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.valkyrienskies.core.api.ships.Ship; import org.valkyrienskies.mod.common.BlockStateInfo; +import org.valkyrienskies.mod.common.util.VSLevelChunk; @Mixin(LevelChunk.class) -public class MixinLevelChunk { +public abstract class MixinLevelChunk extends ChunkAccess implements VSLevelChunk { @Shadow @Final Level level; + @Shadow + @Mutable + private LevelChunkTicks blockTicks; + @Shadow + @Mutable + private LevelChunkTicks fluidTicks; + + @Unique + private static final Set ALL_HEIGHT_MAP_TYPES = new HashSet<>(Arrays.asList((Heightmap.Types.values()))); + + // Dummy constructor + public MixinLevelChunk(final Ship ship) { + super(null, null, null, null, 0, null, null); + throw new IllegalStateException("This should never be called!"); + } + @Inject(method = "setBlockState", at = @At("TAIL")) public void postSetBlockState(final BlockPos pos, final BlockState state, final boolean moved, final CallbackInfoReturnable cir) { final BlockState prevState = cir.getReturnValue(); BlockStateInfo.INSTANCE.onSetBlock(level, pos, prevState, state); } + + @Shadow + public abstract void clearAllBlockEntities(); + + @Shadow + public abstract void registerTickContainerInLevel(ServerLevel serverLevel); + + @Shadow + public abstract void unregisterTickContainerFromLevel(ServerLevel serverLevel); + + @Override + public void clearChunk() { + clearAllBlockEntities(); + unregisterTickContainerFromLevel((ServerLevel) level); + + // Set terrain to empty + heightmaps.clear(); + Arrays.fill(sections, null); + final Registry registry = level.registryAccess().registryOrThrow(Registries.BIOME); + for (int i = 0; i < sections.length; ++i) { + if (sections[i] != null) continue; + //new LevelChunkSection(registry); + sections[i] = new LevelChunkSection(registry); + } + this.setLightCorrect(false); + + registerTickContainerInLevel((ServerLevel) level); + this.unsaved = true; + } + + @Override + public void copyChunkFromOtherDimension(@NotNull final VSLevelChunk srcChunkVS) { + clearAllBlockEntities(); + unregisterTickContainerFromLevel((ServerLevel) level); + + // Set terrain to empty + heightmaps.clear(); + Arrays.fill(sections, null); + + // Copy heightmap and sections and block entities from srcChunk + final LevelChunk srcChunk = (LevelChunk) srcChunkVS; + final CompoundTag compoundTag = ChunkSerializer.write((ServerLevel) srcChunk.getLevel(), srcChunk); + // Set status to be ProtoChunk to fix block entities not saving + compoundTag.putString("Status", ChunkStatus.ChunkType.PROTOCHUNK.name()); + final ProtoChunk protoChunk = ChunkSerializer.read((ServerLevel) level, ((ServerLevel) level).getPoiManager(), chunkPos, compoundTag); + + this.blockTicks = protoChunk.unpackBlockTicks(); + this.fluidTicks = protoChunk.unpackFluidTicks(); + // Copy data from the protoChunk + // this.chunkPos = chunkPos; + // this.upgradeData = upgradeData; + // this.levelHeightAccessor = levelHeightAccessor; + + for (int i = 0; i < sections.length; i++) { + sections[i] = protoChunk.getSection(i); + } + final Registry registry = level.registryAccess().registryOrThrow(Registries.BIOME); + for (int i = 0; i < sections.length; ++i) { + if (sections[i] != null) continue; + sections[i] = new LevelChunkSection(registry); + } + + // this.inhabitedTime = l; + // this.postProcessing = new ShortList[levelHeightAccessor.getSectionsCount()]; + this.blendingData = protoChunk.getBlendingData(); + + for (final BlockEntity blockEntity : protoChunk.getBlockEntities().values()) { + this.setBlockEntity(blockEntity); + } + this.pendingBlockEntities.putAll(protoChunk.getBlockEntityNbts()); + for (int i = 0; i < protoChunk.getPostProcessing().length; ++i) { + this.postProcessing[i] = protoChunk.getPostProcessing()[i]; + } + this.setAllStarts(protoChunk.getAllStarts()); + this.setAllReferences(protoChunk.getAllReferences()); + + // Recompute height maps instead of getting them from protoChunk (This fixes crashes from missing height maps) + Heightmap.primeHeightmaps(this, ALL_HEIGHT_MAP_TYPES); + this.setLightCorrect(false); + + registerTickContainerInLevel((ServerLevel) level); + + this.unsaved = true; + } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/MixinBlockCollisions.java b/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/MixinBlockCollisions.java new file mode 100644 index 000000000..1acd44e66 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/MixinBlockCollisions.java @@ -0,0 +1,54 @@ +package org.valkyrienskies.mod.mixin.world.level; + +import java.util.function.BiFunction; +import net.minecraft.core.Cursor3D; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.BlockCollisions; +import net.minecraft.world.level.CollisionGetter; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.mod.util.BugFixUtil; + +/** + * Fix game freezing when a too-large AABB is used in a BlockCollisions object + */ +@Mixin(BlockCollisions.class) +public class MixinBlockCollisions { + @Shadow + @Final + @Mutable + private AABB box; + @Shadow + @Final + @Mutable + private Cursor3D cursor; + @Shadow + @Final + @Mutable + private VoxelShape entityShape; + + @Inject(method = "", at = @At("RETURN")) + private void postInit(CollisionGetter collisionGetter, Entity entity, AABB aabb, boolean bl, BiFunction biFunction, CallbackInfo ci) { + if (BugFixUtil.INSTANCE.isCollisionBoxToBig(aabb)) { + final AABB newBox = new AABB(aabb.minX, aabb.minY, aabb.minZ, aabb.minX, aabb.minY, aabb.minZ); + this.entityShape = Shapes.create(newBox); + this.box = newBox; + final int i = Mth.floor(newBox.minX - 1.0E-7) - 1; + final int j = Mth.floor(newBox.maxX + 1.0E-7) + 1; + final int k = Mth.floor(newBox.minY - 1.0E-7) - 1; + final int l = Mth.floor(newBox.maxY + 1.0E-7) + 1; + final int m = Mth.floor(newBox.minZ - 1.0E-7) - 1; + final int n = Mth.floor(newBox.maxZ + 1.0E-7) + 1; + this.cursor = new Cursor3D(i, k, m, j, l, n); + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/chunk/MixinChunkGenerator.java b/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/chunk/MixinChunkGenerator.java new file mode 100644 index 000000000..d7590470e --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/chunk/MixinChunkGenerator.java @@ -0,0 +1,69 @@ +package org.valkyrienskies.mod.mixin.world.level.chunk; + +import com.mojang.datafixers.util.Pair; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.RegistryAccess; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; +import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.valkyrienskies.mod.common.VS2ChunkAllocator; + +@Mixin(ChunkGenerator.class) +public class MixinChunkGenerator { + @Inject(method = "findNearestMapStructure", at = @At("HEAD"), cancellable = true) + private void preFindNearestMapFeature(ServerLevel serverLevel, HolderSet holderSet, BlockPos blockPos, int i, boolean bl, CallbackInfoReturnable>> cir) { + if (VS2ChunkAllocator.INSTANCE.isChunkInShipyardCompanion(blockPos.getX() >> 4, blockPos.getZ() >> 4)) { + cir.setReturnValue(null); + } + } + + @Inject(method = "applyBiomeDecoration", at = @At("HEAD"), cancellable = true) + private void preApplyBiomeDecoration(WorldGenLevel worldGenLevel, ChunkAccess chunkAccess, StructureManager structureManager, CallbackInfo callbackInfo) { + final ChunkPos chunkPos = chunkAccess.getPos(); + if (VS2ChunkAllocator.INSTANCE.isChunkInShipyardCompanion(chunkPos.x, chunkPos.z)) { + callbackInfo.cancel(); + } + } + + //TODO + /* + @Inject(method = "hasStructureChunkInRange", at = @At("HEAD"), cancellable = true) + private void preHasFeatureChunkInRange(Holder holder, RandomState randomState, long l, int chunkX, int chunkZ, int k, CallbackInfoReturnable cir) { + if (VS2ChunkAllocator.INSTANCE.isChunkInShipyardCompanion(chunkX, chunkZ)) { + cir.setReturnValue(false); + } + } + + */ + + @Inject(method = "createStructures", at = @At("HEAD"), cancellable = true) + private void preCreateStructures(RegistryAccess registryAccess, + ChunkGeneratorStructureState chunkGeneratorStructureState, StructureManager structureManager, + ChunkAccess chunkAccess, StructureTemplateManager structureTemplateManager, CallbackInfo callbackInfo) { + final ChunkPos chunkPos = chunkAccess.getPos(); + if (VS2ChunkAllocator.INSTANCE.isChunkInShipyardCompanion(chunkPos.x, chunkPos.z)) { + callbackInfo.cancel(); + } + } + + @Inject(method = "createReferences", at = @At("HEAD"), cancellable = true) + private void preCreateReferences(WorldGenLevel worldGenLevel, StructureManager structureManager, ChunkAccess chunkAccess, CallbackInfo callbackInfo) { + final ChunkPos chunkPos = chunkAccess.getPos(); + if (VS2ChunkAllocator.INSTANCE.isChunkInShipyardCompanion(chunkPos.x, chunkPos.z)) { + callbackInfo.cancel(); + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/levelgen/MixinFlatLevelSource.java b/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/levelgen/MixinFlatLevelSource.java new file mode 100644 index 000000000..502de11a5 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/levelgen/MixinFlatLevelSource.java @@ -0,0 +1,26 @@ +package org.valkyrienskies.mod.mixin.world.level.levelgen; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.levelgen.FlatLevelSource; +import net.minecraft.world.level.levelgen.RandomState; +import net.minecraft.world.level.levelgen.blending.Blender; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.valkyrienskies.mod.common.VS2ChunkAllocator; + +@Mixin(FlatLevelSource.class) +public class MixinFlatLevelSource { + @Inject(method = "fillFromNoise", at = @At("HEAD"), cancellable = true) + private void preFillFromNoise(Executor executor, Blender blender, RandomState randomState, StructureManager structureManager, ChunkAccess chunkAccess, CallbackInfoReturnable> cir) { + final ChunkPos chunkPos = chunkAccess.getPos(); + if (VS2ChunkAllocator.INSTANCE.isChunkInShipyardCompanion(chunkPos.x, chunkPos.z)) { + cir.setReturnValue(CompletableFuture.completedFuture(chunkAccess)); + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/levelgen/MixinNoiseBasedChunkGenerator.java b/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/levelgen/MixinNoiseBasedChunkGenerator.java new file mode 100644 index 000000000..a175996a9 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/world/level/levelgen/MixinNoiseBasedChunkGenerator.java @@ -0,0 +1,76 @@ +package org.valkyrienskies.mod.mixin.world.level.levelgen; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import net.minecraft.core.Holder; +import net.minecraft.server.level.WorldGenRegion; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.NoiseColumn; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.biome.BiomeManager; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.levelgen.GenerationStep.Carving; +import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; +import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; +import net.minecraft.world.level.levelgen.NoiseSettings; +import net.minecraft.world.level.levelgen.RandomState; +import net.minecraft.world.level.levelgen.blending.Blender; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.valkyrienskies.mod.common.VS2ChunkAllocator; + +@Mixin(NoiseBasedChunkGenerator.class) +public class MixinNoiseBasedChunkGenerator { + @Shadow + @Final + protected Holder settings; + + + @Inject(method = "getBaseColumn", at = @At("HEAD"), cancellable = true) + private void preGetBaseColumn(int i, int j, LevelHeightAccessor levelHeightAccessor, RandomState randomState, CallbackInfoReturnable cir) { + if (VS2ChunkAllocator.INSTANCE.isChunkInShipyardCompanion(i, j)) { + final NoiseSettings noiseSettings = this.settings.value().noiseSettings(); + final int k = Math.max(noiseSettings.minY(), levelHeightAccessor.getMinBuildHeight()); + cir.setReturnValue(new NoiseColumn(k, new BlockState[0])); + } + } + + @Inject(method = "buildSurface(Lnet/minecraft/server/level/WorldGenRegion;Lnet/minecraft/world/level/StructureManager;Lnet/minecraft/world/level/levelgen/RandomState;Lnet/minecraft/world/level/chunk/ChunkAccess;)V", at = @At("HEAD"), cancellable = true) + private void preBuildSurface(WorldGenRegion worldGenRegion, StructureManager structureManager, RandomState randomState, ChunkAccess chunkAccess, CallbackInfo ci) { + final ChunkPos chunkPos = chunkAccess.getPos(); + if (VS2ChunkAllocator.INSTANCE.isChunkInShipyardCompanion(chunkPos.x, chunkPos.z)) { + ci.cancel(); + } + } + + @Inject(method = "applyCarvers", at = @At("HEAD"), cancellable = true) + private void preApplyCarvers(WorldGenRegion worldGenRegion, long l, RandomState randomState, BiomeManager biomeManager, StructureManager structureManager, ChunkAccess chunkAccess, Carving carving, CallbackInfo ci) { + final ChunkPos chunkPos = chunkAccess.getPos(); + if (VS2ChunkAllocator.INSTANCE.isChunkInShipyardCompanion(chunkPos.x, chunkPos.z)) { + ci.cancel(); + } + } + + @Inject(method = "fillFromNoise", at = @At("HEAD"), cancellable = true) + private void preFillFromNoise(Executor executor, Blender blender, RandomState randomState, StructureManager structureManager, ChunkAccess chunkAccess, CallbackInfoReturnable> cir) { + final ChunkPos chunkPos = chunkAccess.getPos(); + if (VS2ChunkAllocator.INSTANCE.isChunkInShipyardCompanion(chunkPos.x, chunkPos.z)) { + cir.setReturnValue(CompletableFuture.completedFuture(chunkAccess)); + } + } + + @Inject(method = "spawnOriginalMobs", at = @At("HEAD"), cancellable = true) + private void preSpawnOriginalMobs(WorldGenRegion worldGenRegion, CallbackInfo ci) { + final ChunkPos chunkPos = worldGenRegion.getCenter(); + if (VS2ChunkAllocator.INSTANCE.isChunkInShipyardCompanion(chunkPos.x, chunkPos.z)) { + ci.cancel(); + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixinducks/MixinBlockEntityInstanceManagerDuck.java b/common/src/main/java/org/valkyrienskies/mod/mixinducks/MixinBlockEntityInstanceManagerDuck.java index 9e9a3aea5..00be12a98 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixinducks/MixinBlockEntityInstanceManagerDuck.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixinducks/MixinBlockEntityInstanceManagerDuck.java @@ -6,6 +6,7 @@ public interface MixinBlockEntityInstanceManagerDuck { - WeakHashMap getShipMaterialManagers(); + WeakHashMap vs$getShipMaterialManagers(); + void vs$removeShipManager(ClientShip clientShip); } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixinducks/MixinInstancingEngineDuck.java b/common/src/main/java/org/valkyrienskies/mod/mixinducks/MixinInstancingEngineDuck.java index d77668a80..f2582622c 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixinducks/MixinInstancingEngineDuck.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixinducks/MixinInstancingEngineDuck.java @@ -4,5 +4,5 @@ import org.joml.Matrix4f; public interface MixinInstancingEngineDuck { - void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer); + void vs$render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer); } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixinducks/client/world/ClientChunkCacheDuck.java b/common/src/main/java/org/valkyrienskies/mod/mixinducks/client/world/ClientChunkCacheDuck.java index 74136c9b6..89169d9a4 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixinducks/client/world/ClientChunkCacheDuck.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixinducks/client/world/ClientChunkCacheDuck.java @@ -4,5 +4,5 @@ import net.minecraft.world.level.chunk.LevelChunk; public interface ClientChunkCacheDuck { - LongObjectMap vs_getShipChunks(); + LongObjectMap vs$getShipChunks(); } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/CWCluster.java b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/CWCluster.java new file mode 100644 index 000000000..4aada2a8b --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/CWCluster.java @@ -0,0 +1,73 @@ +package org.valkyrienskies.mod.mixinducks.mod_compat.create; + +import com.simibubi.create.foundation.utility.Iterate; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; + +/** + * This class only exists because Creates Cluster class is private, and I can't get an access widener to work on it >.< + */ +public class CWCluster { + public BlockPos anchor; + public final Map visibleFaces; + public final Set visibleEdges; + + public CWCluster() { + visibleEdges = new HashSet<>(); + visibleFaces = new HashMap<>(); + } + + public boolean isEmpty() { + return anchor == null; + } + + public void include(BlockPos pos) { + if (anchor == null) + anchor = pos; + + pos = pos.subtract(anchor); + + // 6 FACES + for (Direction.Axis axis : Iterate.axes) { + Direction direction = Direction.get(Direction.AxisDirection.POSITIVE, axis); + for (int offset : Iterate.zeroAndOne) { + CWMergeEntry entry = new CWMergeEntry(axis, pos.relative(direction, offset)); + if (visibleFaces.remove(entry) == null) + visibleFaces.put(entry, offset == 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE); + } + } + + // 12 EDGES + for (Direction.Axis axis : Iterate.axes) { + for (Direction.Axis axis2 : Iterate.axes) { + if (axis == axis2) + continue; + for (Direction.Axis axis3 : Iterate.axes) { + if (axis == axis3) + continue; + if (axis2 == axis3) + continue; + + Direction direction = Direction.get(Direction.AxisDirection.POSITIVE, axis2); + Direction direction2 = Direction.get(Direction.AxisDirection.POSITIVE, axis3); + + for (int offset : Iterate.zeroAndOne) { + BlockPos entryPos = pos.relative(direction, offset); + for (int offset2 : Iterate.zeroAndOne) { + entryPos = entryPos.relative(direction2, offset2); + CWMergeEntry entry = new CWMergeEntry(axis, entryPos); + if (!visibleEdges.remove(entry)) + visibleEdges.add(entry); + } + } + } + + break; + } + } + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/CWMergeEntry.java b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/CWMergeEntry.java new file mode 100644 index 000000000..7029d1172 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/CWMergeEntry.java @@ -0,0 +1,32 @@ +package org.valkyrienskies.mod.mixinducks.mod_compat.create; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; + +/** + * This class only exists because Creates MergeEntry class is private, and I can't get an access widener to work on it >.< + */ +public class CWMergeEntry { + public final Direction.Axis axis; + public final BlockPos pos; + + public CWMergeEntry(Direction.Axis axis, BlockPos pos) { + this.axis = axis; + this.pos = pos; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof CWMergeEntry other)) + return false; + + return this.axis == other.axis && this.pos.equals(other.pos); + } + + @Override + public int hashCode() { + return this.pos.hashCode() * 31 + axis.ordinal(); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/IExtendedAirCurrentSource.java b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/IExtendedAirCurrentSource.java new file mode 100644 index 000000000..0b7f04184 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/IExtendedAirCurrentSource.java @@ -0,0 +1,10 @@ +package org.valkyrienskies.mod.mixinducks.mod_compat.create; + +import com.simibubi.create.content.kinetics.fan.IAirCurrentSource; +import org.valkyrienskies.core.api.ships.Ship; + +public interface IExtendedAirCurrentSource extends IAirCurrentSource { + + Ship getShip(); + +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/IMixinControlledContraptionEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/IMixinControlledContraptionEntity.java new file mode 100644 index 000000000..9c8214d43 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/IMixinControlledContraptionEntity.java @@ -0,0 +1,7 @@ +package org.valkyrienskies.mod.mixinducks.mod_compat.create; + +import com.simibubi.create.content.contraptions.IControlContraption; + +public interface IMixinControlledContraptionEntity { + IControlContraption grabController(); +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/IMixinStickerTileEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/IMixinStickerTileEntity.java new file mode 100644 index 000000000..ca09a4ed9 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/IMixinStickerTileEntity.java @@ -0,0 +1,6 @@ +package org.valkyrienskies.mod.mixinducks.mod_compat.create; + +public interface IMixinStickerTileEntity { + + boolean isAlreadyPowered(boolean reset); +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/MixinAbstractContraptionEntityDuck.java b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/MixinAbstractContraptionEntityDuck.java new file mode 100644 index 000000000..b7eca7b8b --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixinducks/mod_compat/create/MixinAbstractContraptionEntityDuck.java @@ -0,0 +1,9 @@ +package org.valkyrienskies.mod.mixinducks.mod_compat.create; + +import com.simibubi.create.content.contraptions.StructureTransform; + +public interface MixinAbstractContraptionEntityDuck { + void vs$setForceStall(boolean forceStall); + + StructureTransform getStructureTransform(); +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/client/VSPhysicsEntityRenderer.kt b/common/src/main/kotlin/org/valkyrienskies/mod/client/VSPhysicsEntityRenderer.kt new file mode 100644 index 000000000..040950d37 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/client/VSPhysicsEntityRenderer.kt @@ -0,0 +1,75 @@ +package org.valkyrienskies.mod.client + +import com.mojang.blaze3d.vertex.PoseStack +import net.minecraft.client.Minecraft +import net.minecraft.client.renderer.ItemBlockRenderTypes +import net.minecraft.client.renderer.MultiBufferSource +import net.minecraft.client.renderer.entity.EntityRenderer +import net.minecraft.client.renderer.entity.EntityRendererProvider +import net.minecraft.client.renderer.texture.OverlayTexture +import net.minecraft.core.BlockPos +import net.minecraft.resources.ResourceLocation +import net.minecraft.util.RandomSource +import net.minecraft.world.inventory.InventoryMenu +import net.minecraft.world.level.block.RenderShape.INVISIBLE +import net.minecraft.world.level.block.RenderShape.MODEL +import org.joml.Quaterniondc +import org.joml.Quaternionf +import org.valkyrienskies.core.impl.game.ships.ShipObjectClientWorld +import org.valkyrienskies.mod.common.IShipObjectWorldClientProvider +import org.valkyrienskies.mod.common.ValkyrienSkiesMod +import org.valkyrienskies.mod.common.entity.VSPhysicsEntity +import org.valkyrienskies.mod.common.util.toMinecraft +import java.util.Random + +class VSPhysicsEntityRenderer(context: EntityRendererProvider.Context) : EntityRenderer(context) { + override fun render( + fallingBlockEntity: VSPhysicsEntity, f: Float, partialTick: Float, poseStack: PoseStack, + multiBufferSource: MultiBufferSource, i: Int + ) { + val blockState = ValkyrienSkiesMod.TEST_SPHERE.defaultBlockState() + if (blockState.renderShape != MODEL) { + return + } + val level = fallingBlockEntity.level() + if (blockState === level.getBlockState( + fallingBlockEntity.blockPosition() + ) || blockState.renderShape == INVISIBLE + ) { + return + } + + val renderTransform = fallingBlockEntity.getRenderTransform( + ((Minecraft.getInstance() as IShipObjectWorldClientProvider).shipObjectWorld as ShipObjectClientWorld) + ) ?: return + + val expectedX = fallingBlockEntity.xo + (fallingBlockEntity.x - fallingBlockEntity.xo) * partialTick + val expectedY = fallingBlockEntity.yo + (fallingBlockEntity.y - fallingBlockEntity.yo) * partialTick + val expectedZ = fallingBlockEntity.zo + (fallingBlockEntity.z - fallingBlockEntity.zo) * partialTick + + // Replace the default transform applied by mc with these offsets + val offsetX = renderTransform.positionInWorld.x() - expectedX + val offsetY = renderTransform.positionInWorld.y() - expectedY + val offsetZ = renderTransform.positionInWorld.z() - expectedZ + + poseStack.pushPose() + val blockPos = BlockPos.containing(fallingBlockEntity.x, fallingBlockEntity.boundingBox.maxY, fallingBlockEntity.z) + + poseStack.translate(offsetX, offsetY, offsetZ) + poseStack.mulPose(Quaternionf(renderTransform.shipToWorldRotation)) + poseStack.translate(-0.5, -0.5, -0.5) + val blockRenderDispatcher = Minecraft.getInstance().blockRenderer + blockRenderDispatcher.modelRenderer.tesselateBlock( + level, blockRenderDispatcher.getBlockModel(blockState), blockState, blockPos, poseStack, + multiBufferSource.getBuffer( + ItemBlockRenderTypes.getMovingBlockRenderType(blockState) + ), false, RandomSource.create(), blockState.getSeed(BlockPos.ZERO), OverlayTexture.NO_OVERLAY + ) + poseStack.popPose() + super.render(fallingBlockEntity, f, partialTick, poseStack, multiBufferSource, i) + } + + override fun getTextureLocation(entity: VSPhysicsEntity): ResourceLocation { + return InventoryMenu.BLOCK_ATLAS + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/client/audio/SimpleSoundInstanceOnShip.kt b/common/src/main/kotlin/org/valkyrienskies/mod/client/audio/SimpleSoundInstanceOnShip.kt index 03fadcc32..690311d23 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/client/audio/SimpleSoundInstanceOnShip.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/client/audio/SimpleSoundInstanceOnShip.kt @@ -2,14 +2,14 @@ package org.valkyrienskies.mod.client.audio import net.minecraft.client.resources.sounds.SimpleSoundInstance import net.minecraft.client.resources.sounds.SoundInstance.Attenuation -import net.minecraft.client.resources.sounds.SoundInstance.Attenuation.LINEAR import net.minecraft.resources.ResourceLocation import net.minecraft.sounds.SoundEvent import net.minecraft.sounds.SoundSource import net.minecraft.util.RandomSource +import org.valkyrienskies.core.api.ships.Ship import org.joml.Vector3d import org.joml.Vector3dc -import org.valkyrienskies.core.api.ships.Ship +import net.minecraft.client.resources.sounds.SoundInstance.Attenuation.LINEAR class SimpleSoundInstanceOnShip : SimpleSoundInstance, VelocityTickableSoundInstance { diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt index 8270fccf4..a94660be1 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/BlockStateInfoProvider.kt @@ -17,6 +17,11 @@ import org.valkyrienskies.core.apigame.world.chunks.BlockType import org.valkyrienskies.mod.common.block.WingBlock import org.valkyrienskies.mod.common.config.MassDatapackResolver import org.valkyrienskies.mod.common.hooks.VSGameEvents +import org.valkyrienskies.physics_api.Lod1BlockStateId +import org.valkyrienskies.physics_api.Lod1LiquidBlockStateId +import org.valkyrienskies.physics_api.Lod1SolidBlockStateId +import org.valkyrienskies.physics_api.voxel.Lod1LiquidBlockState +import org.valkyrienskies.physics_api.voxel.Lod1SolidBlockState import java.util.function.IntFunction // Other mods can then provide weights and types based on their added content @@ -28,7 +33,12 @@ interface BlockStateInfoProvider { fun getBlockStateMass(blockState: BlockState): Double? + // Get the id of the block state fun getBlockStateType(blockState: BlockState): BlockType? + + val solidBlockStates: List + val liquidBlockStates: List + val blockStateData: List> } object BlockStateInfo { @@ -36,8 +46,7 @@ object BlockStateInfo { // registry for mods to add their weights val REGISTRY = MappedRegistry( ResourceKey.createRegistryKey(ResourceLocation(ValkyrienSkiesMod.MOD_ID, "blockstate_providers")), - Lifecycle.experimental(), - false + Lifecycle.experimental() ) private lateinit var SORTED_REGISTRY: List diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/CompatUtil.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/CompatUtil.kt new file mode 100644 index 000000000..56dace1d3 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/CompatUtil.kt @@ -0,0 +1,41 @@ +package org.valkyrienskies.mod.common + +import net.minecraft.world.level.Level +import net.minecraft.world.phys.Vec3 +import org.joml.Vector3d +import org.valkyrienskies.core.api.ships.Ship +import org.valkyrienskies.mod.common.util.toJOML +import org.valkyrienskies.mod.common.util.toMinecraft + +object CompatUtil { + fun toSameSpaceAs(level: Level, position: Vector3d, target: Vector3d): Vector3d { + var ship: Ship? + if (level.isBlockInShipyard(position.x, position.y, position.z) && !level.isBlockInShipyard( + target.x, + target.y, + target.z + ) + ) { + ship = level.getShipManagingPos(position) + ship!!.shipToWorld.transformPosition(position) + } + if (!level.isBlockInShipyard(position.x, position.y, position.z) && level.isBlockInShipyard( + target.x, + target.y, + target.z + ) + ) { + ship = level.getShipManagingPos(target) + ship!!.worldToShip.transformPosition(position) + } + return position + } + + fun toSameSpaceAs(level: Level, position: Vec3, target: Vec3): Vec3 { + return toSameSpaceAs(level, position.toJOML(), target.toJOML()).toMinecraft() + } + + fun toSameSpaceAs(level: Level, px: Double, py: Double, pz: Double, target: Vec3): Vec3 { + return toSameSpaceAs(level, Vector3d(px, py, pz), target.toJOML()).toMinecraft() + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/DefaultBlockStateInfoProvider.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/DefaultBlockStateInfoProvider.kt index 389c53940..54f5ce073 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/DefaultBlockStateInfoProvider.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/DefaultBlockStateInfoProvider.kt @@ -4,27 +4,34 @@ import net.minecraft.world.level.block.Blocks import net.minecraft.world.level.block.LiquidBlock import net.minecraft.world.level.block.state.BlockState import org.valkyrienskies.core.apigame.world.chunks.BlockType +import org.valkyrienskies.physics_api.Lod1BlockStateId +import org.valkyrienskies.physics_api.Lod1LiquidBlockStateId +import org.valkyrienskies.physics_api.Lod1SolidBlockStateId +import org.valkyrienskies.physics_api.voxel.Lod1LiquidBlockState +import org.valkyrienskies.physics_api.voxel.Lod1SolidBlockState object DefaultBlockStateInfoProvider : BlockStateInfoProvider { override val priority: Int get() = Int.MIN_VALUE + override val solidBlockStates: List + get() = TODO() + override val liquidBlockStates: List + get() = TODO() + override val blockStateData: List> + get() = TODO() override fun getBlockStateMass(blockState: BlockState): Double { if (blockState.isAir) return 0.0 - return 100.0 + // By default make blocks weight 1000 kg + return 1000.0 } override fun getBlockStateType(blockState: BlockState): BlockType { if (blockState.isAir) return vsCore.blockTypes.air val block = blockState.block - if (block is LiquidBlock) { - return if (block == Blocks.LAVA) { - vsCore.blockTypes.lava - } else { - vsCore.blockTypes.water - } - } + if (block is LiquidBlock) + return if (block == Blocks.LAVA) vsCore.blockTypes.lava else vsCore.blockTypes.water return if (blockState.isSolid) vsCore.blockTypes.solid else vsCore.blockTypes.air } } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/VS2ChunkAllocator.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/VS2ChunkAllocator.kt new file mode 100644 index 000000000..ded9b6c93 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/VS2ChunkAllocator.kt @@ -0,0 +1,8 @@ +package org.valkyrienskies.mod.common + +object VS2ChunkAllocator { + // TODO: Move this to ChunkAllocator eventually + fun isChunkInShipyardCompanion(chunkX: Int, chunkZ: Int): Boolean { + return vsCore.isChunkInShipyard(chunkX, chunkZ) + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/VSClientGameUtils.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/VSClientGameUtils.kt index 29478af85..1ae005c71 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/VSClientGameUtils.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/VSClientGameUtils.kt @@ -108,4 +108,3 @@ object VSClientGameUtils { ) } } - diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/VSGameUtils.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/VSGameUtils.kt index 5dca273dc..8fbae6f3d 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/VSGameUtils.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/VSGameUtils.kt @@ -35,15 +35,13 @@ import org.valkyrienskies.core.apigame.world.chunks.TerrainUpdate import org.valkyrienskies.core.apigame.world.properties.DimensionId import org.valkyrienskies.core.game.ships.ShipObjectServer import org.valkyrienskies.core.impl.hooks.VSEvents.TickEndEvent -import org.valkyrienskies.core.impl.util.expand +import org.valkyrienskies.core.util.expand import org.valkyrienskies.mod.common.util.DimensionIdProvider import org.valkyrienskies.mod.common.util.MinecraftPlayer import org.valkyrienskies.mod.common.util.set import org.valkyrienskies.mod.common.util.toJOML import org.valkyrienskies.mod.common.util.toJOMLD import org.valkyrienskies.mod.common.util.toMinecraft -import org.valkyrienskies.mod.common.world.DummyShipWorldClient -import org.valkyrienskies.mod.common.world.DummyShipWorldServer import org.valkyrienskies.mod.mixin.accessors.resource.ResourceKeyAccessor import org.valkyrienskies.mod.mixinducks.world.entity.PlayerDuck import java.util.function.Consumer @@ -59,15 +57,15 @@ val Level?.shipWorldNullable: ShipWorldCore? } val Level?.shipObjectWorld - get() = shipWorldNullable ?: DummyShipWorldClient + get() = shipWorldNullable ?: vsCore.dummyShipWorldClient val Level?.allShips get() = this.shipObjectWorld.allShips val MinecraftServer.shipObjectWorld: ServerShipWorldCore - get() = (this as IShipObjectWorldServerProvider).shipObjectWorld ?: DummyShipWorldServer + get() = (this as IShipObjectWorldServerProvider).shipObjectWorld ?: vsCore.dummyShipWorldServer val MinecraftServer.vsPipeline get() = (this as IShipObjectWorldServerProvider).vsPipeline!! -val ServerLevel?.shipObjectWorld: ServerShipWorldCore get() = this?.server?.shipObjectWorld ?: DummyShipWorldServer +val ServerLevel?.shipObjectWorld: ServerShipWorldCore get() = this?.server?.shipObjectWorld ?: vsCore.dummyShipWorldServer val Level.dimensionId: DimensionId get() { @@ -100,7 +98,7 @@ fun MinecraftServer.executeIf(condition: () -> Boolean, toExecute: Runnable) { } } -val Level.yRange get() = LevelYRange(minBuildHeight, maxBuildHeight) +val Level.yRange get() = LevelYRange(minBuildHeight, maxBuildHeight - 1) fun Level.isTickingChunk(pos: ChunkPos) = isTickingChunk(pos.x, pos.z) fun Level.isTickingChunk(chunkX: Int, chunkZ: Int) = @@ -110,7 +108,7 @@ fun MinecraftServer.getLevelFromDimensionId(dimensionId: DimensionId): ServerLev return getLevel(getResourceKey(dimensionId)) } -val Minecraft.shipObjectWorld get() = (this as IShipObjectWorldClientProvider).shipObjectWorld ?: DummyShipWorldClient +val Minecraft.shipObjectWorld get() = (this as IShipObjectWorldClientProvider).shipObjectWorld ?: vsCore.dummyShipWorldClient val ClientLevel?.shipObjectWorld get() = Minecraft.getInstance().shipObjectWorld val IPlayer.mcPlayer: Player get() = (this as MinecraftPlayer).playerEntityReference.get()!! @@ -175,7 +173,7 @@ private fun getShipObjectManagingPosImpl(world: Level?, chunkX: Int, chunkZ: Int * Get all ships intersecting an AABB in world-space, then call [cb] with the AABB itself, * followed by the AABB in the ship-space of the intersecting ships. */ -fun Level?.transformFromWorldToNearbyShipsAndWorld(aabb: AABB, cb: Consumer) { +fun Level.transformFromWorldToNearbyShipsAndWorld(aabb: AABB, cb: Consumer) { cb.accept(aabb) val tmpAABB = AABBd() getShipsIntersecting(aabb).forEach { ship -> @@ -295,7 +293,12 @@ fun ServerLevel?.getShipObjectManagingPos(pos: Vector3dc) = private fun getShipManagingPosImpl(world: Level?, x: Int, z: Int): Ship? { return if (world != null && world.isChunkInShipyard(x, z)) { - world.shipObjectWorld.allShips.getByChunkPos(x, z, world.dimensionId) + val ship = world.shipObjectWorld.allShips.getByChunkPos(x, z, world.dimensionId) + if (ship != null && ship.chunkClaimDimension == world.dimensionId) { + ship + } else { + null + } } else { null } @@ -401,8 +404,8 @@ fun Level?.getWorldCoordinates(blockPos: BlockPos, pos: Vector3d): Vector3d { return this.getShipObjectManagingPos(blockPos)?.transform?.shipToWorld?.transformPosition(pos) ?: pos } -fun Level?.getShipsIntersecting(aabb: AABB): Iterable = allShips.getIntersecting(aabb.toJOML()) -fun Level?.getShipsIntersecting(aabb: AABBdc): Iterable = allShips.getShipDataIntersecting(aabb) +fun Level.getShipsIntersecting(aabb: AABB): Iterable = getShipsIntersecting(aabb.toJOML()) +fun Level.getShipsIntersecting(aabb: AABBdc): Iterable = allShips.getIntersecting(aabb).filter { it.chunkClaimDimension == dimensionId } fun Level?.transformAabbToWorld(aabb: AABB): AABB = transformAabbToWorld(aabb.toJOML()).toMinecraft() fun Level?.transformAabbToWorld(aabb: AABBd) = this?.transformAabbToWorld(aabb, aabb) ?: aabb @@ -411,7 +414,7 @@ fun Level.transformAabbToWorld(aabb: AABBdc, dest: AABBd): AABBd { val ship2 = getShipManagingPos(aabb.maxX(), aabb.maxY(), aabb.maxZ()) // if both endpoints of the aabb are in the same ship, do the transform - if (ship1 == ship2 && ship1 != null) { + if (ship1 == ship2 && ship1 != null && ship1.chunkClaimDimension == dimensionId) { return aabb.transform(ship1.shipToWorld, dest) } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt index 822682efe..d14b0ee8e 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/ValkyrienSkiesMod.kt @@ -20,6 +20,7 @@ import org.valkyrienskies.core.impl.hooks.VSEvents import org.valkyrienskies.mod.common.blockentity.TestHingeBlockEntity import org.valkyrienskies.mod.common.config.VSGameConfig import org.valkyrienskies.mod.common.entity.ShipMountingEntity +import org.valkyrienskies.mod.common.entity.VSPhysicsEntity import org.valkyrienskies.mod.common.networking.VSGamePackets import org.valkyrienskies.mod.common.util.GameTickForceApplier @@ -27,17 +28,16 @@ object ValkyrienSkiesMod { const val MOD_ID = "valkyrienskies" lateinit var TEST_CHAIR: Block - lateinit var TEST_CHAIR_ITEM: Item lateinit var TEST_HINGE: Block - lateinit var TEST_HINGE_ITEM: Item lateinit var TEST_FLAP: Block - lateinit var TEST_FLAP_ITEM: Item lateinit var TEST_WING: Block - lateinit var TEST_WING_ITEM: Item + lateinit var TEST_SPHERE: Block lateinit var SHIP_CREATOR_ITEM: Item lateinit var SHIP_ASSEMBLER_ITEM: Item lateinit var SHIP_CREATOR_ITEM_SMALLER: Item + lateinit var PHYSICS_ENTITY_CREATOR_ITEM: Item lateinit var SHIP_MOUNTING_ENTITY_TYPE: EntityType + lateinit var PHYSICS_ENTITY_TYPE: EntityType lateinit var TEST_HINGE_BLOCK_ENTITY_TYPE: BlockEntityType val VS_CREATIVE_TAB = ResourceKey.create(Registries.CREATIVE_MODE_TAB, ResourceLocation("valkyrienskies")) @@ -70,10 +70,10 @@ object ValkyrienSkiesMod { .title(Component.translatable("itemGroup.valkyrienSkies")) .icon { ItemStack(SHIP_CREATOR_ITEM) } .displayItems { _, output -> - output.accept(TEST_CHAIR_ITEM) - output.accept(TEST_HINGE_ITEM) - output.accept(TEST_FLAP_ITEM) - output.accept(TEST_WING_ITEM) + output.accept(TEST_CHAIR.asItem()) + output.accept(TEST_HINGE.asItem()) + output.accept(TEST_FLAP.asItem()) + output.accept(TEST_WING.asItem()) output.accept(SHIP_CREATOR_ITEM) output.accept(SHIP_ASSEMBLER_ITEM) output.accept(SHIP_CREATOR_ITEM_SMALLER) diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/SeamlessChunksManager.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/SeamlessChunksManager.kt index 2ea311d60..bb8aac7ab 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/SeamlessChunksManager.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/SeamlessChunksManager.kt @@ -13,7 +13,7 @@ import org.valkyrienskies.core.api.ships.ClientShip import org.valkyrienskies.core.api.ships.properties.ChunkClaim import org.valkyrienskies.core.impl.hooks.VSEvents.ShipLoadEventClient import org.valkyrienskies.core.impl.networking.simple.registerClientHandler -import org.valkyrienskies.core.impl.util.pollUntilEmpty +import org.valkyrienskies.core.util.pollUntilEmpty import org.valkyrienskies.mod.common.getShipManagingPos import org.valkyrienskies.mod.common.isChunkInShipyard import org.valkyrienskies.mod.common.networking.PacketRestartChunkUpdates diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembly.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembly.kt index 81b7a4ce7..8df8aea74 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembly.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/assembly/ShipAssembly.kt @@ -5,7 +5,7 @@ import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.ChunkPos import org.joml.Vector3d import org.valkyrienskies.core.api.ships.ServerShip -import org.valkyrienskies.core.impl.datastructures.DenseBlockPosSet +import org.valkyrienskies.core.util.datastructures.DenseBlockPosSet import org.valkyrienskies.core.impl.game.ships.ShipData import org.valkyrienskies.core.impl.game.ships.ShipTransformImpl import org.valkyrienskies.core.impl.networking.simple.sendToClient diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestChairBlock.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestChairBlock.kt index d351871ca..01b589c1e 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestChairBlock.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestChairBlock.kt @@ -14,21 +14,20 @@ import net.minecraft.world.level.block.HorizontalDirectionalBlock import net.minecraft.world.level.block.SoundType import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.StateDefinition -import net.minecraft.world.level.material.MapColor import net.minecraft.world.phys.BlockHitResult import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import org.joml.Vector3d import org.joml.Vector3dc -import org.valkyrienskies.core.impl.util.x -import org.valkyrienskies.core.impl.util.y -import org.valkyrienskies.core.impl.util.z +import org.valkyrienskies.core.util.x +import org.valkyrienskies.core.util.y +import org.valkyrienskies.core.util.z import org.valkyrienskies.mod.common.ValkyrienSkiesMod import org.valkyrienskies.mod.common.util.toDoubles object TestChairBlock : HorizontalDirectionalBlock( - Properties.of().mapColor(MapColor.WOOL).strength(1.0f, 120.0f).sound(SoundType.WOOL).requiresCorrectToolForDrops() + Properties.of().strength(1.0f, 120.0f).sound(SoundType.WOOL) ) { private val SEAT_AABB: VoxelShape = box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0) @@ -47,7 +46,7 @@ object TestChairBlock : @Deprecated("Deprecated in Java") override fun getShape( - state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext + state: BlockState, level: BlockGetter?, pos: BlockPos?, context: CollisionContext? ): VoxelShape = SEAT_AABB @Deprecated("Deprecated in Java") diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestFlapBlock.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestFlapBlock.kt index c3d3506af..33c2a429d 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestFlapBlock.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestFlapBlock.kt @@ -15,7 +15,6 @@ import net.minecraft.world.level.block.DirectionalBlock import net.minecraft.world.level.block.SoundType import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.StateDefinition -import net.minecraft.world.level.material.MapColor import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import org.valkyrienskies.core.api.ships.Wing @@ -23,7 +22,7 @@ import org.valkyrienskies.mod.common.util.toJOMLD object TestFlapBlock : DirectionalBlock( - Properties.of().mapColor(MapColor.METAL).strength(10.0f, 1200.0f).sound(SoundType.METAL).requiresCorrectToolForDrops() + Properties.of().strength(10.0f, 1200.0f).sound(SoundType.METAL) ), WingBlock { private val EAST_AABB = box(4.0, 0.0, 0.0, 12.0, 16.0, 16.0) diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestHingeBlock.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestHingeBlock.kt index 0acece596..b2cf03379 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestHingeBlock.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestHingeBlock.kt @@ -24,7 +24,6 @@ import net.minecraft.world.level.block.entity.BlockEntityTicker import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.StateDefinition -import net.minecraft.world.level.material.MapColor import net.minecraft.world.phys.BlockHitResult import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape @@ -47,7 +46,7 @@ import kotlin.math.roundToInt object TestHingeBlock : DirectionalBlock( - Properties.of().mapColor(MapColor.METAL).strength(10.0f, 1200.0f).sound(SoundType.WOOL).requiresCorrectToolForDrops() + Properties.of().strength(10.0f, 1200.0f).sound(SoundType.METAL) ), EntityBlock { private val EAST_AABB = box(0.0, 0.0, 0.0, 8.0, 16.0, 16.0) @@ -71,7 +70,7 @@ object TestHingeBlock : @Deprecated("Deprecated in Java") override fun getShape( - state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext + state: BlockState, level: BlockGetter?, pos: BlockPos?, context: CollisionContext? ): VoxelShape { when (state.getValue(FACING)) { DOWN -> { diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestSphereBlock.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestSphereBlock.kt new file mode 100644 index 000000000..3449b717a --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestSphereBlock.kt @@ -0,0 +1,27 @@ +package org.valkyrienskies.mod.common.block + +import net.minecraft.core.BlockPos +import net.minecraft.world.level.BlockGetter +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.phys.shapes.CollisionContext +import net.minecraft.world.phys.shapes.Shapes +import net.minecraft.world.phys.shapes.VoxelShape + +object TestSphereBlock : Block(Properties.of()) { + override fun getVisualShape( + blockState: BlockState?, blockGetter: BlockGetter?, blockPos: BlockPos?, collisionContext: CollisionContext? + ): VoxelShape { + return Shapes.empty() + } + + override fun getShadeBrightness(blockState: BlockState?, blockGetter: BlockGetter?, blockPos: BlockPos?): Float { + return 1.0f + } + + override fun propagatesSkylightDown( + blockState: BlockState?, blockGetter: BlockGetter?, blockPos: BlockPos? + ): Boolean { + return true + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestWingBlock.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestWingBlock.kt index 6b3fee44f..57542ced8 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestWingBlock.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestWingBlock.kt @@ -15,7 +15,6 @@ import net.minecraft.world.level.block.DirectionalBlock import net.minecraft.world.level.block.SoundType import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.StateDefinition -import net.minecraft.world.level.material.MapColor import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import org.valkyrienskies.core.api.ships.Wing @@ -23,7 +22,7 @@ import org.valkyrienskies.mod.common.util.toJOMLD object TestWingBlock : DirectionalBlock( - Properties.of().mapColor(MapColor.METAL).strength(10.0f, 1200.0f).sound(SoundType.WOOL).requiresCorrectToolForDrops() + Properties.of().strength(10.0f, 1200.0f).sound(SoundType.METAL) ), WingBlock { private val EAST_AABB = box(4.0, 0.0, 0.0, 12.0, 16.0, 16.0) diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/command/RelativeVector3Argument.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/command/RelativeVector3Argument.kt index a6d0b1394..29a59b17a 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/command/RelativeVector3Argument.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/command/RelativeVector3Argument.kt @@ -11,6 +11,7 @@ import net.minecraft.commands.CommandSourceStack import net.minecraft.commands.arguments.coordinates.RotationArgument import net.minecraft.commands.arguments.coordinates.WorldCoordinate import net.minecraft.network.chat.Component +import net.minecraft.network.chat.Component.translatable import java.util.concurrent.CompletableFuture class RelativeVector3Argument : ArgumentType { diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/command/ShipArgument.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/command/ShipArgument.kt index 9687f8f4c..9c9aaf2d2 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/command/ShipArgument.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/command/ShipArgument.kt @@ -1,5 +1,6 @@ package org.valkyrienskies.mod.common.command +import com.google.gson.JsonObject import com.mojang.brigadier.StringReader import com.mojang.brigadier.arguments.ArgumentType import com.mojang.brigadier.context.CommandContext @@ -7,7 +8,9 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException import com.mojang.brigadier.suggestion.Suggestions import com.mojang.brigadier.suggestion.SuggestionsBuilder import net.minecraft.commands.CommandRuntimeException +import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.chat.Component +import net.minecraft.network.chat.Component.translatable import org.valkyrienskies.core.api.ships.Ship import org.valkyrienskies.mod.mixinducks.feature.command.VSCommandSource import java.util.concurrent.CompletableFuture diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/command/ShipArgumentParser.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/command/ShipArgumentParser.kt index d70d40405..00adb0621 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/command/ShipArgumentParser.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/command/ShipArgumentParser.kt @@ -24,62 +24,73 @@ class ShipArgumentParser(private val source: VSCommandSource?, private var selec // Read the selector type if (reader.read() == '@') { - reader.expectR('v') - - suggestOpenOptions() - if (reader.canRead() && reader.read() == '[') { - - // Read the selector arguments ex @v[slug=mogus,limit=1] - while (reader.canRead() && reader.peek() != ']') { - suggestOptions() - reader.skipWhitespace() - - val i = reader.cursor - val s = reader.readString() - - if (!isOption(s)) { - if (isForSuggestion) { - reader.cursor = i - throw ERROR_UNKNOWN_OPTION.createWithContext(reader, s) + if (!reader.canRead()) { + // Suggest "v" + suggest { builder, _ -> + builder.suggest("v") + } + } else { + reader.read() + + if (!reader.canRead()) { + suggestOpenOptions() + } else if (reader.read() == '[') { + if (!reader.canRead()) { + suggestOptions() + } else { + // Read the selector arguments ex @v[slug=mogus,limit=1] + while (reader.canRead() && reader.peek() != ']') { + val i = reader.cursor + val s = reader.readString() + + suggestOptions(s) + reader.skipWhitespace() + + if (!isOption(s)) { + if (isForSuggestion) { + reader.cursor = i + throw ERROR_UNKNOWN_OPTION.createWithContext(reader, s) + } + // If not for suggestion then we cannot throw an exception + // otherwise MC won't generate suggestions for this argument + return ShipSelector(null, null, 0) + } + + reader.skipWhitespace() + + suggestEquals() + + if (!reader.canRead() || reader.peek() != '=') { + throw ERROR_EXPECTED_OPTION_VALUE.createWithContext(reader, s) + } + + reader.skip() + reader.skipWhitespace() + + suggestionsOfOption(s) + + reader.skipWhitespace() + if (reader.canRead()) + parseOption(s, reader) + else throw ERROR_EXPECTED_OPTION_VALUE.createWithContext(reader, s) + reader.skipWhitespace() + + suggestOptionsNextOrClose() + reader.skipWhitespace() } - // If not for suggestion then we cannot throw an exception - // otherwise MC won't generate suggestions for this argument - return ShipSelector(null, null, 0) - } - - reader.skipWhitespace() - - suggestEquals() - - if (!reader.canRead() || reader.peek() != '=') { - throw ERROR_EXPECTED_OPTION_VALUE.createWithContext(reader, s) } - reader.skip() - reader.skipWhitespace() - - suggestionsOfOption(s) - - reader.skipWhitespace() - if (reader.canRead()) - parseOption(s, reader) - else throw ERROR_EXPECTED_OPTION_VALUE.createWithContext(reader, s) - reader.skipWhitespace() + if (!reader.canRead() || reader.read() != ']') + if (isForSuggestion) { + throw ERROR_EXPECTED_END_OF_OPTIONS.createWithContext(reader) + }else { + // If not for suggestion then we cannot throw an exception + // otherwise MC won't generate suggestions for this argument + return ShipSelector(null, null, 0) + } - suggestOptionsNextOrClose() - reader.skipWhitespace() + suggest { _, _ -> } } - - if (!reader.canRead() || reader.read() != ']') - if (isForSuggestion) { - throw ERROR_EXPECTED_END_OF_OPTIONS.createWithContext(reader) - }else { - // If not for suggestion then we cannot throw an exception - // otherwise MC won't generate suggestions for this argument - return ShipSelector(null, null, 0) - } - - suggest { _, _ -> } } } else if (!selectorOnly) { suggestionsOfOption("slug") @@ -97,10 +108,16 @@ class ShipArgumentParser(private val source: VSCommandSource?, private var selec } // TODO keep a dynamic list of options... - private fun suggestOptions() = suggest { builder, source -> - builder.suggest("slug=") - builder.suggest("limit=") - builder.suggest("id=") + private fun suggestOptions(textSoFar: String? = null) = suggest { builder, source -> + if (textSoFar == null) { + builder.suggest("slug=") + builder.suggest("limit=") + builder.suggest("id=") + } else { + if ("slug=".startsWith(textSoFar)) builder.suggest("slug=") + if ("limit=".startsWith(textSoFar)) builder.suggest("limit=") + if ("id=".startsWith(textSoFar)) builder.suggest("id=") + } } private fun suggestSelectorOrSlug() = suggest { builder, source -> diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/command/VSCommands.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/command/VSCommands.kt index 07e692ef5..63597f2db 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/command/VSCommands.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/command/VSCommands.kt @@ -3,6 +3,7 @@ package org.valkyrienskies.mod.common.command import com.mojang.brigadier.CommandDispatcher import com.mojang.brigadier.arguments.ArgumentType import com.mojang.brigadier.arguments.BoolArgumentType +import com.mojang.brigadier.arguments.DoubleArgumentType import com.mojang.brigadier.arguments.StringArgumentType import com.mojang.brigadier.builder.LiteralArgumentBuilder import com.mojang.brigadier.builder.RequiredArgumentBuilder @@ -13,6 +14,7 @@ import net.minecraft.commands.arguments.EntityArgument import net.minecraft.commands.arguments.coordinates.BlockPosArgument import net.minecraft.commands.arguments.coordinates.Vec3Argument import net.minecraft.network.chat.Component +import net.minecraft.network.chat.Component.translatable import net.minecraft.world.entity.Entity import net.minecraft.world.phys.BlockHitResult import org.joml.Vector3d @@ -23,9 +25,10 @@ import org.valkyrienskies.core.apigame.ShipTeleportData import org.valkyrienskies.core.impl.game.ShipTeleportDataImpl import org.valkyrienskies.core.impl.game.ships.ShipData import org.valkyrienskies.core.impl.game.ships.ShipObject -import org.valkyrienskies.core.impl.util.x -import org.valkyrienskies.core.impl.util.y -import org.valkyrienskies.core.impl.util.z +import org.valkyrienskies.core.util.x +import org.valkyrienskies.core.util.y +import org.valkyrienskies.core.util.z +import org.valkyrienskies.mod.common.dimensionId import org.valkyrienskies.mod.common.getShipManagingPos import org.valkyrienskies.mod.common.util.toJOML import org.valkyrienskies.mod.common.util.toJOMLD diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/config/VSGameConfig.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/config/VSGameConfig.kt index ff408f762..fe225d812 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/config/VSGameConfig.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/config/VSGameConfig.kt @@ -17,6 +17,8 @@ object VSGameConfig { class Client { val Tooltip = TOOLTIP() + val BlockTinting = BLOCKTINT() + @JsonSchema(description = "Renders the VS2 debug HUD with TPS") var renderDebugText = false @@ -36,6 +38,13 @@ object VSGameConfig { ) var useImperialUnits = false } + + class BLOCKTINT { + @JsonSchema( + description = "Partly fixes the block tinting issue with blocks on ships" + ) + var fixBlockTinting = false + } } class Server { diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/config/VSMassDataLoader.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/config/VSMassDataLoader.kt index 4ce7006f7..097e1bed6 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/config/VSMassDataLoader.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/config/VSMassDataLoader.kt @@ -2,6 +2,7 @@ package org.valkyrienskies.mod.common.config import com.google.gson.Gson import com.google.gson.JsonElement +import net.minecraft.core.BlockPos import net.minecraft.core.HolderSet import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.core.registries.Registries @@ -10,22 +11,63 @@ import net.minecraft.server.packs.resources.ResourceManager import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener import net.minecraft.tags.TagKey import net.minecraft.util.profiling.ProfilerFiller +import net.minecraft.world.level.BlockGetter import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.Blocks +import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.material.FluidState +import net.minecraft.world.level.material.Fluids +import net.minecraft.world.phys.shapes.VoxelShape +import org.joml.Vector3f +import org.joml.Vector3i +import org.valkyrienskies.core.apigame.world.chunks.BlockType import org.valkyrienskies.core.game.VSBlockType +import org.valkyrienskies.core.impl.collision.Lod1SolidShapeUtils +import org.valkyrienskies.core.impl.game.BlockTypeImpl import org.valkyrienskies.mod.common.BlockStateInfoProvider import org.valkyrienskies.mod.common.hooks.VSGameEvents +import org.valkyrienskies.mod.common.vsCore +import org.valkyrienskies.mod.mixin.accessors.world.level.block.SlabBlockAccessor +import org.valkyrienskies.mod.mixin.accessors.world.level.block.StairBlockAccessor import org.valkyrienskies.mod.util.logger +import org.valkyrienskies.physics_api.Lod1BlockStateId +import org.valkyrienskies.physics_api.Lod1LiquidBlockStateId +import org.valkyrienskies.physics_api.Lod1SolidBlockStateId +import org.valkyrienskies.physics_api.voxel.CollisionPoint +import org.valkyrienskies.physics_api.voxel.Lod1LiquidBlockState +import org.valkyrienskies.physics_api.voxel.Lod1SolidBlockState +import org.valkyrienskies.physics_api.voxel.Lod1SolidBoxesCollisionShape +import org.valkyrienskies.physics_api.voxel.Lod1SolidCollisionShape +import org.valkyrienskies.physics_api.voxel.LodBlockBoundingBox import java.util.Optional +import kotlin.math.max +import kotlin.math.min +import kotlin.math.roundToInt private data class VSBlockStateInfo( - val id: ResourceLocation, val priority: Int, val mass: Double, val type: VSBlockType? + val id: ResourceLocation, + val priority: Int, + val mass: Double, + val friction: Double, + val elasticity: Double, + val type: VSBlockType?, ) object MassDatapackResolver : BlockStateInfoProvider { private val map = hashMapOf() + private val _solidBlockStates: MutableList = ArrayList() + private val _liquidBlockStates: MutableList = ArrayList() + private val _blockStateData: MutableList> = ArrayList() + private val blockStateToId: MutableMap = HashMap() + val loader get() = VSMassDataLoader() + private const val DEFAULT_ELASTICITY = 0.3 + private const val DEFAULT_FRICTION = 0.5 + // Unused for now, placeholder for later + private const val DEFAULT_HARDNESS = 1.0 + override val priority: Int get() = 100 @@ -33,15 +75,25 @@ object MassDatapackResolver : BlockStateInfoProvider { map[BuiltInRegistries.BLOCK.getKey(blockState.block)]?.mass override fun getBlockStateType(blockState: BlockState): VSBlockType? = - map[BuiltInRegistries.BLOCK.getKey(blockState.block)]?.type + blockStateToId[blockState]!! + + var registeredBlocks = false + private set + + override val solidBlockStates: List + get() = _solidBlockStates + override val liquidBlockStates: List + get() = _liquidBlockStates + override val blockStateData: List> + get() = _blockStateData class VSMassDataLoader : SimpleJsonResourceReloadListener(Gson(), "vs_mass") { private val tags = mutableListOf() override fun apply( - objects: MutableMap, - resourceManager: ResourceManager, - profiler: ProfilerFiller + objects: MutableMap?, + resourceManager: ResourceManager?, + profiler: ProfilerFiller? ) { map.clear() tags.clear() @@ -75,7 +127,8 @@ object MassDatapackResolver : BlockStateInfoProvider { tag.get().forEach { add( VSBlockStateInfo( - BuiltInRegistries.BLOCK.getKey(it.value()), tagInfo.priority, tagInfo.mass, tagInfo.type + BuiltInRegistries.BLOCK.getKey(it.value()), tagInfo.priority, tagInfo.mass, tagInfo.friction, + tagInfo.elasticity, tagInfo.type ) ) } @@ -104,18 +157,293 @@ object MassDatapackResolver : BlockStateInfoProvider { val tag = element.asJsonObject["tag"]?.asString val weight = element.asJsonObject["mass"]?.asDouble ?: throw IllegalArgumentException("No mass in file $origin") + val friction = element.asJsonObject["friction"]?.asDouble ?: DEFAULT_FRICTION + val elasticity = element.asJsonObject["elasticity"]?.asDouble ?: DEFAULT_ELASTICITY val priority = element.asJsonObject["priority"]?.asInt ?: 100 if (tag != null) { - addToBeAddedTags(VSBlockStateInfo(ResourceLocation(tag), priority, weight, null)) + addToBeAddedTags(VSBlockStateInfo(ResourceLocation(tag), priority, weight, friction, elasticity, null)) } else { val block = element.asJsonObject["block"]?.asString ?: throw IllegalArgumentException("No block or tag in file $origin") - add(VSBlockStateInfo(ResourceLocation(block), priority, weight, null)) + add(VSBlockStateInfo(ResourceLocation(block), priority, weight, friction, elasticity, null)) + } + } + } + + private fun generateStairCollisionShapes(stairShapes: Array): Map { + val testPoints = listOf( + CollisionPoint(Vector3f(.25f, .25f, .25f), .25f), + CollisionPoint(Vector3f(.25f, .25f, .75f), .25f), + CollisionPoint(Vector3f(.25f, .75f, .25f), .25f), + CollisionPoint(Vector3f(.25f, .75f, .75f), .25f), + CollisionPoint(Vector3f(.75f, .25f, .25f), .25f), + CollisionPoint(Vector3f(.75f, .25f, .75f), .25f), + CollisionPoint(Vector3f(.75f, .75f, .25f), .25f), + CollisionPoint(Vector3f(.75f, .75f, .75f), .25f), + ) + + val testBoxes = listOf( + LodBlockBoundingBox.createVSBoundingBox(0, 0, 0, 7, 7, 7), + LodBlockBoundingBox.createVSBoundingBox(0, 0, 8, 7, 7, 15), + LodBlockBoundingBox.createVSBoundingBox(0, 8, 0, 7, 15, 7), + LodBlockBoundingBox.createVSBoundingBox(0, 8, 8, 7, 15, 15), + LodBlockBoundingBox.createVSBoundingBox(8, 0, 0, 15, 7, 7), + LodBlockBoundingBox.createVSBoundingBox(8, 0, 8, 15, 7, 15), + LodBlockBoundingBox.createVSBoundingBox(8, 8, 0, 15, 15, 7), + LodBlockBoundingBox.createVSBoundingBox(8, 8, 8, 15, 15, 15), + ) + + val map: MutableMap = HashMap() + stairShapes.forEach { stairShape -> + val points: MutableList = ArrayList() + val positiveBoxes: MutableList = ArrayList() + val negativeBoxes: MutableList = ArrayList() + testPoints.forEachIndexed { index, testPoint -> + var added = false + stairShape.forAllBoxes { minX, minY, minZ, maxX, maxY, maxZ -> + if (testPoint.pos.x() in minX .. maxX && testPoint.pos.y() in minY .. maxY && testPoint.pos.z() in minZ .. maxZ) { + points.add(testPoint) + added = true + return@forAllBoxes + } + } + if (added) { + positiveBoxes.add(testBoxes[index]) + } else { + negativeBoxes.add(testBoxes[index]) + } + } + val minTotalAABB = Vector3i(positiveBoxes[0].minX.toInt(), positiveBoxes[0].minY.toInt(), positiveBoxes[0].minZ.toInt()) + val maxTotalAABB = Vector3i(positiveBoxes[0].maxX.toInt(), positiveBoxes[0].maxY.toInt(), positiveBoxes[0].maxZ.toInt()) + for (i in 1 until positiveBoxes.size) { + minTotalAABB.x = min(minTotalAABB.x, positiveBoxes[i].minX.toInt()) + minTotalAABB.y = min(minTotalAABB.y, positiveBoxes[i].minY.toInt()) + minTotalAABB.z = min(minTotalAABB.z, positiveBoxes[i].minZ.toInt()) + maxTotalAABB.x = max(maxTotalAABB.x, positiveBoxes[i].maxX.toInt()) + maxTotalAABB.y = max(maxTotalAABB.y, positiveBoxes[i].maxY.toInt()) + maxTotalAABB.z = max(maxTotalAABB.z, positiveBoxes[i].maxZ.toInt()) + } + val overallBox = LodBlockBoundingBox.createVSBoundingBox( + minTotalAABB.x.toByte(), minTotalAABB.y.toByte(), minTotalAABB.z.toByte(), maxTotalAABB.x.toByte(), + maxTotalAABB.y.toByte(), maxTotalAABB.z.toByte() + ) + val collisionShape = Lod1SolidBoxesCollisionShape( + overallBoundingBox = overallBox, + collisionPoints = points, + solidBoxes = Lod1SolidShapeUtils.mergeBoxes(positiveBoxes), + negativeBoxes = Lod1SolidShapeUtils.mergeBoxes(negativeBoxes), + ) + map[stairShape] = collisionShape + } + return map + } + + private fun generateShapeFromVoxel(voxelShape: VoxelShape): Lod1SolidBoxesCollisionShape? { + val posBoxes = ArrayList() + var failed = false + var maxBoxesToTest = 20 + voxelShape.forAllBoxes { minX, minY, minZ, maxX, maxY, maxZ -> + if (failed) { + return@forAllBoxes + } + val lodMinX = (minX * 16).roundToInt().toByte() + val lodMinY = (minY * 16).roundToInt().toByte() + val lodMinZ = (minZ * 16).roundToInt().toByte() + val lodMaxX = ((maxX * 16).roundToInt() - 1).toByte() + val lodMaxY = ((maxY * 16).roundToInt() - 1).toByte() + val lodMaxZ = ((maxZ * 16).roundToInt() - 1).toByte() + if (lodMinX !in 0..15 || lodMinY !in 0..15 || lodMinZ !in 0..15 || lodMaxX !in 0..15 || lodMaxY !in 0..15 || lodMaxZ !in 0..15) { + // Out of range + failed = true + return@forAllBoxes + } else { + posBoxes.add( + LodBlockBoundingBox.createVSBoundingBox(lodMinX, lodMinY, lodMinZ, lodMaxX, lodMaxY, lodMaxZ) + ) + } + if (maxBoxesToTest == 0) { + failed = true + } else { + maxBoxesToTest-- } } + return if (!failed) { + Lod1SolidShapeUtils.generateShapeFromBoxes(posBoxes) + } else { + null + } + } + + fun registerAllBlockStates(blockStates: Iterable) { + val fullLodBoundingBox = LodBlockBoundingBox.createVSBoundingBox(0, 0, 0, 15, 15, 15) + val fullBlockCollisionPoints = listOf( + CollisionPoint(Vector3f(.25f, .25f, .25f), .25f), + CollisionPoint(Vector3f(.25f, .25f, .75f), .25f), + CollisionPoint(Vector3f(.25f, .75f, .25f), .25f), + CollisionPoint(Vector3f(.25f, .75f, .75f), .25f), + CollisionPoint(Vector3f(.75f, .25f, .25f), .25f), + CollisionPoint(Vector3f(.75f, .25f, .75f), .25f), + CollisionPoint(Vector3f(.75f, .75f, .25f), .25f), + CollisionPoint(Vector3f(.75f, .75f, .75f), .25f), + ) + val fullBlockCollisionShape = Lod1SolidBoxesCollisionShape( + overallBoundingBox = fullLodBoundingBox, + collisionPoints = fullBlockCollisionPoints, + solidBoxes = listOf(fullLodBoundingBox), + negativeBoxes = listOf(), + ) + + // Add default block states + run { + // region Add default solid block state + val solidBlockState = Lod1SolidBlockState( + collisionShape = fullBlockCollisionShape, + elasticity = DEFAULT_ELASTICITY.toFloat(), + friction = DEFAULT_FRICTION.toFloat(), + hardness = DEFAULT_HARDNESS.toFloat(), + lod1SolidBlockStateId = BlockTypeImpl.SOLID.toInt(), + ) + _solidBlockStates.add(solidBlockState) + _blockStateData.add(Triple(BlockTypeImpl.SOLID.toInt(), BlockTypeImpl.AIR.toInt(), BlockTypeImpl.SOLID.toInt())) + // endregion + + // region Add default water/lava liquid block states + val waterBlockState = Lod1LiquidBlockState( + boundingBox = fullLodBoundingBox, + density = 1000.0f, + dragCoefficient = 0.3f, + fluidVel = Vector3f(), + lod1LiquidBlockStateId = BlockTypeImpl.WATER.toInt(), + ) + + val lavaBlockState = Lod1LiquidBlockState( + boundingBox = fullLodBoundingBox, + density = 10000.0f, + dragCoefficient = 1.0f, + fluidVel = Vector3f(), + lod1LiquidBlockStateId = BlockTypeImpl.LAVA.toInt(), + ) + + _liquidBlockStates.add(waterBlockState) + _liquidBlockStates.add(lavaBlockState) + _blockStateData.add(Triple(BlockTypeImpl.AIR.toInt(), BlockTypeImpl.WATER.toInt(), BlockTypeImpl.WATER.toInt())) + _blockStateData.add(Triple(BlockTypeImpl.AIR.toInt(), BlockTypeImpl.LAVA.toInt(), BlockTypeImpl.LAVA.toInt())) + // endregion + } + + // A dummy world used to get the VoxelShape for each block state + val dummyBlockGetter = object: BlockGetter { + override fun getHeight(): Int = 255 + + override fun getMinBuildHeight(): Int = 0 + + override fun getBlockEntity(blockPos: BlockPos): BlockEntity? = null + + override fun getBlockState(blockPos: BlockPos): BlockState = Blocks.VOID_AIR.defaultBlockState() + + override fun getFluidState(blockPos: BlockPos): FluidState = Fluids.EMPTY.defaultFluidState() + } + + // Create a map of common VoxelShape to Lod1SolidCollisionShape + val voxelShapeToCollisionShapeMap = generateStairCollisionShapes( + StairBlockAccessor.getTopShapes() + StairBlockAccessor.getBottomShapes() + SlabBlockAccessor.getBottomAABB() + SlabBlockAccessor.getTopAABB() + ) + + // Setup initial conditions for future ids + var nextSolidId = 2 + var nextFluidId = 4 + var nextVoxelStateId = 4 + + val generatedCollisionShapesMap = HashMap() + val liquidMaterialToDensityMap = mapOf(Fluids.WATER to Pair(1000.0f, 0.3f), Fluids.LAVA to Pair(10000.0f, 1.0f), Fluids.FLOWING_WATER to Pair(1000.0f, 0.3f), Fluids.FLOWING_LAVA to Pair(10000.0f, 1.0f)) + + val fluidStateToBlockTypeMap = HashMap>() + + // Get the id of the fluid state/create a new fluid state if necessary + fun getFluidState(fluidState: FluidState): Pair { + val cached = fluidStateToBlockTypeMap[fluidState] + if (cached != null) return cached + val maxY = ((fluidState.ownHeight * 16.0).roundToInt() - 1).coerceIn(0, 15).toByte() + val fluidBox = LodBlockBoundingBox.createVSBoundingBox(0, 0, 0, 15, maxY, 15) + if (fluidState.type in liquidMaterialToDensityMap) { + val (density, dragCoefficient) = liquidMaterialToDensityMap[fluidState.type]!! + val newFluidBlockState = Lod1LiquidBlockState( + boundingBox = fluidBox, + density = density, + dragCoefficient = dragCoefficient, + fluidVel = Vector3f(), + lod1LiquidBlockStateId = nextFluidId++, + ) + val stateId = nextVoxelStateId++ + _liquidBlockStates.add(newFluidBlockState) + _blockStateData.add(Triple(BlockTypeImpl.AIR.toInt(), newFluidBlockState.lod1LiquidBlockStateId, stateId)) + val blockTypeNew = BlockTypeImpl(stateId) + fluidStateToBlockTypeMap[fluidState] = newFluidBlockState.lod1LiquidBlockStateId to blockTypeNew + return newFluidBlockState.lod1LiquidBlockStateId to blockTypeNew + } else { + // Default + return BlockTypeImpl.WATER.toInt() to BlockTypeImpl.WATER + } + } + + blockStates.forEach { blockState: BlockState -> + val blockType: BlockType + if (blockState.isAir) { + blockType = vsCore.blockTypes.air + } else { + blockType = if (blockState.liquid()) { + getFluidState(blockState.fluidState).second + } else if (blockState.isSolid) { + val voxelShape = blockState.getShape(dummyBlockGetter, BlockPos.ZERO) + + val collisionShape: Lod1SolidCollisionShape = if (voxelShapeToCollisionShapeMap.contains(voxelShape)) { + voxelShapeToCollisionShapeMap[voxelShape]!! + } else if (generatedCollisionShapesMap.contains(voxelShape)) { + if (generatedCollisionShapesMap[voxelShape] != null) { + generatedCollisionShapesMap[voxelShape]!! + } else { + fullBlockCollisionShape + } + } else { + val generated = generateShapeFromVoxel(voxelShape) + generatedCollisionShapesMap[voxelShape] = generated + generated ?: fullBlockCollisionShape + } + + val vsBlockStateInfo = map[BuiltInRegistries.BLOCK.getKey(blockState.block)] + + // Create new solid block state + val solidStateId = nextSolidId++ + val newSolidBlockState = Lod1SolidBlockState( + collisionShape = collisionShape, + elasticity = vsBlockStateInfo?.elasticity?.toFloat() ?: DEFAULT_ELASTICITY.toFloat(), + friction = vsBlockStateInfo?.friction?.toFloat() ?: DEFAULT_FRICTION.toFloat(), + hardness = DEFAULT_HARDNESS.toFloat(), + lod1SolidBlockStateId = solidStateId, + ) + _solidBlockStates.add(newSolidBlockState) + + // Create new voxel state + val blockStateId = nextVoxelStateId++ + + var fluidId = BlockTypeImpl.AIR.toInt() + if (!blockState.fluidState.isEmpty) { + fluidId = getFluidState(blockState.fluidState).first + } + + _blockStateData.add(Triple(solidStateId, fluidId, blockStateId)) + BlockTypeImpl(blockStateId) + } else { + vsCore.blockTypes.air + } + } + blockStateToId[blockState] = blockType + } + + registeredBlocks = true } private val logger by logger() diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/ShipMountingEntity.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/ShipMountingEntity.kt index 1f778ff4a..f8eb1f0fb 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/ShipMountingEntity.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/ShipMountingEntity.kt @@ -9,18 +9,20 @@ import net.minecraft.world.entity.Entity import net.minecraft.world.entity.EntityType import net.minecraft.world.entity.LivingEntity import net.minecraft.world.level.Level +import net.minecraft.world.phys.Vec3 import org.joml.Vector3f import org.valkyrienskies.core.api.ships.LoadedServerShip import org.valkyrienskies.core.api.ships.setAttachment import org.valkyrienskies.core.impl.networking.simple.sendToServer import org.valkyrienskies.mod.api.SeatedControllingPlayer import org.valkyrienskies.mod.common.config.VSKeyBindings +import org.valkyrienskies.mod.common.getShipManagingPos import org.valkyrienskies.mod.common.getShipObjectManagingPos +import org.valkyrienskies.mod.common.isBlockInShipyard import org.valkyrienskies.mod.common.networking.PacketPlayerDriving open class ShipMountingEntity(type: EntityType, level: Level) : Entity(type, level) { - - // Decides if this entity controlls the ship it is in. + // Decides if this entity controls the ship it is in. // Only needs to be set serverside var isController = false @@ -43,15 +45,36 @@ open class ShipMountingEntity(type: EntityType, level: Level sendDrivingPacket() } - override fun readAdditionalSaveData(compoundTag: CompoundTag) { + // This is a partial fix for mounting ships that have been deleted + // TODO: Make a full fix eventually + /* + override fun positionRider(entity: Entity) { + if (level().isBlockInShipyard(position()) && level().getShipManagingPos(position()) == null) { + // Stop rider positioning if we can't find the ship + entity.removeVehicle() + return + } + super.positionRider(entity) } - override fun addAdditionalSaveData(compoundTag: CompoundTag) { - } + */ - override fun defineSynchedData() { + // This is a partial fix for mounting ships that have been deleted + // TODO: Make a full fix eventually + override fun getDismountLocationForPassenger(livingEntity: LivingEntity): Vec3 { + if (level().isBlockInShipyard(position()) && level().getShipManagingPos(position()) == null) { + // Don't teleport to the ship if we can't find the ship + return livingEntity.position() + } + return super.getDismountLocationForPassenger(livingEntity) } + override fun readAdditionalSaveData(compound: CompoundTag) {} + + override fun addAdditionalSaveData(compound: CompoundTag) {} + + override fun defineSynchedData() {} + override fun remove(removalReason: RemovalReason) { if (this.isController && !level().isClientSide) (level().getShipObjectManagingPos(blockPosition()) as LoadedServerShip?) @@ -82,7 +105,7 @@ open class ShipMountingEntity(type: EntityType, level: Level override fun getControllingPassenger(): LivingEntity? { return if (isController) { - this.passengers.getOrNull(0) as? LivingEntity + this.passengers.getOrNull(0) as? LivingEntity } else { null } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/VSPhysicsEntity.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/VSPhysicsEntity.kt new file mode 100644 index 000000000..879b890f7 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/VSPhysicsEntity.kt @@ -0,0 +1,251 @@ +package org.valkyrienskies.mod.common.entity + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import net.minecraft.core.Rotations +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.game.ClientGamePacketListener +import net.minecraft.network.protocol.game.ClientboundAddEntityPacket +import net.minecraft.network.syncher.EntityDataAccessor +import net.minecraft.network.syncher.EntityDataSerializers +import net.minecraft.network.syncher.SynchedEntityData +import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.EntityType +import net.minecraft.world.level.Level +import net.minecraft.world.level.entity.EntityInLevelCallback +import org.joml.Matrix3d +import org.joml.Vector3d +import org.joml.Vector3dc +import org.valkyrienskies.core.api.ships.properties.ShipId +import org.valkyrienskies.core.api.ships.properties.ShipInertiaData +import org.valkyrienskies.core.api.ships.properties.ShipTransform +import org.valkyrienskies.core.apigame.physics.PhysicsEntityData +import org.valkyrienskies.core.apigame.physics.PhysicsEntityServer +import org.valkyrienskies.core.apigame.physics.VSSphereCollisionShapeData +import org.valkyrienskies.core.apigame.world.ServerShipWorldCore +import org.valkyrienskies.core.impl.game.ShipTeleportDataImpl +import org.valkyrienskies.core.impl.game.ships.ShipInertiaDataImpl +import org.valkyrienskies.core.impl.game.ships.ShipObjectClientWorld +import org.valkyrienskies.core.impl.game.ships.ShipObjectServerWorld +import org.valkyrienskies.core.impl.game.ships.ShipTransformImpl +import org.valkyrienskies.core.impl.util.serialization.VSJacksonUtil +import org.valkyrienskies.mod.common.dimensionId +import org.valkyrienskies.mod.common.shipObjectWorld +import org.valkyrienskies.mod.common.util.toJOML +import org.valkyrienskies.mod.common.util.toMinecraft +import org.valkyrienskies.mod.mixin.accessors.entity.EntityAccessor + +open class VSPhysicsEntity(type: EntityType, level: Level) : Entity(type, level) { + // Physics data, persistent + protected var physicsEntityData: PhysicsEntityData? = null + private set + + // The physics entity, transient, only exists server side after this entity has been added to a world + protected var physicsEntityServer: PhysicsEntityServer? = null + private set + + private var lerpPos: Vector3dc? = null + private var lerpSteps = 0 + + fun setPhysicsEntityData(physicsEntityData: PhysicsEntityData) { + if (this.physicsEntityData != null) { + throw IllegalStateException("Cannot define physicsEntityData, its already defined!") + } + this.physicsEntityData = physicsEntityData + if (!this.level().isClientSide) { + var defaultRot = Rotations(0.0f, 0.0f, 0.0f) + if (!this.level().isClientSide) { + val eulerAngles = physicsEntityData.transform.shipToWorldRotation.getEulerAnglesXYZ(Vector3d()) + defaultRot = Rotations(eulerAngles.x.toFloat(), eulerAngles.y.toFloat(), eulerAngles.z.toFloat()) + } + this.entityData.set(SHIP_ID_DATA, physicsEntityData.shipId.toString()) + } + } + + override fun tick() { + if (lerpPos == null) { + lerpPos = position().toJOML() + } + if (!this.level().isClientSide) { + val physicsEntityServerCopy = physicsEntityServer + if (physicsEntityServerCopy != null) { + val transform = physicsEntityServerCopy.shipTransform + this.setPos(transform.positionInWorld.toMinecraft()) + val eulerAngles = transform.shipToWorldRotation.getEulerAnglesXYZ(Vector3d()) + this.physicsEntityData!!.transform = transform + } + this.tryCheckInsideBlocks() + } else { + tickLerp() + } + super.tick() + } + + override fun lerpTo(d: Double, e: Double, f: Double, g: Float, h: Float, i: Int, bl: Boolean) { + this.lerpPos = Vector3d(d, e, f) + this.lerpSteps = CLIENT_INTERP_STEPS + } + + private fun tickLerp() { + if (this.lerpSteps <= 0) { + return + } else if (this.lerpSteps == 1) { + setPos(lerpPos!!.x(), lerpPos!!.y(), lerpPos!!.z()) + lerpSteps = 0 + return + } + + val d: Double = this.x + (this.lerpPos!!.x() - this.x) / this.lerpSteps.toDouble() + val e: Double = this.y + (this.lerpPos!!.y() - this.y) / this.lerpSteps.toDouble() + val f: Double = this.z + (this.lerpPos!!.z() - this.z) / this.lerpSteps.toDouble() + + --this.lerpSteps + this.setPos(d, e, f) + } + + fun getRenderTransform(shipObjectClientWorld: ShipObjectClientWorld): ShipTransform? { + val shipIdString = entityData.get(SHIP_ID_DATA) + if (shipIdString == "") { + return null + } + val shipIdLong = shipIdString.toLong() + val physEntityClient = shipObjectClientWorld.physicsEntities[shipIdLong] + return physEntityClient?.renderTransform + } + + override fun defineSynchedData() { + entityData.define(SHIP_ID_DATA, "") + } + + override fun readAdditionalSaveData(compoundTag: CompoundTag) { + } + + override fun addAdditionalSaveData(compoundTag: CompoundTag) { + } + + override fun getAddEntityPacket(): Packet { + return ClientboundAddEntityPacket(this) + } + + override fun saveWithoutId(compoundTag: CompoundTag): CompoundTag { + val physicsEntityDataAsBytes = getMapper().writeValueAsBytes(physicsEntityData) + compoundTag.putByteArray(PHYS_DATA_NBT_KEY, physicsEntityDataAsBytes) + return super.saveWithoutId(compoundTag) + } + + // Used when teleporting through nether portals to create a new entity that's almost the same as this one + // Note how a new shipId is generated, since this is meant to be a new copy not the exact same one + private fun loadForTeleport(compoundTag: CompoundTag) { + if (!this.level().isClientSide && physicsEntityData != null) { + throw IllegalStateException("This entity is already loaded!") + } + val physicsEntityDataAsBytes: ByteArray = compoundTag.getByteArray(PHYS_DATA_NBT_KEY) + val oldPhysicsEntityData = getMapper().readValue(physicsEntityDataAsBytes) + val newShipId = (level().shipObjectWorld as ShipObjectServerWorld).allocateShipId(level().dimensionId) + val newPhysicsEntityData = oldPhysicsEntityData.copyPhysicsEntityDataWithNewId(newShipId) + // Change the shipId to be something new + setPhysicsEntityData(newPhysicsEntityData) + super.load(compoundTag) + } + + override fun load(compoundTag: CompoundTag) { + if (!this.level().isClientSide && physicsEntityData != null) { + throw IllegalStateException("This entity is already loaded!") + } + val physicsEntityDataAsBytes: ByteArray = compoundTag.getByteArray(PHYS_DATA_NBT_KEY) + val physicsEntityData = getMapper().readValue(physicsEntityDataAsBytes) + setPhysicsEntityData(physicsEntityData) + super.load(compoundTag) + } + + override fun setLevelCallback(callback: EntityInLevelCallback?) { + super.setLevelCallback(callback) + if (!this.level().isClientSide) { + val isNull = (callback == null) || callback == EntityInLevelCallback.NULL + if (!isNull) { + // Try adding the rigid body of this entity from the world + if (physicsEntityServer != null) { + throw IllegalStateException("Rigid body is already in the world!") + } + physicsEntityServer = (level().shipObjectWorld as ServerShipWorldCore).createPhysicsEntity( + physicsEntityData!!, level().dimensionId + ) + } else { + // Try removing the rigid body of this entity from the world + if (physicsEntityServer == null) { + return + // throw IllegalStateException("Rigid body does not exist in the world!") + } + (level().shipObjectWorld as ServerShipWorldCore).deletePhysicsEntity(physicsEntityData!!.shipId) + physicsEntityServer = null + } + } + } + + override fun shouldRenderAtSqrDistance(d: Double): Boolean { + var e = this.boundingBox.size + if (java.lang.Double.isNaN(e)) { + e = 1.0 + } + e *= 1024.0 + return d < e * e + } + + override fun moveTo(d: Double, e: Double, f: Double, g: Float, h: Float) { + super.moveTo(d, e, f, g, h) + if (!this.level().isClientSide) { + val physicsEntityServerCopy = physicsEntityServer + if (physicsEntityServerCopy != null) { + val newPos = Vector3d(d, e, f) + val teleportData = ShipTeleportDataImpl(newPos = newPos) + (this.level().shipObjectWorld as ShipObjectServerWorld).teleportPhysicsEntity(this.physicsEntityServer!!, teleportData) + } else { + physicsEntityData!!.transform = ShipTransformImpl.create( + Vector3d(d, e, f), + Vector3d(), + physicsEntityData!!.transform.shipToWorldRotation, + ) + } + } + } + + // Used when teleporting through nether portals to create a new entity that's almost the same as this one + override fun restoreFrom(entity: Entity) { + val compoundTag = entity.saveWithoutId(CompoundTag()) + compoundTag.remove("Dimension") + loadForTeleport(compoundTag) + ((this as EntityAccessor).portalCooldown) = (entity as EntityAccessor).portalCooldown + portalEntrancePos = entity.portalEntrancePos + } + + companion object { + private const val PHYS_DATA_NBT_KEY = "phys_entity_data" + private const val CLIENT_INTERP_STEPS = 3 + + // Use string because there is no LONG serializer by default SMH my head! + private val SHIP_ID_DATA: EntityDataAccessor = + SynchedEntityData.defineId(VSPhysicsEntity::class.java, EntityDataSerializers.STRING) + + private fun getMapper(): ObjectMapper { + return VSJacksonUtil.defaultMapper + } + + fun createBasicSphereData( + shipId: ShipId, transform: ShipTransform, radius: Double = 0.5, mass: Double = 10000.0 + ): PhysicsEntityData { + val inertia = 0.4 * mass * radius * radius + val inertiaData: ShipInertiaData = ShipInertiaDataImpl(Vector3d(), mass, Matrix3d().scale(inertia)) + val collisionShapeData = VSSphereCollisionShapeData(radius) + return PhysicsEntityData( + shipId = shipId, + transform = transform, + inertiaData = inertiaData, + linearVelocity = Vector3d(), + angularVelocity = Vector3d(), + collisionShapeData = collisionShapeData, + isStatic = false + ) + } + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/AbstractShipyardEntityHandler.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/AbstractShipyardEntityHandler.kt index e47476889..f3d585039 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/AbstractShipyardEntityHandler.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/AbstractShipyardEntityHandler.kt @@ -4,10 +4,10 @@ import com.mojang.blaze3d.vertex.PoseStack import net.minecraft.client.renderer.MultiBufferSource import net.minecraft.client.renderer.entity.EntityRenderer import net.minecraft.world.entity.Entity +import org.joml.Quaternionf import org.joml.Vector3d import org.valkyrienskies.core.api.ships.ClientShip import org.valkyrienskies.core.api.ships.Ship -import org.valkyrienskies.mod.common.util.toFloat import org.valkyrienskies.mod.common.util.toJOML import org.valkyrienskies.mod.common.util.toMinecraft @@ -36,7 +36,7 @@ abstract class AbstractShipyardEntityHandler : VSEntityHandler { val scale = transform.shipToWorldScaling matrixStack.translate(transformed.x + camX, transformed.y + camY, transformed.z + camZ) - matrixStack.mulPose(transform.shipToWorldRotation.toFloat()) + matrixStack.mulPose(Quaternionf(transform.shipToWorldRotation)) matrixStack.scale(scale.x().toFloat(), scale.y().toFloat(), scale.z().toFloat()) matrixStack.translate(offset.x, offset.y, offset.z) } @@ -54,6 +54,6 @@ abstract class AbstractShipyardEntityHandler : VSEntityHandler { ) { // TODO: somewhere else position is already applied in the matrix stack // EW: i think it was in entity dragging logic - matrixStack.mulPose(ship.renderTransform.shipToWorldRotation.toFloat()) + matrixStack.mulPose(Quaternionf(ship.renderTransform.shipToWorldRotation)) } } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/VSEntityManager.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/VSEntityManager.kt index c8dbdef39..900e9c645 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/VSEntityManager.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/VSEntityManager.kt @@ -1,6 +1,7 @@ package org.valkyrienskies.mod.common.entity.handling import com.google.common.cache.CacheBuilder +import net.minecraft.core.Registry import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.Entity diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/WorldEntityHandler.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/WorldEntityHandler.kt index bdd29d4bb..ca1f9fa77 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/WorldEntityHandler.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/handling/WorldEntityHandler.kt @@ -8,9 +8,9 @@ import net.minecraft.world.entity.projectile.AbstractHurtingProjectile import org.joml.Vector3d import org.valkyrienskies.core.api.ships.ClientShip import org.valkyrienskies.core.api.ships.Ship -import org.valkyrienskies.core.impl.util.component1 -import org.valkyrienskies.core.impl.util.component2 -import org.valkyrienskies.core.impl.util.component3 +import org.valkyrienskies.core.util.component1 +import org.valkyrienskies.core.util.component2 +import org.valkyrienskies.core.util.component3 import org.valkyrienskies.mod.common.toWorldCoordinates import org.valkyrienskies.mod.common.util.toJOML import org.valkyrienskies.mod.common.util.toMinecraft diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/item/PhysicsEntityCreatorItem.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/PhysicsEntityCreatorItem.kt new file mode 100644 index 000000000..d6f02bcc4 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/PhysicsEntityCreatorItem.kt @@ -0,0 +1,86 @@ +package org.valkyrienskies.mod.common.item + +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.InteractionResult +import net.minecraft.world.item.Item +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.context.UseOnContext +import org.joml.Quaterniond +import org.joml.Vector3d +import org.joml.Vector3dc +import org.valkyrienskies.core.apigame.constraints.VSAttachmentConstraint +import org.valkyrienskies.core.apigame.constraints.VSPosDampingConstraint +import org.valkyrienskies.core.apigame.constraints.VSRotDampingAxes +import org.valkyrienskies.core.apigame.constraints.VSRotDampingConstraint +import org.valkyrienskies.core.impl.game.ships.ShipTransformImpl.Companion +import org.valkyrienskies.mod.common.ValkyrienSkiesMod +import org.valkyrienskies.mod.common.dimensionId +import org.valkyrienskies.mod.common.entity.VSPhysicsEntity +import org.valkyrienskies.mod.common.getShipManagingPos +import org.valkyrienskies.mod.common.shipObjectWorld +import org.valkyrienskies.mod.common.util.toJOML +import org.valkyrienskies.mod.common.util.toJOMLD + +class PhysicsEntityCreatorItem( + properties: Properties +) : Item(properties) { + override fun isFoil(stack: ItemStack): Boolean { + return true + } + + override fun useOn(ctx: UseOnContext): InteractionResult { + val level = ctx.level as? ServerLevel ?: return super.useOn(ctx) + + if (!level.isClientSide) { + val entity = ValkyrienSkiesMod.PHYSICS_ENTITY_TYPE.create(level)!! + val shipId = level.shipObjectWorld.allocateShipId(level.dimensionId) + val sphereRadius = 0.5 + val offsetInLocal: Vector3dc = ctx.clickedFace.normal.toJOMLD().mul(sphereRadius) + + val shipOn = ctx.level.getShipManagingPos(ctx.clickedPos) + val offsetInGlobal = if (shipOn != null) { + shipOn.transform.shipToWorldRotation.transform(offsetInLocal, Vector3d()) + } else { + offsetInLocal + } + + val entityPos: Vector3dc = if (shipOn != null) { + shipOn.transform.shipToWorld.transformPosition(ctx.clickLocation.toJOML()).add(offsetInGlobal) + } else { + ctx.clickLocation.toJOML().add(offsetInGlobal) + } + + val transform = Companion.create(entityPos, Vector3d()) + val physicsEntityData = VSPhysicsEntity.createBasicSphereData(shipId, transform, sphereRadius) + entity.setPhysicsEntityData(physicsEntityData) + entity.setPos(entityPos.x(), entityPos.y(), entityPos.z()) + level.addFreshEntity(entity) + + // Example of adding a constraint to a physics entity + if (shipOn != null) { + val attachCompliance = 1e-8 + val attachMaxForce = 1e10 + // Attach the click position of the ship to the surface of the physics entity + val attachConstraint = VSAttachmentConstraint( + shipOn.id, physicsEntityData.shipId, attachCompliance, ctx.clickLocation.toJOML(), offsetInGlobal.mul(-1.0, Vector3d()), + attachMaxForce, 0.0 + ) + val posDampingConstraint = VSPosDampingConstraint( + shipOn.id, physicsEntityData.shipId, attachCompliance, ctx.clickLocation.toJOML(), offsetInGlobal.mul(-1.0, Vector3d()), + attachMaxForce, 0.1 + ) + val rotDampingConstraint = VSRotDampingConstraint( + shipOn.id, physicsEntityData.shipId, attachCompliance, shipOn.transform.shipToWorldRotation.invert( + Quaterniond() + ), + Quaterniond(), 1e10, 0.1, VSRotDampingAxes.ALL_AXES + ) + level.shipObjectWorld.createNewConstraint(attachConstraint) + level.shipObjectWorld.createNewConstraint(posDampingConstraint) + level.shipObjectWorld.createNewConstraint(rotDampingConstraint) + } + } + + return super.useOn(ctx) + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ShipAssemblerItem.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ShipAssemblerItem.kt index 719402242..06693a335 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ShipAssemblerItem.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ShipAssemblerItem.kt @@ -1,12 +1,13 @@ package org.valkyrienskies.mod.common.item +import net.minecraft.Util import net.minecraft.network.chat.Component import net.minecraft.server.level.ServerLevel import net.minecraft.world.InteractionResult import net.minecraft.world.item.Item import net.minecraft.world.item.context.UseOnContext import net.minecraft.world.level.block.state.BlockState -import org.valkyrienskies.core.impl.datastructures.DenseBlockPosSet +import org.valkyrienskies.core.util.datastructures.DenseBlockPosSet import org.valkyrienskies.mod.common.assembly.createNewShipWithBlocks import org.valkyrienskies.mod.common.isChunkInShipyard diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ShipCreatorItem.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ShipCreatorItem.kt index 89d89be87..95e0e8afe 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ShipCreatorItem.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/item/ShipCreatorItem.kt @@ -1,5 +1,6 @@ package org.valkyrienskies.mod.common.item +import net.minecraft.Util import net.minecraft.network.chat.Component import net.minecraft.server.level.ServerLevel import net.minecraft.world.InteractionResult @@ -24,6 +25,7 @@ import java.util.function.DoubleSupplier class ShipCreatorItem( properties: Properties, private val scale: DoubleSupplier, private val minScaling: DoubleSupplier ) : Item(properties) { + override fun isFoil(stack: ItemStack): Boolean { return true } @@ -58,7 +60,7 @@ class ShipCreatorItem( val newShipPosInShipyard = blockPos.toJOMLD().add(0.5, 0.5, 0.5) val newShipRotation = parentShip.transform.shipToWorldRotation var newShipScaling = parentShip.transform.shipToWorldScaling.mul(scale, Vector3d()) - if (newShipScaling.x() < scale) { + if (newShipScaling.x() < minScaling) { // Do not allow scaling to go below minScaling newShipScaling = Vector3d(minScaling, minScaling, minScaling) } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityShipCollisionUtils.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityShipCollisionUtils.kt index 235dc6870..80997f52f 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityShipCollisionUtils.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityShipCollisionUtils.kt @@ -12,16 +12,19 @@ import net.minecraft.world.phys.shapes.VoxelShape import org.joml.primitives.AABBd import org.joml.primitives.AABBdc import org.valkyrienskies.core.api.ships.Ship -import org.valkyrienskies.core.impl.collision.ConvexPolygonc -import org.valkyrienskies.core.impl.collision.EntityPolygonCollider -import org.valkyrienskies.core.impl.collision.EntityPolygonCollider.createPolygonFromAABB -import org.valkyrienskies.core.impl.util.extend +import org.valkyrienskies.core.apigame.collision.ConvexPolygonc +import org.valkyrienskies.core.impl.collision.k.createPolygonFromAABB +import org.valkyrienskies.core.util.extend import org.valkyrienskies.mod.common.getShipsIntersecting import org.valkyrienskies.mod.common.shipObjectWorld +import org.valkyrienskies.mod.common.vsCore +import org.valkyrienskies.mod.util.BugFixUtil import kotlin.math.max object EntityShipCollisionUtils { + private val collider = vsCore.entityPolygonCollider + @JvmStatic fun isCollidingWithUnloadedShips(entity: Entity): Boolean { val level = entity.level() @@ -86,7 +89,7 @@ object EntityShipCollisionUtils { return movement } - val (newMovement, shipCollidingWith) = EntityPolygonCollider.adjustEntityMovementForPolygonCollisions( + val (newMovement, shipCollidingWith) = collider.adjustEntityMovementForPolygonCollisions( movement.toJOML(), entityBoundingBox.toJOML(), stepHeight, collidingShipPolygons ) if (entity != null) { @@ -109,11 +112,15 @@ object EntityShipCollisionUtils { val entityBoundingBoxExtended = entityBoundingBox.toJOML().extend(movement.toJOML()) for (shipObject in world.shipObjectWorld.loadedShips.getIntersecting(entityBoundingBoxExtended)) { val shipTransform = shipObject.transform - val entityPolyInShipCoordinates: ConvexPolygonc = createPolygonFromAABB( + val entityPolyInShipCoordinates: ConvexPolygonc = collider.createPolygonFromAABB( entityBoxWithMovement.toJOML(), shipTransform.worldToShip ) val entityBoundingBoxInShipCoordinates: AABBdc = entityPolyInShipCoordinates.getEnclosingAABB(AABBd()) + if (BugFixUtil.isCollisionBoxToBig(entityBoundingBoxInShipCoordinates.toMinecraft())) { + // Box too large, skip it + continue + } val shipBlockCollisionStream = world.getBlockCollisions(entity, entityBoundingBoxInShipCoordinates.toMinecraft()) shipBlockCollisionStream.forEach { voxelShape: VoxelShape -> diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/GameTickForceApplier.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/GameTickForceApplier.kt index e2a623aa4..bef91b2b6 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/GameTickForceApplier.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/GameTickForceApplier.kt @@ -2,8 +2,8 @@ package org.valkyrienskies.mod.common.util import org.joml.Vector3dc import org.valkyrienskies.core.api.ships.PhysShip -import org.valkyrienskies.core.impl.api.ShipForcesInducer -import org.valkyrienskies.core.impl.util.pollUntilEmpty +import org.valkyrienskies.core.api.ships.ShipForcesInducer +import org.valkyrienskies.core.util.pollUntilEmpty import java.util.concurrent.ConcurrentLinkedQueue class GameTickForceApplier : ShipForcesInducer { diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/MinecraftPlayer.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/MinecraftPlayer.kt index b82f29afd..75ec785d3 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/MinecraftPlayer.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/MinecraftPlayer.kt @@ -2,9 +2,14 @@ package org.valkyrienskies.mod.common.util import net.minecraft.world.entity.player.Player import org.joml.Vector3d +import org.joml.Vector3dc +import org.valkyrienskies.core.api.ships.properties.ShipId import org.valkyrienskies.core.apigame.world.IPlayer +import org.valkyrienskies.core.apigame.world.PlayerState import org.valkyrienskies.core.apigame.world.properties.DimensionId import org.valkyrienskies.mod.common.dimensionId +import org.valkyrienskies.mod.common.getPassengerPos +import org.valkyrienskies.mod.common.getShipObjectEntityMountedTo import org.valkyrienskies.mod.common.vsCore import java.lang.ref.WeakReference import java.util.UUID @@ -34,6 +39,22 @@ class MinecraftPlayer(playerObject: Player) : IPlayer { return dest.set(player.x, player.y, player.z) } + override fun getPlayerState(): PlayerState { + var mountedShip: ShipId? = null + var mountedPos: Vector3dc? = null + player.level().getShipObjectEntityMountedTo(player)?.let { + mountedShip = it.id + mountedPos = player.vehicle!!.getPassengerPos(player.myRidingOffset, 0.0f) + } + return PlayerState( + Vector3d(player.x, player.y, player.z), + Vector3d(Vector3d(player.x - player.xo, player.y - player.yo, player.z - player.zo)), + dimension, + mountedShip, + mountedPos, + ) + } + override fun hashCode(): Int { return uuid.hashCode() } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/ShipSettings.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/ShipSettings.kt index c5eb9a222..be9f2f8c7 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/ShipSettings.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/ShipSettings.kt @@ -12,7 +12,12 @@ data class ShipSettings( * Should the ship chunks try to generate? If true it will generate chunks in the shipyard. * You normally don't want this EVER */ - var shouldGenerateChunks: Boolean = false + var shouldGenerateChunks: Boolean = false, + + /** + * If true this ship will change dimensions when it touches a portal + */ + var changeDimensionOnTouchPortals: Boolean = true ) val ServerShip.settings: ShipSettings diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/VSServerLevel.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/VSServerLevel.kt new file mode 100644 index 000000000..d80293ea5 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/VSServerLevel.kt @@ -0,0 +1,13 @@ +package org.valkyrienskies.mod.common.util + +// Used on Level to get a Level to remove a chunk from its tracking +interface VSServerLevel { + fun removeChunk(chunkX: Int, chunkZ: Int) +} + +// Used on LevelChunk to delete all blocks and block entities in a LevelChunk +interface VSLevelChunk { + fun clearChunk() + + fun copyChunkFromOtherDimension(srcChunk: VSLevelChunk) +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/world/ChunkManagement.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/world/ChunkManagement.kt index cc464c42d..281d80b20 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/world/ChunkManagement.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/world/ChunkManagement.kt @@ -12,7 +12,7 @@ import org.valkyrienskies.mod.common.getLevelFromDimensionId import org.valkyrienskies.mod.common.isTickingChunk import org.valkyrienskies.mod.common.mcPlayer import org.valkyrienskies.mod.common.util.MinecraftPlayer -import org.valkyrienskies.mod.mixin.accessors.server.world.ChunkMapAccessor +import org.valkyrienskies.mod.mixin.accessors.server.level.ChunkMapAccessor import org.valkyrienskies.mod.util.logger object ChunkManagement { diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/world/DummyShipWorldClient.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/world/DummyShipWorldClient.kt deleted file mode 100644 index 2e096d22d..000000000 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/world/DummyShipWorldClient.kt +++ /dev/null @@ -1,53 +0,0 @@ -package org.valkyrienskies.mod.common.world - -import org.joml.primitives.AABBdc -import org.valkyrienskies.core.api.ships.ClientShip -import org.valkyrienskies.core.api.ships.QueryableShipData -import org.valkyrienskies.core.apigame.world.ClientShipWorldCore -import org.valkyrienskies.core.apigame.world.chunks.BlockType -import org.valkyrienskies.core.apigame.world.properties.DimensionId -import org.valkyrienskies.core.impl.game.ships.QueryableShipDataImpl -import java.net.SocketAddress - -object DummyShipWorldClient : ClientShipWorldCore { - override fun tickNetworking(server: SocketAddress) { - throw UnsupportedOperationException() - } - - override fun postTick() { - throw UnsupportedOperationException() - } - - override fun updateRenderTransforms(partialTicks: Double) { - throw UnsupportedOperationException() - } - - override fun destroyWorld() { - throw UnsupportedOperationException() - } - - override val isSyncedWithServer: Boolean - get() = throw UnsupportedOperationException() - - override fun onSetBlock( - posX: Int, posY: Int, posZ: Int, dimensionId: DimensionId, oldBlockType: BlockType, newBlockType: BlockType, - oldBlockMass: Double, newBlockMass: Double - ) { - } - - override val allShips: QueryableShipData get() = loadedShips - override val loadedShips: QueryableShipData = QueryableShipDataImpl() - - override fun isChunkInShipyard(chunkX: Int, chunkZ: Int, dimensionId: DimensionId): Boolean { - return false - } - - override fun isBlockInShipyard(blockX: Int, blockY: Int, blockZ: Int, dimensionId: DimensionId): Boolean { - return false - } - - @Deprecated("redundant", replaceWith = ReplaceWith("loadedShips.getIntersecting(aabb)")) - override fun getShipObjectsIntersecting(aabb: AABBdc): List { - return emptyList() - } -} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/world/DummyShipWorldServer.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/world/DummyShipWorldServer.kt deleted file mode 100644 index d6dfbaf9f..000000000 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/world/DummyShipWorldServer.kt +++ /dev/null @@ -1,107 +0,0 @@ -package org.valkyrienskies.mod.common.world - -import org.joml.Vector3ic -import org.joml.primitives.AABBdc -import org.valkyrienskies.core.api.ships.LoadedServerShip -import org.valkyrienskies.core.api.ships.QueryableShipData -import org.valkyrienskies.core.api.ships.ServerShip -import org.valkyrienskies.core.api.ships.properties.ShipId -import org.valkyrienskies.core.api.world.LevelYRange -import org.valkyrienskies.core.apigame.ShipTeleportData -import org.valkyrienskies.core.apigame.constraints.VSConstraint -import org.valkyrienskies.core.apigame.constraints.VSConstraintId -import org.valkyrienskies.core.apigame.world.IPlayer -import org.valkyrienskies.core.apigame.world.ServerShipWorldCore -import org.valkyrienskies.core.apigame.world.chunks.BlockType -import org.valkyrienskies.core.apigame.world.chunks.ChunkUnwatchTask -import org.valkyrienskies.core.apigame.world.chunks.ChunkWatchTask -import org.valkyrienskies.core.apigame.world.chunks.ChunkWatchTasks -import org.valkyrienskies.core.apigame.world.chunks.TerrainUpdate -import org.valkyrienskies.core.apigame.world.properties.DimensionId -import org.valkyrienskies.core.impl.game.ships.QueryableShipDataImpl - -object DummyShipWorldServer : ServerShipWorldCore { - override var players: Set = emptySet() - - override fun addTerrainUpdates(dimensionId: DimensionId, terrainUpdates: List) { - TODO("Not yet implemented") - } - - override fun getIPlayersWatchingShipChunk(chunkX: Int, chunkZ: Int, dimensionId: DimensionId): Iterator { - TODO("Not yet implemented") - } - - override fun getChunkWatchTasks(): ChunkWatchTasks { - TODO("Not yet implemented") - } - - override fun setExecutedChunkWatchTasks( - watchTasks: Iterable, unwatchTasks: Iterable - ) { - TODO("Not yet implemented") - } - - override fun createNewShipAtBlock( - blockPosInWorldCoordinates: Vector3ic, createShipObjectImmediately: Boolean, scaling: Double, - dimensionId: DimensionId - ): ServerShip { - TODO("Not yet implemented") - } - - override fun createNewConstraint(vsConstraint: VSConstraint): VSConstraintId? { - TODO("Not yet implemented") - } - - override fun updateConstraint(constraintId: VSConstraintId, updatedVSConstraint: VSConstraint): Boolean { - TODO("Not yet implemented") - } - - override fun removeConstraint(constraintId: VSConstraintId): Boolean { - TODO("Not yet implemented") - } - - override fun addDimension(dimensionId: DimensionId, yRange: LevelYRange) { - TODO("Not yet implemented") - } - - override fun removeDimension(dimensionId: DimensionId) { - TODO("Not yet implemented") - } - - override fun onDisconnect(player: IPlayer) { - } - - override fun deleteShip(ship: ServerShip) { - TODO("Not yet implemented") - } - - override fun teleportShip(ship: ServerShip, teleportData: ShipTeleportData) { - TODO("Not yet implemented") - } - - override val dimensionToGroundBodyIdImmutable: Map - get() = TODO("Not yet implemented") - - override fun onSetBlock( - posX: Int, posY: Int, posZ: Int, dimensionId: DimensionId, oldBlockType: BlockType, newBlockType: BlockType, - oldBlockMass: Double, newBlockMass: Double - ) { - } - - override val allShips: QueryableShipData - get() = loadedShips - override val loadedShips: QueryableShipData = QueryableShipDataImpl() - - override fun isChunkInShipyard(chunkX: Int, chunkZ: Int, dimensionId: DimensionId): Boolean { - return false - } - - override fun isBlockInShipyard(blockX: Int, blockY: Int, blockZ: Int, dimensionId: DimensionId): Boolean { - return false - } - - @Deprecated("redundant", replaceWith = ReplaceWith("loadedShips.getIntersecting(aabb)")) - override fun getShipObjectsIntersecting(aabb: AABBdc): List { - return emptyList() - } -} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/world/RaycastUtils.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/world/RaycastUtils.kt index fe8ae339f..83a1bdd3a 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/world/RaycastUtils.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/world/RaycastUtils.kt @@ -222,17 +222,14 @@ fun Level.raytraceEntities( val start = Vector3d() val end = Vector3d() - if (shipObjectWorld == null) logger.error("rayTraceEntities shipObjectWorld was null! this should never happen!") - shipObjectWorld?.loadedShips?.getIntersecting(origBoundingBoxM.toJOML())?.forEach { + shipObjectWorld.loadedShips.getIntersecting(origBoundingBoxM.toJOML()).forEach { it.worldToShip.transformPosition(origStartVec, start) it.worldToShip.transformPosition(origEndVec, end) - // Shouldn't we have a double for scale in transform? - val scale = it.shipTransform.worldToShipMatrix.getScale(Vector3d()) - assert(scale.x == scale.y && scale.y == scale.z) + val scale = 1.0 / it.transform.shipToWorldScaling.x() - checkEntities(entities, start.toMinecraft(), end.toMinecraft(), scale.x) + checkEntities(entities, start.toMinecraft(), end.toMinecraft(), scale) } return if (resultEntity == null) { diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/compat/CreateCompat.kt b/common/src/main/kotlin/org/valkyrienskies/mod/compat/CreateCompat.kt index 150308810..bb880bf56 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/compat/CreateCompat.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/compat/CreateCompat.kt @@ -5,7 +5,7 @@ import net.minecraft.world.entity.Entity object CreateCompat { private val contraptionClass = runCatching { - Class.forName("com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity") + Class.forName("com.simibubi.create.content.contraptions.AbstractContraptionEntity") }.getOrNull() @JvmStatic diff --git a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/CreateConversions.kt b/common/src/main/kotlin/org/valkyrienskies/mod/compat/CreateConversions.kt similarity index 72% rename from forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/CreateConversions.kt rename to common/src/main/kotlin/org/valkyrienskies/mod/compat/CreateConversions.kt index 1bd63dbc1..dff475f40 100644 --- a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/CreateConversions.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/compat/CreateConversions.kt @@ -1,8 +1,7 @@ -package org.valkyrienskies.mod.forge.common +package org.valkyrienskies.mod.compat -/* import org.joml.Matrix3d -import org.valkyrienskies.mod.forge.mixin.compat.create.Matrix3dAccessor +import org.valkyrienskies.mod.mixin.mod_compat.create.accessors.Matrix3dAccessor fun com.simibubi.create.foundation.collision.Matrix3d.toJOML(): Matrix3d { val accessor = this as Matrix3dAccessor @@ -12,4 +11,4 @@ fun com.simibubi.create.foundation.collision.Matrix3d.toJOML(): Matrix3d { accessor.m20, accessor.m21, accessor.m22 ) } -*/ + diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/compat/clothconfig/VSClothConfig.kt b/common/src/main/kotlin/org/valkyrienskies/mod/compat/clothconfig/VSClothConfig.kt index 68a4951d7..8081551a7 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/compat/clothconfig/VSClothConfig.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/compat/clothconfig/VSClothConfig.kt @@ -14,10 +14,10 @@ import net.minecraft.ChatFormatting.GRAY import net.minecraft.ChatFormatting.ITALIC import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component +import org.apache.commons.lang3.StringUtils import org.valkyrienskies.core.impl.config.SidedVSConfigClass import org.valkyrienskies.core.impl.config.VSConfigClass import org.valkyrienskies.core.impl.util.serialization.VSJacksonUtil -import org.valkyrienskies.core.impl.util.splitCamelCaseAndCapitalize import java.util.Optional object VSClothConfig { @@ -68,6 +68,10 @@ object VSClothConfig { } } + private fun String.splitCamelCaseAndCapitalize(): String { + return StringUtils.capitalize(StringUtils.join(StringUtils.splitByCharacterTypeCamelCase(this), " ")) + } + private fun getEntriesForProperty( key: String, currentValue: JsonNode, @@ -247,9 +251,7 @@ object VSClothConfig { } if (description != null) { - entries.add( - entryBuilder().startTextDescription(Component.literal(description).withStyle(GRAY, ITALIC)).build() - ) + entries.add(entryBuilder().startTextDescription(Component.literal(description).withStyle(GRAY, ITALIC)).build()) } return entries diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/util/BugFixUtil.kt b/common/src/main/kotlin/org/valkyrienskies/mod/util/BugFixUtil.kt new file mode 100644 index 000000000..58e39edc2 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/util/BugFixUtil.kt @@ -0,0 +1,9 @@ +package org.valkyrienskies.mod.util + +import net.minecraft.world.phys.AABB + +object BugFixUtil { + fun isCollisionBoxToBig(aabb: AABB): Boolean { + return aabb.xsize > 1000 || aabb.ysize > 1000 || aabb.zsize > 1000 + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/util/VectorConversionsMC.kt b/common/src/main/kotlin/org/valkyrienskies/mod/util/VectorConversionsMC.kt index 7a7aeed7b..dbb47cbd0 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/util/VectorConversionsMC.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/util/VectorConversionsMC.kt @@ -1,5 +1,4 @@ package org.valkyrienskies.mod.common.util - import com.mojang.blaze3d.vertex.PoseStack import net.minecraft.core.BlockPos import net.minecraft.core.Direction diff --git a/common/src/main/resources/assets/valkyrienskies/blockstates/test_sphere.json b/common/src/main/resources/assets/valkyrienskies/blockstates/test_sphere.json new file mode 100644 index 000000000..41203f87c --- /dev/null +++ b/common/src/main/resources/assets/valkyrienskies/blockstates/test_sphere.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "valkyrienskies:block/test_sphere" + } + } +} diff --git a/common/src/main/resources/assets/valkyrienskies/lang/en_us.json b/common/src/main/resources/assets/valkyrienskies/lang/en_us.json index b19749a0d..ddd33df22 100644 --- a/common/src/main/resources/assets/valkyrienskies/lang/en_us.json +++ b/common/src/main/resources/assets/valkyrienskies/lang/en_us.json @@ -8,7 +8,7 @@ "block.valkyrienskies.test_wing": "Debug Wing", "item.valkyrienskies.ship_creator": "Ship Creator", "item.valkyrienskies.ship_creator_smaller": "Mini Ship Creator", - "itemGroup.valkyrienSkies": "Valkyrien Skies", + "item.valkyrienskies.physics_entity_creator": "Physics Entity Creator", "argument.valkyrienskies.ship.no_found": "Ship not found", "argument.valkyrienskies.ship.multiple_found": "Multiple ships found", "command.valkyrienskies.delete.success": "Deleted %d ships!", @@ -19,5 +19,6 @@ "command.valkyrienskies.get_ship.success": "Found ship with slug %s", "command.valkyrienskies.get_ship.fail": "No ship found", "command.valkyrienskies.get_ship.only_usable_by_entities": "/vs get-ship can only be run by entities!", - "tooltip.valkyrienskies.mass": "Mass" + "tooltip.valkyrienskies.mass": "Mass", + "command.valkyrienskies.scale.success": "Scaled %d ships!" } diff --git a/common/src/main/resources/assets/valkyrienskies/models/block/test_sphere.json b/common/src/main/resources/assets/valkyrienskies/models/block/test_sphere.json new file mode 100644 index 000000000..71ac0e389 --- /dev/null +++ b/common/src/main/resources/assets/valkyrienskies/models/block/test_sphere.json @@ -0,0 +1,2157 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "0": "valkyrienskies:test_sphere", + "particle": "valkyrienskies:test_sphere" + }, + "elements": [ + { + "from": [3, 3, 3], + "to": [13, 13, 13], + "faces": { + "north": {"uv": [0, 0, 10, 10], "texture": "#0"}, + "east": {"uv": [0, 0, 10, 10], "texture": "#0"}, + "south": {"uv": [0, 0, 10, 10], "texture": "#0"}, + "west": {"uv": [0, 0, 10, 10], "texture": "#0"}, + "up": {"uv": [0, 0, 10, 10], "texture": "#0"}, + "down": {"uv": [0, 0, 10, 10], "texture": "#0"} + } + }, + { + "from": [9, 6, 15], + "to": [10, 10, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 1, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [7, 5, 15], + "to": [9, 11, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 6, 2], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 6, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 6, 2], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 6, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [7, 3, 14], + "to": [9, 13, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 10, 2], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 10, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 10, 2], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 10, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [6, 3, 13], + "to": [10, 13, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 10, 4], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 10, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 10, 4], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 10, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 6, 13], + "to": [14, 10, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 4, 4], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 4, 4], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 4, 13], + "to": [13, 6, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 3, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [3, 4, 13], + "to": [6, 6, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 3, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [4, 3, 13], + "to": [6, 4, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 1, 2], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 1, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 1, 2], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 3, 13], + "to": [12, 4, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 1, 2], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 1, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 1, 2], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 12, 13], + "to": [12, 13, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 0, 2, 2], "rotation": 270, "texture": "#0"}, + "east": {"uv": [1, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1, 0, 2, 2], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 0, 4, 1], "texture": "#0"}, + "down": {"uv": [2, 0, 4, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [4, 12, 13], + "to": [6, 13, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 0, 2, 2], "rotation": 270, "texture": "#0"}, + "east": {"uv": [1, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1, 0, 2, 2], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 0, 4, 1], "texture": "#0"}, + "down": {"uv": [2, 0, 4, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [3, 10, 13], + "to": [6, 12, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 6, 1], "texture": "#0"}, + "down": {"uv": [3, 0, 6, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 10, 13], + "to": [13, 12, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 6, 1], "texture": "#0"}, + "down": {"uv": [3, 0, 6, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [2, 6, 13], + "to": [6, 10, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 4, 4], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 4, 4], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [3, 7, 14], + "to": [7, 9, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 4], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 4], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [4, 5, 14], + "to": [7, 7, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 3, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [4, 9, 14], + "to": [7, 11, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 6, 1], "texture": "#0"}, + "down": {"uv": [3, 0, 6, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 5, 14], + "to": [12, 7, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 3, 2, 6], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 3, 2, 6], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 6, 1], "texture": "#0"}, + "down": {"uv": [3, 0, 6, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 4, 14], + "to": [11, 5, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 0, 3, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "down": {"uv": [3, 0, 5, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 11, 14], + "to": [11, 12, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 0, 3, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "down": {"uv": [3, 0, 5, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [5, 11, 14], + "to": [7, 12, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 0, 3, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "down": {"uv": [3, 0, 5, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [5, 4, 14], + "to": [7, 5, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 0, 3, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "down": {"uv": [3, 0, 5, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 9, 14], + "to": [12, 11, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 3, 4, 6], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [2, 3, 4, 6], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 3, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 7, 14], + "to": [13, 9, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 4], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 4], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [5, 7, 15], + "to": [6, 9, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 1, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 7, 15], + "to": [11, 9, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 1, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [6, 6, 15], + "to": [7, 10, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 1, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [6, 3, 2], + "to": [10, 13, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 4, 10, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 10, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 4, 10, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 10, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 4, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [7, 3, 1], + "to": [9, 13, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 2, 10, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 10, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 2, 10, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 10, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 2, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 3, 2], + "to": [12, 4, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 2, 1, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 1, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 2, 1, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 2, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 4, 1], + "to": [11, 5, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 1, 3, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "down": {"uv": [3, 1, 5, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 4, 2], + "to": [13, 6, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 3, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 5, 1], + "to": [12, 7, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 6, 2, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 6, 2, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 6, 0], "texture": "#0"}, + "down": {"uv": [3, 1, 6, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 6, 2], + "to": [14, 10, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 4, 4, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 4, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 4, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 7, 1], + "to": [13, 9, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 4, 2, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 4, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 4, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 9, 1], + "to": [12, 11, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 6, 4, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [2, 6, 4, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 3, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 10, 2], + "to": [13, 12, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 6, 0], "texture": "#0"}, + "down": {"uv": [3, 1, 6, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 12, 2], + "to": [12, 13, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 2, 2, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [1, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1, 2, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 1, 4, 0], "texture": "#0"}, + "down": {"uv": [2, 1, 4, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 11, 1], + "to": [11, 12, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 1, 3, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "down": {"uv": [3, 1, 5, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [4, 12, 2], + "to": [6, 13, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 2, 2, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [1, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1, 2, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 1, 4, 0], "texture": "#0"}, + "down": {"uv": [2, 1, 4, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [5, 11, 1], + "to": [7, 12, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 1, 3, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "down": {"uv": [3, 1, 5, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [4, 9, 1], + "to": [7, 11, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 6, 0], "texture": "#0"}, + "down": {"uv": [3, 1, 6, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [3, 10, 2], + "to": [6, 12, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 6, 0], "texture": "#0"}, + "down": {"uv": [3, 1, 6, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [2, 6, 2], + "to": [6, 10, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 4, 4, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 4, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 4, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [3, 7, 1], + "to": [7, 9, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 4, 2, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 4, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 4, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [3, 4, 2], + "to": [6, 6, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 3, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [4, 5, 1], + "to": [7, 7, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 3, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [4, 3, 2], + "to": [6, 4, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 2, 1, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 1, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 2, 1, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 2, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [5, 4, 1], + "to": [7, 5, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2, 1, 3, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "down": {"uv": [3, 1, 5, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [7, 5, 0], + "to": [9, 11, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 2, 6, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 6, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 2, 6, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 6, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 2, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [9, 6, 0], + "to": [10, 10, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 1, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [10, 7, 0], + "to": [11, 9, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 1, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [5, 7, 0], + "to": [6, 9, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 1, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [6, 6, 0], + "to": [7, 10, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "south": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 1, 0], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [15, 6, 6], + "to": [16, 10, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [15, 5, 7], + "to": [16, 11, 9], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 6, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 6, 2], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 6, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 6, 2], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [14, 3, 7], + "to": [15, 13, 9], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 10, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 10, 2], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 10, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 10, 2], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 3, 6], + "to": [14, 13, 10], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 10, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 10, 4], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 10, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 10, 4], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 6, 3], + "to": [14, 10, 5], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 4, 2], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 4, 2], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 4, 3], + "to": [14, 6, 6], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 3, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 4, 10], + "to": [14, 6, 13], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 3, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 3, 10], + "to": [14, 4, 12], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 1, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 1, 2], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 1, 2], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 3, 4], + "to": [14, 4, 6], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 1, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 1, 2], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 1, 2], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 12, 4], + "to": [14, 13, 6], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [1, 0, 2, 2], "rotation": 270, "texture": "#0"}, + "south": {"uv": [1, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 0, 2, 2], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 12, 10], + "to": [14, 13, 12], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [1, 0, 2, 2], "rotation": 270, "texture": "#0"}, + "south": {"uv": [1, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 0, 2, 2], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 10, 10], + "to": [14, 12, 13], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 6, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 0, 6, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 10, 3], + "to": [14, 12, 6], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 6, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 0, 6, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 6, 10], + "to": [14, 10, 13], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 3, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [14, 7, 9], + "to": [15, 9, 13], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 4], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 4], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [14, 5, 9], + "to": [15, 7, 12], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 3, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [14, 9, 9], + "to": [15, 11, 12], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 0, 4, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 6, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 0, 6, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [14, 5, 4], + "to": [15, 7, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 3, 2, 6], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 3, 2, 6], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 6, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 0, 6, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [14, 4, 5], + "to": [15, 5, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 0, 3, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 5, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 0, 5, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [14, 11, 5], + "to": [15, 12, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 0, 3, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 5, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 0, 5, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [14, 11, 9], + "to": [15, 12, 11], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 0, 3, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 5, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 0, 5, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [14, 4, 9], + "to": [15, 5, 11], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 0, 3, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 3, 1, 5], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 0, 5, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 0, 5, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [14, 9, 4], + "to": [15, 11, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [2, 3, 4, 6], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 3, 4, 6], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 3, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 3, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [14, 7, 3], + "to": [15, 9, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 4], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 4], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [15, 7, 10], + "to": [16, 9, 11], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [15, 7, 5], + "to": [16, 9, 6], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 2, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [15, 6, 9], + "to": [16, 10, 10], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 4, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 0, 4, 1], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 0, 1, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [2, 3, 6], + "to": [3, 13, 10], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 10, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 4, 10, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 10, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 4, 10, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [1, 3, 7], + "to": [2, 13, 9], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 10, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 2, 10, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 10, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 2, 10, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [2, 3, 4], + "to": [3, 4, 6], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 1, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 2, 1, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 2, 1, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [1, 4, 5], + "to": [2, 5, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 1, 3, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 5, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 1, 5, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [2, 4, 3], + "to": [3, 6, 6], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 3, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [1, 5, 4], + "to": [2, 7, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 6, 2, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 6, 2, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 6, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 1, 6, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [2, 6, 3], + "to": [3, 10, 5], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 4, 2], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 4, 4, 6], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 4, 2], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 4, 4, 6], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 2, 2], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 2, 2], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [1, 7, 3], + "to": [2, 9, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 4, 2, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 4, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [1, 9, 4], + "to": [2, 11, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [2, 6, 4, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 6, 4, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 3, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [2, 10, 3], + "to": [3, 12, 6], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 6, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 1, 6, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [2, 12, 4], + "to": [3, 13, 6], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [1, 2, 2, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [1, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 2, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [1, 11, 5], + "to": [2, 12, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 1, 3, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 5, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 1, 5, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [2, 12, 10], + "to": [3, 13, 12], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [1, 2, 2, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [1, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [1, 2, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [1, 11, 9], + "to": [2, 12, 11], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 1, 3, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 5, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 1, 5, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [1, 9, 9], + "to": [2, 11, 12], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 6, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 1, 6, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [2, 10, 10], + "to": [3, 12, 13], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2, 3, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 6, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 1, 6, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [2, 6, 10], + "to": [3, 10, 14], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 4, 4, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 4, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [1, 7, 9], + "to": [2, 9, 13], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 4, 2, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 4, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [2, 4, 10], + "to": [3, 6, 13], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 3, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [1, 5, 9], + "to": [2, 7, 12], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 3, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 3, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [2, 3, 10], + "to": [3, 4, 12], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 1, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 2, 1, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 2, 1, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [1, 4, 9], + "to": [2, 5, 11], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [2, 1, 3, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2, 1, 3, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 5, 1, 3], "rotation": 270, "texture": "#0"}, + "up": {"uv": [3, 1, 5, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [3, 1, 5, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [0, 5, 7], + "to": [1, 11, 9], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 6, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 2, 6, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 6, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 2, 6, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [0, 6, 6], + "to": [1, 10, 7], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [0, 7, 5], + "to": [1, 9, 6], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [0, 7, 10], + "to": [1, 9, 11], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [0, 6, 9], + "to": [1, 10, 10], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1, 4, 0], "rotation": 90, "texture": "#0"}, + "east": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 1, 4, 0], "rotation": 270, "texture": "#0"}, + "up": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 1, 1, 0], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [6, 0, 6], + "to": [10, 1, 7], + "faces": { + "north": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 1], "texture": "#0"} + } + }, + { + "from": [5, 0, 7], + "to": [11, 1, 9], + "faces": { + "north": {"uv": [0, 0, 6, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 6, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 6, 2], "texture": "#0"}, + "down": {"uv": [0, 0, 6, 2], "texture": "#0"} + } + }, + { + "from": [3, 1, 7], + "to": [13, 2, 9], + "faces": { + "north": {"uv": [0, 0, 10, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 10, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 10, 2], "texture": "#0"}, + "down": {"uv": [0, 0, 10, 2], "texture": "#0"} + } + }, + { + "from": [2, 2, 6], + "to": [14, 3, 10], + "faces": { + "north": {"uv": [0, 0, 12, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 12, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 12, 4], "texture": "#0"}, + "down": {"uv": [0, 0, 12, 4], "texture": "#0"} + } + }, + { + "from": [6, 2, 2], + "to": [10, 3, 6], + "faces": { + "north": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 4, 4], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 4], "texture": "#0"} + } + }, + { + "from": [4, 2, 3], + "to": [6, 3, 6], + "faces": { + "north": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 2, 3], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 3], "texture": "#0"} + } + }, + { + "from": [4, 2, 10], + "to": [6, 3, 13], + "faces": { + "north": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 2, 3], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 3], "texture": "#0"} + } + }, + { + "from": [3, 2, 10], + "to": [4, 3, 12], + "faces": { + "north": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 1, 2], "texture": "#0"}, + "down": {"uv": [0, 0, 1, 2], "texture": "#0"} + } + }, + { + "from": [3, 2, 4], + "to": [4, 3, 6], + "faces": { + "north": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 1, 2], "texture": "#0"}, + "down": {"uv": [0, 0, 1, 2], "texture": "#0"} + } + }, + { + "from": [12, 2, 4], + "to": [13, 3, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [1, 0, 0, 1], "texture": "#0"}, + "east": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "south": {"uv": [1, 0, 0, 1], "texture": "#0"}, + "west": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "up": {"uv": [1, 0, 0, 2], "texture": "#0"}, + "down": {"uv": [1, 0, 0, 2], "texture": "#0"} + } + }, + { + "from": [12, 2, 10], + "to": [13, 3, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [1, 0, 0, 1], "texture": "#0"}, + "east": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "south": {"uv": [1, 0, 0, 1], "texture": "#0"}, + "west": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "up": {"uv": [1, 0, 0, 2], "texture": "#0"}, + "down": {"uv": [1, 0, 0, 2], "texture": "#0"} + } + }, + { + "from": [10, 2, 10], + "to": [12, 3, 13], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "east": {"uv": [3, 0, 0, 1], "texture": "#0"}, + "south": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "west": {"uv": [3, 0, 0, 1], "texture": "#0"}, + "up": {"uv": [2, 0, 0, 3], "texture": "#0"}, + "down": {"uv": [2, 0, 0, 3], "texture": "#0"} + } + }, + { + "from": [10, 2, 3], + "to": [12, 3, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "east": {"uv": [3, 0, 0, 1], "texture": "#0"}, + "south": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "west": {"uv": [3, 0, 0, 1], "texture": "#0"}, + "up": {"uv": [2, 0, 0, 3], "texture": "#0"}, + "down": {"uv": [2, 0, 0, 3], "texture": "#0"} + } + }, + { + "from": [6, 2, 10], + "to": [10, 3, 14], + "faces": { + "north": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 4, 4], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 4], "texture": "#0"} + } + }, + { + "from": [7, 1, 9], + "to": [9, 2, 13], + "faces": { + "north": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 2, 4], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 4], "texture": "#0"} + } + }, + { + "from": [5, 1, 9], + "to": [7, 2, 12], + "faces": { + "north": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 2, 3], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 3], "texture": "#0"} + } + }, + { + "from": [9, 1, 9], + "to": [11, 2, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 0]}, + "faces": { + "north": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "east": {"uv": [3, 0, 0, 1], "texture": "#0"}, + "south": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "west": {"uv": [3, 0, 0, 1], "texture": "#0"}, + "up": {"uv": [2, 0, 0, 3], "texture": "#0"}, + "down": {"uv": [2, 0, 0, 3], "texture": "#0"} + } + }, + { + "from": [5, 1, 4], + "to": [7, 2, 7], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 16]}, + "faces": { + "north": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "east": {"uv": [3, 0, 0, 1], "texture": "#0"}, + "south": {"uv": [2, 0, 0, 1], "texture": "#0"}, + "west": {"uv": [3, 0, 0, 1], "texture": "#0"}, + "up": {"uv": [0, 3, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 3, 2, 0], "texture": "#0"} + } + }, + { + "from": [4, 1, 5], + "to": [5, 2, 7], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 16]}, + "faces": { + "north": {"uv": [2, 0, 3, 1], "texture": "#0"}, + "east": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "south": {"uv": [2, 0, 3, 1], "texture": "#0"}, + "west": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "up": {"uv": [0, 3, 1, 5], "texture": "#0"}, + "down": {"uv": [0, 3, 1, 5], "texture": "#0"} + } + }, + { + "from": [11, 1, 5], + "to": [12, 2, 7], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 16]}, + "faces": { + "north": {"uv": [2, 0, 3, 1], "texture": "#0"}, + "east": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "south": {"uv": [2, 0, 3, 1], "texture": "#0"}, + "west": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "up": {"uv": [0, 3, 1, 5], "texture": "#0"}, + "down": {"uv": [0, 3, 1, 5], "texture": "#0"} + } + }, + { + "from": [11, 1, 9], + "to": [12, 2, 11], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 16]}, + "faces": { + "north": {"uv": [2, 0, 3, 1], "texture": "#0"}, + "east": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "south": {"uv": [2, 0, 3, 1], "texture": "#0"}, + "west": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "up": {"uv": [0, 3, 1, 5], "texture": "#0"}, + "down": {"uv": [0, 3, 1, 5], "texture": "#0"} + } + }, + { + "from": [4, 1, 9], + "to": [5, 2, 11], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 16]}, + "faces": { + "north": {"uv": [2, 0, 3, 1], "texture": "#0"}, + "east": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "south": {"uv": [2, 0, 3, 1], "texture": "#0"}, + "west": {"uv": [3, 0, 5, 1], "texture": "#0"}, + "up": {"uv": [0, 3, 1, 5], "texture": "#0"}, + "down": {"uv": [0, 3, 1, 5], "texture": "#0"} + } + }, + { + "from": [9, 1, 4], + "to": [11, 2, 7], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 0, 16]}, + "faces": { + "north": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 3, 1], "texture": "#0"}, + "up": {"uv": [2, 3, 0, 0], "texture": "#0"}, + "down": {"uv": [2, 3, 0, 0], "texture": "#0"} + } + }, + { + "from": [7, 1, 3], + "to": [9, 2, 7], + "faces": { + "north": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 2, 4], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 4], "texture": "#0"} + } + }, + { + "from": [7, 0, 10], + "to": [9, 1, 11], + "faces": { + "north": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 1], "texture": "#0"} + } + }, + { + "from": [7, 0, 5], + "to": [9, 1, 6], + "faces": { + "north": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 1], "texture": "#0"} + } + }, + { + "from": [6, 0, 9], + "to": [10, 1, 10], + "faces": { + "north": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 1, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 4, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 1], "texture": "#0"} + } + }, + { + "from": [6, 15, 6], + "to": [10, 16, 7], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "up": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 4, 0], "texture": "#0"} + } + }, + { + "from": [5, 15, 7], + "to": [11, 16, 9], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 6, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 6, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "up": {"uv": [0, 2, 6, 0], "texture": "#0"}, + "down": {"uv": [0, 2, 6, 0], "texture": "#0"} + } + }, + { + "from": [3, 14, 7], + "to": [13, 15, 9], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 10, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 10, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "up": {"uv": [0, 2, 10, 0], "texture": "#0"}, + "down": {"uv": [0, 2, 10, 0], "texture": "#0"} + } + }, + { + "from": [2, 13, 6], + "to": [14, 14, 10], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 12, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 12, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "up": {"uv": [0, 4, 12, 0], "texture": "#0"}, + "down": {"uv": [0, 4, 12, 0], "texture": "#0"} + } + }, + { + "from": [6, 13, 2], + "to": [10, 14, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "up": {"uv": [0, 4, 4, 0], "texture": "#0"}, + "down": {"uv": [0, 4, 4, 0], "texture": "#0"} + } + }, + { + "from": [4, 13, 3], + "to": [6, 14, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "up": {"uv": [0, 3, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 3, 2, 0], "texture": "#0"} + } + }, + { + "from": [4, 13, 10], + "to": [6, 14, 13], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "up": {"uv": [0, 3, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 3, 2, 0], "texture": "#0"} + } + }, + { + "from": [3, 13, 10], + "to": [4, 14, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "up": {"uv": [0, 2, 1, 0], "texture": "#0"}, + "down": {"uv": [0, 2, 1, 0], "texture": "#0"} + } + }, + { + "from": [3, 13, 4], + "to": [4, 14, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "up": {"uv": [0, 2, 1, 0], "texture": "#0"}, + "down": {"uv": [0, 2, 1, 0], "texture": "#0"} + } + }, + { + "from": [12, 13, 4], + "to": [13, 14, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 16, 0]}, + "faces": { + "north": {"uv": [1, 1, 0, 0], "texture": "#0"}, + "east": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "south": {"uv": [1, 1, 0, 0], "texture": "#0"}, + "west": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "up": {"uv": [1, 2, 0, 0], "texture": "#0"}, + "down": {"uv": [1, 2, 0, 0], "texture": "#0"} + } + }, + { + "from": [12, 13, 10], + "to": [13, 14, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 16, 0]}, + "faces": { + "north": {"uv": [1, 1, 0, 0], "texture": "#0"}, + "east": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "south": {"uv": [1, 1, 0, 0], "texture": "#0"}, + "west": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "up": {"uv": [1, 2, 0, 0], "texture": "#0"}, + "down": {"uv": [1, 2, 0, 0], "texture": "#0"} + } + }, + { + "from": [10, 13, 10], + "to": [12, 14, 13], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 16, 0]}, + "faces": { + "north": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "east": {"uv": [3, 1, 0, 0], "texture": "#0"}, + "south": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "west": {"uv": [3, 1, 0, 0], "texture": "#0"}, + "up": {"uv": [2, 3, 0, 0], "texture": "#0"}, + "down": {"uv": [2, 3, 0, 0], "texture": "#0"} + } + }, + { + "from": [10, 13, 3], + "to": [12, 14, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 16, 0]}, + "faces": { + "north": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "east": {"uv": [3, 1, 0, 0], "texture": "#0"}, + "south": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "west": {"uv": [3, 1, 0, 0], "texture": "#0"}, + "up": {"uv": [2, 3, 0, 0], "texture": "#0"}, + "down": {"uv": [2, 3, 0, 0], "texture": "#0"} + } + }, + { + "from": [6, 13, 10], + "to": [10, 14, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "up": {"uv": [0, 4, 4, 0], "texture": "#0"}, + "down": {"uv": [0, 4, 4, 0], "texture": "#0"} + } + }, + { + "from": [7, 14, 9], + "to": [9, 15, 13], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "up": {"uv": [0, 4, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 4, 2, 0], "texture": "#0"} + } + }, + { + "from": [5, 14, 9], + "to": [7, 15, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "up": {"uv": [0, 3, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 3, 2, 0], "texture": "#0"} + } + }, + { + "from": [9, 14, 9], + "to": [11, 15, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 16, 0]}, + "faces": { + "north": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "east": {"uv": [3, 1, 0, 0], "texture": "#0"}, + "south": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "west": {"uv": [3, 1, 0, 0], "texture": "#0"}, + "up": {"uv": [2, 3, 0, 0], "texture": "#0"}, + "down": {"uv": [2, 3, 0, 0], "texture": "#0"} + } + }, + { + "from": [5, 14, 4], + "to": [7, 15, 7], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 16]}, + "faces": { + "north": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "east": {"uv": [3, 1, 0, 0], "texture": "#0"}, + "south": {"uv": [2, 1, 0, 0], "texture": "#0"}, + "west": {"uv": [3, 1, 0, 0], "texture": "#0"}, + "up": {"uv": [0, 0, 2, 3], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 3], "texture": "#0"} + } + }, + { + "from": [4, 14, 5], + "to": [5, 15, 7], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 16]}, + "faces": { + "north": {"uv": [2, 1, 3, 0], "texture": "#0"}, + "east": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "south": {"uv": [2, 1, 3, 0], "texture": "#0"}, + "west": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "up": {"uv": [0, 5, 1, 3], "texture": "#0"}, + "down": {"uv": [0, 5, 1, 3], "texture": "#0"} + } + }, + { + "from": [11, 14, 5], + "to": [12, 15, 7], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 16]}, + "faces": { + "north": {"uv": [2, 1, 3, 0], "texture": "#0"}, + "east": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "south": {"uv": [2, 1, 3, 0], "texture": "#0"}, + "west": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "up": {"uv": [0, 5, 1, 3], "texture": "#0"}, + "down": {"uv": [0, 5, 1, 3], "texture": "#0"} + } + }, + { + "from": [11, 14, 9], + "to": [12, 15, 11], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 16]}, + "faces": { + "north": {"uv": [2, 1, 3, 0], "texture": "#0"}, + "east": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "south": {"uv": [2, 1, 3, 0], "texture": "#0"}, + "west": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "up": {"uv": [0, 5, 1, 3], "texture": "#0"}, + "down": {"uv": [0, 5, 1, 3], "texture": "#0"} + } + }, + { + "from": [4, 14, 9], + "to": [5, 15, 11], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 16]}, + "faces": { + "north": {"uv": [2, 1, 3, 0], "texture": "#0"}, + "east": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "south": {"uv": [2, 1, 3, 0], "texture": "#0"}, + "west": {"uv": [3, 1, 5, 0], "texture": "#0"}, + "up": {"uv": [0, 5, 1, 3], "texture": "#0"}, + "down": {"uv": [0, 5, 1, 3], "texture": "#0"} + } + }, + { + "from": [9, 14, 4], + "to": [11, 15, 7], + "rotation": {"angle": 0, "axis": "y", "origin": [16, 16, 16]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 3, 0], "texture": "#0"}, + "up": {"uv": [2, 0, 0, 3], "texture": "#0"}, + "down": {"uv": [2, 0, 0, 3], "texture": "#0"} + } + }, + { + "from": [7, 14, 3], + "to": [9, 15, 7], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "up": {"uv": [0, 4, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 4, 2, 0], "texture": "#0"} + } + }, + { + "from": [7, 15, 10], + "to": [9, 16, 11], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "up": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 2, 0], "texture": "#0"} + } + }, + { + "from": [7, 15, 5], + "to": [9, 16, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "up": {"uv": [0, 1, 2, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 2, 0], "texture": "#0"} + } + }, + { + "from": [6, 15, 9], + "to": [10, 16, 10], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 16, 0]}, + "faces": { + "north": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "east": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "south": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "west": {"uv": [0, 1, 1, 0], "texture": "#0"}, + "up": {"uv": [0, 1, 4, 0], "texture": "#0"}, + "down": {"uv": [0, 1, 4, 0], "texture": "#0"} + } + } + ], + "groups": [ + { + "name": "el sphero", + "origin": [8, 8, 8], + "color": 0, + "children": [ + 0, + { + "name": "south", + "origin": [8, 8, 8], + "color": 0, + "children": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27] + }, + { + "name": "north", + "origin": [8, 8, 8], + "color": 0, + "children": [28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54] + }, + { + "name": "east", + "origin": [8, 8, 8], + "color": 0, + "children": [55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81] + }, + { + "name": "west", + "origin": [8, 8, 8], + "color": 0, + "children": [82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108] + }, + { + "name": "down", + "origin": [0, 0, 0], + "color": 0, + "children": [109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135] + }, + { + "name": "up", + "origin": [0, 0, 0], + "color": 0, + "children": [136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162] + } + ] + } + ] +} diff --git a/common/src/main/resources/assets/valkyrienskies/models/item/physics_entity_creator.json b/common/src/main/resources/assets/valkyrienskies/models/item/physics_entity_creator.json new file mode 100644 index 000000000..f0dc3b971 --- /dev/null +++ b/common/src/main/resources/assets/valkyrienskies/models/item/physics_entity_creator.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "minecraft:item/stick" + } +} \ No newline at end of file diff --git a/common/src/main/resources/assets/valkyrienskies/textures/test_sphere.png b/common/src/main/resources/assets/valkyrienskies/textures/test_sphere.png new file mode 100644 index 000000000..ac11082a7 Binary files /dev/null and b/common/src/main/resources/assets/valkyrienskies/textures/test_sphere.png differ diff --git a/common/src/main/resources/data/valkyrienskies/vs_mass/1_18_blocks.json b/common/src/main/resources/data/valkyrienskies/vs_mass/1_18_blocks.json index ab957f9e5..023e8219b 100644 --- a/common/src/main/resources/data/valkyrienskies/vs_mass/1_18_blocks.json +++ b/common/src/main/resources/data/valkyrienskies/vs_mass/1_18_blocks.json @@ -1,55 +1,67 @@ [ { "block": "minecraft:light", - "mass": 0.0 + "mass": 0.1 }, { "block": "minecraft:rooted_dirt", - "mass": 1100.0 + "mass": 1100.0, + "friction": 0.7 }, { "block": "minecraft:calcite", - "mass": 2700.0 + "mass": 2700.0, + "friction": 0.5 }, { "block": "minecraft:dripstone_block", - "mass": 2700.0 + "mass": 2700.0, + "friction": 0.5 }, { "block": "minecraft:pointed_dripstone", - "mass": 1900.0 + "mass": 1900.0, + "friction": 0.5 }, { "block": "minecraft:tuff", - "mass": 1800.0 + "mass": 1800.0, + "friction": 0.7 }, { "block": "minecraft:budding_amethyst", - "mass": 2650.0 + "mass": 2650.0, + "friction": 1.0 }, { "block": "minecraft:amethyst_block", - "mass": 2650.0 + "mass": 2650.0, + "friction": 1.0 }, { "block": "minecraft:small_amethyst_bud", - "mass": 100.0 + "mass": 100.0, + "friction": 0.7 }, { "block": "minecraft:medium_amethyst_bud", - "mass": 300.0 + "mass": 300.0, + "friction": 0.8 }, { "block": "minecraft:large_amethyst_bud", - "mass": 600.0 + "mass": 600.0, + "friction": 0.9 }, { "block": "minecraft:azalea", - "mass": 120.0 + "mass": 120.0, + "elasticity": 0.1 }, { "block": "minecraft:flowering_azalea", - "mass": 120.0 + "mass": 120.0, + "elasticity": 0.1 }, { "block": "minecraft:hanging_roots", @@ -57,7 +69,9 @@ }, { "block": "minecraft:big_dripleaf", - "mass": 8.0 + "mass": 8.0, + "friction": 0.3, + "elasticity": 0.3 }, { "block": "minecraft:big_dripleaf_stem", @@ -85,366 +99,454 @@ }, { "block": "minecraft:moss_block", - "mass": 250.0 + "mass": 250.0, + "friction": 0.5, + "elasticity": 0.05 }, { "block": "minecraft:moss_carpet", - "mass": 15.0 + "mass": 15.0, + "friction": 0.5 }, { "block": "minecraft:lightning_rod", - "mass": 1800.0 + "mass": 1800.0, + "friction": 0.2 }, { "block": "minecraft:copper_block", - "mass": 8960.0 + "mass": 8960.0, + "friction": 0.2 }, { "block": "minecraft:exposed_copper", - "mass": 8960.0 + "mass": 8960.0, + "friction": 0.25 }, { "block": "minecraft:weathered_copper", - "mass": 8960.0 + "mass": 8960.0, + "friction": 0.3 }, { "block": "minecraft:oxidized_copper", - "mass": 8960.0 + "mass": 8960.0, + "friction": 0.35 }, { "block": "minecraft:waxed_copper_block", - "mass": 8960.0 + "mass": 8960.0, + "friction": 0.15 }, { "block": "minecraft:waxed_exposed_copper", - "mass": 8960.0 + "mass": 8960.0, + "friction": 0.2 }, { "block": "minecraft:waxed_weathered_copper", - "mass": 8960.0 + "mass": 8960.0, + "friction": 0.25 }, { "block": "minecraft:waxed_oxidized_copper", - "mass": 8960.0 + "mass": 8960.0, + "friction": 0.3 }, { "block": "minecraft:cut_copper", - "mass": 2240.0 + "mass": 2240.0, + "friction": 0.2 }, { "block": "minecraft:exposed_cut_copper", - "mass": 2240.0 + "mass": 2240.0, + "friction": 0.25 }, { "block": "minecraft:weathered_cut_copper", - "mass": 2240.0 + "mass": 2240.0, + "friction": 0.3 }, { "block": "minecraft:oxidized_cut_copper", - "mass": 2240.0 + "mass": 2240.0, + "friction": 0.35 }, { "block": "minecraft:waxed_cut_copper", - "mass": 2240.0 + "mass": 2240.0, + "friction": 0.15 }, { "block": "minecraft:waxed_exposed_cut_copper", - "mass": 2240.0 + "mass": 2240.0, + "friction": 0.2 }, { "block": "minecraft:waxed_weathered_cut_copper", - "mass": 2240.0 + "mass": 2240.0, + "friction": 0.25 }, { "block": "minecraft:waxed_oxidized_cut_copper", - "mass": 2240.0 + "mass": 2240.0, + "friction": 0.3 }, { "block": "minecraft:cut_copper_slab", - "mass": 1120.0 + "mass": 1120.0, + "friction": 0.2 }, { "block": "minecraft:exposed_cut_copper_slab", - "mass": 1120.0 + "mass": 1120.0, + "friction": 0.25 }, { "block": "minecraft:weathered_cut_copper_slab", - "mass": 1120.0 + "mass": 1120.0, + "friction": 0.3 }, { "block": "minecraft:oxidized_cut_copper_slab", - "mass": 1120.0 + "mass": 1120.0, + "friction": 0.35 }, { "block": "minecraft:waxed_cut_copper_slab", - "mass": 1120.0 + "mass": 1120.0, + "friction": 0.15 }, { "block": "minecraft:waxed_exposed_cut_copper_slab", - "mass": 1120.0 + "mass": 1120.0, + "friction": 0.2 }, { "block": "minecraft:waxed_weathered_cut_copper_slab", - "mass": 1120.0 + "mass": 1120.0, + "friction": 0.25 }, { "block": "minecraft:waxed_oxidized_cut_copper_slab", - "mass": 1120.0 + "mass": 1120.0, + "friction": 0.3 }, { "block": "minecraft:cut_copper_stairs", - "mass": 1680.0 + "mass": 1680.0, + "friction": 0.2 }, { "block": "minecraft:exposed_cut_copper_stairs", - "mass": 1680.0 + "mass": 1680.0, + "friction": 0.25 }, { "block": "minecraft:weathered_cut_copper_stairs", - "mass": 1680.0 + "mass": 1680.0, + "friction": 0.3 }, { "block": "minecraft:oxidized_cut_copper_stairs", - "mass": 1680.0 + "mass": 1680.0, + "friction": 0.35 }, { "block": "minecraft:waxed_cut_copper_stairs", - "mass": 1680.0 + "mass": 1680.0, + "friction": 0.15 }, { "block": "minecraft:waxed_exposed_cut_copper_stairs", - "mass": 1680.0 + "mass": 1680.0, + "friction": 0.2 }, { "block": "minecraft:waxed_weathered_cut_copper_stairs", - "mass": 1680.0 + "mass": 1680.0, + "friction": 0.25 }, { "block": "minecraft:waxed_oxidized_cut_copper_stairs", - "mass": 1680.0 + "mass": 1680.0, + "friction": 0.3 }, { "block": "minecraft:raw_copper_block", - "mass": 8960.0 + "mass": 8960.0, + "friction": 0.8 }, { "block": "minecraft:raw_iron_block", - "mass": 7840.0 + "mass": 7840.0, + "friction": 0.8 }, { "block": "minecraft:raw_gold_block", - "mass": 19280.0 + "mass": 19280.0, + "friction": 0.8 }, { "block": "minecraft:candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:white_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:orange_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:magenta_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:light_blue_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:yellow_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:lime_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:pink_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:gray_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:light_gray_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:cyan_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:purple_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:blue_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:brown_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:green_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:red_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:black_candle", - "mass": 2.0 + "mass": 2.0, + "friction": 0.1 }, { "block": "minecraft:deepslate", - "mass": 2900.0 + "mass": 2900.0, + "friction": 0.5 }, { "block": "minecraft:infested_deepslate", - "mass": 2900.0 + "mass": 2900.0, + "friction": 0.5 }, { "block": "minecraft:cobbled_deepslate", - "mass": 2720.0 + "mass": 2720.0, + "friction": 0.8 }, { "block": "minecraft:chiseled_deepslate", - "mass": 2720.0 + "mass": 2720.0, + "friction": 0.6 }, { "block": "minecraft:polished_deepslate", - "mass": 2720.0 + "mass": 2720.0, + "friction": 0.35 }, { "block": "minecraft:deepslate_bricks", - "mass": 2720.0 + "mass": 2720.0, + "friction": 0.5 }, { "block": "minecraft:cracked_deepslate_bricks", - "mass": 2720.0 + "mass": 2720.0, + "friction": 0.6 }, { "block": "minecraft:deepslate_tiles", - "mass": 2720.0 + "mass": 2720.0, + "friction": 0.6 }, { "block": "minecraft:cracked_deepslate_tiles", - "mass": 2720.0 + "mass": 2720.0, + "friction": 0.7 }, { "block": "minecraft:cobbled_deepslate_slab", - "mass": 1360.0 + "mass": 1360.0, + "friction": 0.8 }, { "block": "minecraft:polished_deepslate_slab", - "mass": 1360.0 + "mass": 1360.0, + "friction": 0.35 }, { "block": "minecraft:deepslate_brick_slab", - "mass": 1360.0 + "mass": 1360.0, + "friction": 0.5 }, { "block": "minecraft:deepslate_tile_slab", - "mass": 1360.0 + "mass": 1360.0, + "friction": 0.6 }, { "block": "minecraft:cobbled_deepslate_stairs", - "mass": 2040.0 + "mass": 2040.0, + "friction": 0.8 }, { "block": "minecraft:polished_deepslate_stairs", - "mass": 2040.0 + "mass": 2040.0, + "friction": 0.35 }, { "block": "minecraft:deepslate_brick_stairs", - "mass": 2040.0 + "mass": 2040.0, + "friction": 0.5 }, { "block": "minecraft:deepslate_tile_stairs", - "mass": 2040.0 + "mass": 2040.0, + "friction": 0.6 }, { "block": "minecraft:cobbled_deepslate_wall", - "mass": 1360.0 + "mass": 1360.0, + "friction": 0.8 }, { "block": "minecraft:polished_deepslate_wall", - "mass": 1360.0 + "mass": 1360.0, + "friction": 0.45 }, { "block": "minecraft:deepslate_brick_wall", - "mass": 1360.0 + "mass": 1360.0, + "friction": 0.5 }, { "block": "minecraft:deepslate_tile_wall", - "mass": 1360.0 + "mass": 1360.0, + "friction": 0.6 }, { "block": "minecraft:copper_ore", - "mass": 3260.0 + "mass": 3260.0, + "friction": 0.6 }, { "block": "minecraft:deepslate_copper_ore", - "mass": 3510.0 + "mass": 3510.0, + "friction": 0.5 }, { "block": "minecraft:deepslate_coal_ore", - "mass": 2715.0 + "mass": 2715.0, + "friction": 0.5 }, { "block": "minecraft:deepslate_lapis_ore", - "mass": 2950.0 + "mass": 2950.0, + "friction": 0.5 }, { "block": "minecraft:deepslate_iron_ore", - "mass": 3430.0 + "mass": 3430.0, + "friction": 0.5 }, { "block": "minecraft:deepslate_gold_ore", - "mass": 4700.0 + "mass": 4700.0, + "friction": 0.5 }, { "block": "minecraft:deepslate_redstone_ore", - "mass": 2225.0 + "mass": 2225.0, + "friction": 0.5 }, { "block": "minecraft:deepslate_diamond_ore", - "mass": 2950.0 + "mass": 2950.0, + "friction": 0.5 }, { "block": "minecraft:deepslate_emerald_ore", - "mass": 2855.0 + "mass": 2855.0, + "friction": 0.5 }, { "block": "minecraft:powder_snow", - "mass": 120.0 + "mass": 120.0, + "friction": 0.3 }, { "block": "minecraft:sculk_sensor", - "mass": 200.0 + "mass": 200.0, + "friction": 0.2, + "elasticity": 0.3 }, { "block": "minecraft:smooth_basalt", - "mass": 3010.0 + "mass": 3010.0, + "friction": 0.35 }, { "block": "minecraft:tinted_glass", - "mass": 2200.0 - }, - { - "block": "minecraft:tuff", - "mass": 2400.0 + "mass": 2200.0, + "friction": 0.2 }, { "tag": "minecraft:candle_cakes", - "mass": 702.0 + "mass": 702.0, + "friction": 0.1 } ] diff --git a/common/src/main/resources/data/valkyrienskies/vs_mass/crafting_stations.json b/common/src/main/resources/data/valkyrienskies/vs_mass/crafting_stations.json index 64db9e16d..a3c014bf8 100644 --- a/common/src/main/resources/data/valkyrienskies/vs_mass/crafting_stations.json +++ b/common/src/main/resources/data/valkyrienskies/vs_mass/crafting_stations.json @@ -1,23 +1,28 @@ [ { "block": "minecraft:crafting_table", - "mass": 800.0 + "mass": 800.0, + "friction": 0.6 }, { "block": "minecraft:furnace", - "mass": 2800.0 + "mass": 2800.0, + "friction": 0.5 }, { "block": "minecraft:blast_furnace", - "mass": 3000.0 + "mass": 3000.0, + "friction": 0.5 }, { "block": "minecraft:smoker", - "mass": 2800.0 + "mass": 2800.0, + "friction": 0.5 }, { "block": "minecraft:stonecutter", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.5 }, { "tag": "minecraft:campfires", @@ -29,15 +34,18 @@ }, { "tag": "minecraft:anvil", - "mass": 7000.0 + "mass": 7000.0, + "friction": 0.2 }, { "block": "minecraft:cauldron", - "mass": 5400.0 + "mass": 5400.0, + "friction": 0.2 }, { "block": "minecraft:water_cauldron", - "mass": 5900.0 + "mass": 5900.0, + "friction": 0.2 }, { "block": "minecraft:brewing_stand", @@ -45,15 +53,18 @@ }, { "block": "minecraft:grindstone", - "mass": 1500.0 + "mass": 1500.0, + "friction": 0.2 }, { "block": "minecraft:fletching_table", - "mass": 900.0 + "mass": 900.0, + "friction": 0.6 }, { "block": "minecraft:smithing_table", - "mass": 1800.0 + "mass": 1800.0, + "friction": 0.6 }, { "block": "minecraft:loom", @@ -61,10 +72,12 @@ }, { "block": "minecraft:cartography_table", - "mass": 800.0 + "mass": 800.0, + "friction": 0.5 }, { "block": "minecraft:composter", - "mass": 700.0 + "mass": 700.0, + "friction": 0.5 } ] diff --git a/common/src/main/resources/data/valkyrienskies/vs_mass/ground.json b/common/src/main/resources/data/valkyrienskies/vs_mass/ground.json index 7077e525f..139a148a2 100644 --- a/common/src/main/resources/data/valkyrienskies/vs_mass/ground.json +++ b/common/src/main/resources/data/valkyrienskies/vs_mass/ground.json @@ -1,190 +1,237 @@ [ { "block": "minecraft:dirt", - "mass": 1220.0 + "mass": 1220.0, + "friction": 0.6 }, { "block": "minecraft:coarse_dirt", - "mass": 1500.0 + "mass": 1500.0, + "friction": 0.7 }, { "block": "minecraft:dirt_path", - "mass": 1200.0 + "mass": 1200.0, + "friction": 0.5 }, { "block": "minecraft:farmland", - "mass": 1220.0 + "mass": 1220.0, + "friction": 0.6 }, { "block": "minecraft:grass", - "mass": 1300.0 + "mass": 1300.0, + "friction": 0.5 }, { "block": "minecraft:clay", - "mass": 1700.0 + "mass": 1700.0, + "friction": 0.4 }, { "block": "minecraft:gravel", - "mass": 1680.0 + "mass": 1680.0, + "friction": 0.7 }, { "block": "minecraft:mycelium", - "mass": 1300.0 + "mass": 1300.0, + "friction": 0.5 }, { "tag": "minecraft:nylium", - "mass": 1180.0 + "mass": 1180.0, + "friction": 0.5 }, { "block": "minecraft:podzol", - "mass": 1300.0 + "mass": 1300.0, + "friction": 0.6 }, { "tag": "minecraft:sand", - "mass": 1560.0 + "mass": 1560.0, + "friction": 0.4 }, { "block": "minecraft:soul_sand", - "mass": 1000.0 + "mass": 1000.0, + "friction": 0.9 }, { "block": "minecraft:soul_soil", - "mass": 900.0 + "mass": 900.0, + "friction": 0.8 }, { "block": "minecraft:andesite", - "mass": 2770.0 + "mass": 2770.0, + "friction": 0.6 }, { "block": "minecraft:basalt", - "mass": 3010.0 + "mass": 3010.0, + "friction": 0.6 }, { "block": "minecraft:smooth_basalt", - "mass": 3010.0 + "mass": 3010.0, + "friction": 0.5 }, { "block": "minecraft:blackstone", - "mass": 3400.0 + "mass": 3400.0, + "friction": 0.7 }, { "block": "minecraft:cobblestone", - "mass": 2480.0 + "mass": 2480.0, + "friction": 0.8 }, { "block": "minecraft:mossy_cobblestone", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.8 }, { "block": "minecraft:diorite", - "mass": 2900.0 + "mass": 2900.0, + "friction": 0.6 }, { "block": "minecraft:end_stone", - "mass": 2800.0 + "mass": 2800.0, + "friction": 0.6 }, { "block": "minecraft:glowstone", - "mass": 1000.0 + "mass": 1000.0, + "friction": 0.7 }, { "block": "minecraft:granite", - "mass": 2700.0 + "mass": 2700.0, + "friction": 0.6 }, { "block": "minecraft:magma_block", - "mass": 3200.0 + "mass": 3200.0, + "friction": 0.4 }, { "block": "minecraft:netherrack", - "mass": 1100.0 + "mass": 1100.0, + "friction": 0.4 }, { "block": "minecraft:obsidian", - "mass": 2350.0 + "mass": 2350.0, + "friction": 0.8 }, { "block": "minecraft:crying_obsidian", - "mass": 2350.0 + "mass": 2350.0, + "friction": 0.8 }, { "block": "minecraft:sandstone", - "mass": 2300.0 + "mass": 2300.0, + "friction": 0.6 }, { "block": "minecraft:red_sandstone", - "mass": 2300.0 + "mass": 2300.0, + "friction": 0.6 }, { "block": "minecraft:stone", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.6 }, { "block": "minecraft:terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:white_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:orange_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:magenta_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:light_blue_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:yellow_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:lime_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:pink_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:gray_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:light_gray_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:cyan_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:purple_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:blue_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:brown_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:green_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:red_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 }, { "block": "minecraft:black_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.6 } ] diff --git a/common/src/main/resources/data/valkyrienskies/vs_mass/masonry.json b/common/src/main/resources/data/valkyrienskies/vs_mass/masonry.json index ddd635cc0..bd5e2a265 100644 --- a/common/src/main/resources/data/valkyrienskies/vs_mass/masonry.json +++ b/common/src/main/resources/data/valkyrienskies/vs_mass/masonry.json @@ -1,666 +1,827 @@ [ { "block": "minecraft:stone_slab", - "mass": 1300.0 + "mass": 1300.0, + "friction": 0.6 }, { "block": "minecraft:smooth_stone_slab", - "mass": 1300.0 + "mass": 1300.0, + "friction": 0.4 }, { "block": "minecraft:granite_slab", - "mass": 1350.0 + "mass": 1350.0, + "friction": 0.6 }, { "block": "minecraft:polished_granite_slab", - "mass": 1350.0 + "mass": 1350.0, + "friction": 0.4 }, { "block": "minecraft:diorite_slab", - "mass": 1450.0 + "mass": 1450.0, + "friction": 0.6 }, { "block": "minecraft:polished_diorite_slab", - "mass": 1450.0 + "mass": 1450.0, + "friction": 0.4 }, { "block": "minecraft:andesite_slab", - "mass": 1385.0 + "mass": 1385.0, + "friction": 0.6 }, { "block": "minecraft:polished_andesite_slab", - "mass": 1385.0 + "mass": 1385.0, + "friction": 0.4 }, { "block": "minecraft:cobblestone_slab", - "mass": 1240.0 + "mass": 1240.0, + "friction": 0.8 }, { "block": "minecraft:mossy_cobblestone_slab", - "mass": 1300.0 + "mass": 1300.0, + "friction": 0.8 }, { "block": "minecraft:stone_brick_slab", - "mass": 1300.0 + "mass": 1300.0, + "friction": 0.5 }, { "block": "minecraft:mossy_stone_brick_slab", - "mass": 1300.0 + "mass": 1300.0, + "friction": 0.3 }, { "block": "minecraft:brick_slab", - "mass": 950.0 + "mass": 950.0, + "friction": 0.6 }, { "block": "minecraft:end_stone_brick_slab", - "mass": 1400.0 + "mass": 1400.0, + "friction": 0.5 }, { "block": "minecraft:nether_brick_slab", - "mass": 950.0 + "mass": 950.0, + "friction": 0.6 }, { "block": "minecraft:red_nether_brick_slab", - "mass": 950.0 + "mass": 950.0, + "friction": 0.6 }, { "block": "minecraft:sandstone_slab", - "mass": 1150.0 + "mass": 1150.0, + "friction": 0.6 }, { "block": "minecraft:cut_sandstone_slab", - "mass": 1150.0 + "mass": 1150.0, + "friction": 0.6 }, { "block": "minecraft:smooth_sandstone_slab", - "mass": 1150.0 + "mass": 1150.0, + "friction": 0.5 }, { "block": "minecraft:red_sandstone_slab", - "mass": 1150.0 + "mass": 1150.0, + "friction": 0.6 }, { "block": "minecraft:cut_red_sandstone_slab", - "mass": 1150.0 + "mass": 1150.0, + "friction": 0.6 }, { "block": "minecraft:smooth_red_sandstone_slab", - "mass": 1150.0 + "mass": 1150.0, + "friction": 0.5 }, { "block": "minecraft:quartz_slab", - "mass": 1160.0 + "mass": 1160.0, + "friction": 0.5 }, { "block": "minecraft:smooth_quartz_slab", - "mass": 1160.0 + "mass": 1160.0, + "friction": 0.3 }, { "block": "minecraft:purpur_slab", - "mass": 60.0 + "mass": 60.0, + "friction": 0.6 }, { "block": "minecraft:prismarine_slab", - "mass": 1000.0 + "mass": 1000.0, + "friction": 0.8 }, { "block": "minecraft:prismarine_brick_slab", - "mass": 1600.0 + "mass": 1600.0, + "friction": 0.5 }, { "block": "minecraft:dark_prismarine_slab", - "mass": 1600.0 + "mass": 1600.0, + "friction": 0.6 }, { "block": "minecraft:blackstone_slab", - "mass": 1700.0 + "mass": 1700.0, + "friction": 0.7 }, { "block": "minecraft:polished_blackstone_slab", - "mass": 1700.0 + "mass": 1700.0, + "friction": 0.5 }, { "block": "minecraft:polished_blackstone_brick_slab", - "mass": 1700.0 + "mass": 1700.0, + "friction": 0.5 }, { "block": "minecraft:stone_stairs", - "mass": 1950.0 + "mass": 1950.0, + "friction": 0.6 }, { "block": "minecraft:granite_stairs", - "mass": 2025.0 + "mass": 2025.0, + "friction": 0.6 }, { "block": "minecraft:polished_granite_stairs", - "mass": 2025.0 + "mass": 2025.0, + "friction": 0.5 }, { "block": "minecraft:diorite_stairs", - "mass": 2175.0 + "mass": 2175.0, + "friction": 0.6 }, { "block": "minecraft:polished_diorite_stairs", - "mass": 2175.0 + "mass": 2175.0, + "friction": 0.5 }, { "block": "minecraft:andesite_stairs", - "mass": 2080.0 + "mass": 2080.0, + "friction": 0.6 }, { "block": "minecraft:polished_andesite_stairs", - "mass": 2080.0 + "mass": 2080.0, + "friction": 0.5 }, { "block": "minecraft:cobblestone_stairs", - "mass": 1860.0 + "mass": 1860.0, + "friction": 0.8 }, { "block": "minecraft:mossy_cobblestone_stairs", - "mass": 1950.0 + "mass": 1950.0, + "friction": 0.8 }, { "block": "minecraft:stone_brick_stairs", - "mass": 1950.0 + "mass": 1950.0, + "friction": 0.5 }, { "block": "minecraft:mossy_stone_brick_stairs", - "mass": 1950.0 + "mass": 1950.0, + "friction": 0.3 }, { "block": "minecraft:brick_stairs", - "mass": 1425.0 + "mass": 1425.0, + "friction": 0.6 }, { "block": "minecraft:end_stone_brick_stairs", - "mass": 2100.0 + "mass": 2100.0, + "friction": 0.5 }, { "block": "minecraft:nether_brick_stairs", - "mass": 1425.0 + "mass": 1425.0, + "friction": 0.6 }, { "block": "minecraft:red_nether_brick_stairs", - "mass": 1425.0 + "mass": 1425.0, + "friction": 0.6 }, { "block": "minecraft:sandstone_stairs", - "mass": 1725.0 + "mass": 1725.0, + "friction": 0.6 }, { "block": "minecraft:smooth_sandstone_stairs", - "mass": 1725.0 + "mass": 1725.0, + "friction": 0.5 }, { "block": "minecraft:red_sandstone_stairs", - "mass": 1725.0 + "mass": 1725.0, + "friction": 0.6 }, { "block": "minecraft:smooth_red_sandstone_stairs", - "mass": 1725.0 + "mass": 1725.0, + "friction": 0.5 }, { "block": "minecraft:quartz_stairs", - "mass": 1740.0 + "mass": 1740.0, + "friction": 0.5 }, { "block": "minecraft:smooth_quartz_stairs", - "mass": 1740.0 + "mass": 1740.0, + "friction": 0.3 }, { "block": "minecraft:purpur_stairs", - "mass": 90.0 + "mass": 90.0, + "friction": 0.6 }, { "block": "minecraft:prismarine_stairs", - "mass": 1500.0 + "mass": 1500.0, + "friction": 0.8 }, { "block": "minecraft:prismarine_brick_stairs", - "mass": 2400.0 + "mass": 2400.0, + "friction": 0.5 }, { "block": "minecraft:dark_prismarine_stairs", - "mass": 2400.0 + "mass": 2400.0, + "friction": 0.6 }, { "block": "minecraft:blackstone_stairs", - "mass": 2550.0 + "mass": 2550.0, + "friction": 0.7 }, { "block": "minecraft:polished_blackstone_stairs", - "mass": 2550.0 + "mass": 2550.0, + "friction": 0.5 }, { "block": "minecraft:polished_blackstone_brick_stairs", - "mass": 2550.0 + "mass": 2550.0, + "friction": 0.4 }, { "block": "minecraft:granite_wall", - "mass": 1350.0 + "mass": 1350.0, + "friction": 0.6 }, { "block": "minecraft:diorite_wall", - "mass": 1450.0 + "mass": 1450.0, + "friction": 0.6 }, { "block": "minecraft:andesite_wall", - "mass": 1385.0 + "mass": 1385.0, + "friction": 0.6 }, { "block": "minecraft:cobblestone_wall", - "mass": 1240.0 + "mass": 1240.0, + "friction": 0.8 }, { "block": "minecraft:mossy_cobblestone_wall", - "mass": 1300.0 + "mass": 1300.0, + "friction": 0.8 }, { "block": "minecraft:stone_brick_wall", - "mass": 1300.0 + "mass": 1300.0, + "friction": 0.5 }, { "block": "minecraft:mossy_stone_brick_wall", - "mass": 1300.0 + "mass": 1300.0, + "friction": 0.3 }, { "block": "minecraft:brick_wall", - "mass": 950.0 + "mass": 950.0, + "friction": 0.6 }, { "block": "minecraft:end_stone_brick_wall", - "mass": 1400.0 + "mass": 1400.0, + "friction": 0.5 }, { "block": "minecraft:nether_brick_wall", - "mass": 950.0 + "mass": 950.0, + "friction": 0.6 }, { "block": "minecraft:red_nether_brick_wall", - "mass": 950.0 + "mass": 950.0, + "friction": 0.6 }, { "block": "minecraft:sandstone_wall", - "mass": 1150.0 + "mass": 1150.0, + "friction": 0.6 }, { "block": "minecraft:red_sandstone_wall", - "mass": 1150.0 + "mass": 1150.0, + "friction": 0.6 }, { "block": "minecraft:prismarine_wall", - "mass": 1000.0 + "mass": 1000.0, + "friction": 0.8 }, { "block": "minecraft:blackstone_wall", - "mass": 1700.0 + "mass": 1700.0, + "friction": 0.7 }, { "block": "minecraft:polished_blackstone_wall", - "mass": 1700.0 + "mass": 1700.0, + "friction": 0.5 }, { "block": "minecraft:polished_blackstone_brick_wall", - "mass": 1700.0 + "mass": 1700.0, + "friction": 0.4 }, { "block": "minecraft:polished_granite", - "mass": 2700.0 + "mass": 2700.0, + "friction": 0.4 }, { "block": "minecraft:polished_diorite", - "mass": 2900.0 + "mass": 2900.0, + "friction": 0.4 }, { "block": "minecraft:polished_andesite", - "mass": 2770.0 + "mass": 2770.0, + "friction": 0.4 }, { "block": "minecraft:polished_basalt", - "mass": 3010.0 + "mass": 3010.0, + "friction": 0.4 }, { "block": "minecraft:polished_blackstone", - "mass": 3400.0 + "mass": 3400.0, + "friction": 0.5 }, { "block": "minecraft:polished_blackstone_bricks", - "mass": 3400.0 + "mass": 3400.0, + "friction": 0.4 }, { "block": "minecraft:smooth_quartz", - "mass": 2320.0 + "mass": 2320.0, + "friction": 0.3 }, { "block": "minecraft:smooth_sandstone", - "mass": 2300.0 + "mass": 2300.0, + "friction": 0.5 }, { "block": "minecraft:smooth_red_sandstone", - "mass": 2300.0 + "mass": 2300.0, + "friction": 0.4 }, { "block": "minecraft:smooth_stone", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.4 }, { "block": "minecraft:cracked_stone_bricks", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.7 }, { "block": "minecraft:cracked_nether_bricks", - "mass": 1900.0 + "mass": 1900.0, + "friction": 0.7 }, { "block": "minecraft:cracked_polished_blackstone_bricks", - "mass": 3400.0 + "mass": 3400.0, + "friction": 0.6 }, { "block": "minecraft:chiseled_sandstone", - "mass": 2300.0 + "mass": 2300.0, + "friction": 0.6 }, { "block": "minecraft:chiseled_stone_bricks", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.6 }, { "block": "minecraft:chiseled_nether_bricks", - "mass": 1900.0 + "mass": 1900.0, + "friction": 0.6 }, { "block": "minecraft:chiseled_quartz_block", - "mass": 2320.0 + "mass": 2320.0, + "friction": 0.6 }, { "block": "minecraft:chiseled_red_sandstone", - "mass": 2300.0 + "mass": 2300.0, + "friction": 0.6 }, { "block": "minecraft:chiseled_polished_blackstone", - "mass": 3400.0 + "mass": 3400.0, + "friction": 0.6 }, { "block": "minecraft:quartz_pillar", - "mass": 2320.0 + "mass": 2320.0, + "friction": 0.5 }, { "block": "minecraft:purpur_pillar", - "mass": 120.0 + "mass": 120.0, + "friction": 0.6 }, { "block": "minecraft:purpur_block", - "mass": 120.0 + "mass": 120.0, + "friction": 0.6 }, { "block": "minecraft:quartz_block", - "mass": 2320.0 + "mass": 2320.0, + "friction": 0.6 }, { "block": "minecraft:mossy_stone_bricks", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.3 }, { "block": "minecraft:gilded_blackstone", - "mass": 3800.0 + "mass": 3800.0, + "friction": 0.7 }, { "block": "minecraft:nether_brick_fence", - "mass": 380.0 + "mass": 380.0, + "friction": 0.6 }, { "block": "minecraft:bricks", - "mass": 1900.0 + "mass": 1900.0, + "friction": 0.6 }, { "block": "minecraft:stone_bricks", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.5 }, { "block": "minecraft:nether_bricks", - "mass": 1900.0 + "mass": 1900.0, + "friction": 0.5 }, { "block": "minecraft:red_nether_bricks", - "mass": 1900.0 + "mass": 1900.0, + "friction": 0.5 }, { "block": "minecraft:end_stone_bricks", - "mass": 2800.0 + "mass": 2800.0, + "friction": 0.5 }, { "block": "minecraft:quartz_bricks", - "mass": 2320.0 + "mass": 2320.0, + "friction": 0.5 }, { "block": "minecraft:prismarine", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.8 }, { "block": "minecraft:prismarine_bricks", - "mass": 3200.0 + "mass": 3200.0, + "friction": 0.5 }, { "block": "minecraft:dark_prismarine", - "mass": 3200.0 - }, - { - "block": "minecraft:prismarine", - "mass": 2000.0 + "mass": 3200.0, + "friction": 0.6 }, { "block": "minecraft:white_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:orange_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:magenta_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:light_blue_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:yellow_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:lime_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:pink_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:gray_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:light_gray_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:cyan_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:purple_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:blue_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:brown_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:green_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:red_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:black_glazed_terracotta", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:white_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:orange_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:magenta_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:light_blue_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:yellow_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:lime_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:pink_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:gray_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:light_gray_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:cyan_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:purple_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:blue_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:brown_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:green_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:red_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:black_concrete_powder", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.6 }, { "block": "minecraft:white_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:orange_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:magenta_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:light_blue_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:yellow_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:lime_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:pink_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:gray_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:light_gray_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:cyan_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:purple_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:blue_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:brown_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:green_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:red_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:black_concrete", - "mass": 2360.0 + "mass": 2360.0, + "friction": 0.4 }, { "block": "minecraft:infested_stone", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.6 }, { "block": "minecraft:infested_cobblestone", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.8 }, { "block": "minecraft:infested_stone_bricks", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.5 }, { "block": "minecraft:infested_cracked_stone_bricks", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.6 }, { "block": "minecraft:infested_mossy_stone_bricks", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.3 }, { "block": "minecraft:infested_chiseled_stone_bricks", - "mass": 2600.0 + "mass": 2600.0, + "friction": 0.6 } ] diff --git a/common/src/main/resources/data/valkyrienskies/vs_mass/misc.json b/common/src/main/resources/data/valkyrienskies/vs_mass/misc.json index dc34f5392..c964b8257 100644 --- a/common/src/main/resources/data/valkyrienskies/vs_mass/misc.json +++ b/common/src/main/resources/data/valkyrienskies/vs_mass/misc.json @@ -1,127 +1,152 @@ [ { "tag": "minecraft:fire", - "mass": 0.0 + "mass": 0.1 }, { "tag": "minecraft:portals", - "mass": 0.0 + "mass": 0.1 }, { "block": "minecraft:bedrock", - "mass": 0.0 + "mass": 3000.0, + "friction": 0.8 }, { "block": "minecraft:barrier", - "mass": 0.0 + "mass": 0.1 }, { "block": "minecraft:command_block", - "mass": 0.0 + "mass": 0.1 }, { "block": "minecraft:chain_command_block", - "mass": 0.0 + "mass": 0.1 }, { "block": "minecraft:repeating_command_block", - "mass": 0.0 + "mass": 0.1 }, { "block": "minecraft:structure_block", - "mass": 0.0 + "mass": 0.1 }, { "block": "minecraft:gold_block", - "mass": 19280.0 + "mass": 19280.0, + "friction": 0.2 }, { "block": "minecraft:iron_block", - "mass": 7840.0 + "mass": 7840.0, + "friction": 0.2 }, { "block": "minecraft:diamond_block", - "mass": 3520.0 + "mass": 3520.0, + "friction": 0.1 }, { "block": "minecraft:emerald_block", - "mass": 2670.0 + "mass": 2670.0, + "friction": 0.1 }, { "block": "minecraft:coal_block", - "mass": 1400.0 + "mass": 1400.0, + "friction": 0.7 }, { "block": "minecraft:netherite_block", - "mass": 19280.0 + "mass": 89680.0, + "friction": 0.2 }, { "block": "minecraft:lapis_block", - "mass": 2750.0 + "mass": 2750.0, + "friction": 0.5 }, { "block": "minecraft:coal_ore", - "mass": 2465.0 + "mass": 2465.0, + "friction": 0.6 }, { "block": "minecraft:diamond_ore", - "mass": 2700.0 + "mass": 2700.0, + "friction": 0.6 }, { "block": "minecraft:emerald_ore", - "mass": 2605.0 + "mass": 2605.0, + "friction": 0.6 }, { "block": "minecraft:ancient_debris", - "mass": 3140.0 + "mass": 3140.0, + "friction": 0.8 }, { "block": "minecraft:iron_ore", - "mass": 3180.0 + "mass": 3180.0, + "friction": 0.6 }, { "block": "minecraft:gold_ore", - "mass": 4450.0 + "mass": 4450.0, + "friction": 0.6 }, { "block": "minecraft:lapis_ore", - "mass": 2700.0 + "mass": 2700.0, + "friction": 0.6 }, { "block": "minecraft:redstone_ore", - "mass": 1975.0 + "mass": 1975.0, + "friction": 0.6 }, { "block": "minecraft:nether_quartz_ore", - "mass": 1405.0 + "mass": 1405.0, + "friction": 0.4 }, { "block": "minecraft:nether_gold_ore", - "mass": 2210.0 + "mass": 2210.0, + "friction": 0.4 }, { "block": "minecraft:bone_block", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:cobweb", - "mass": 0.0 + "mass": 0.1, + "friction": 1.0 }, { "block": "minecraft:hay_block", - "mass": 200.0 + "mass": 200.0, + "friction": 0.6, + "elasticity": 0.3 }, { "block": "minecraft:carved_pumpkin", - "mass": 100.0 + "mass": 100.0, + "friction": 0.3 }, { "block": "minecraft:jack_o_lantern", - "mass": 105.0 + "mass": 105.0, + "friction": 0.3 }, { "block": "minecraft:beacon", - "mass": 930.0 + "mass": 930.0, + "friction": 0.2 }, { "block": "minecraft:conduit", @@ -129,11 +154,15 @@ }, { "block": "minecraft:sponge", - "mass": 170.0 + "mass": 170.0, + "friction": 0.6, + "elasticity": 0.2 }, { "block": "minecraft:wet_sponge", - "mass": 1050.0 + "mass": 1050.0, + "friction": 0.3, + "elasticity": 0.6 }, { "block": "minecraft:torch", @@ -161,171 +190,216 @@ }, { "block": "minecraft:end_rod", - "mass": 10.0 + "mass": 10.0, + "friction": 0.1 }, { "block": "minecraft:sea_lantern", - "mass": 2500.0 + "mass": 2500.0, + "friction": 0.2 }, { "block": "minecraft:glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:white_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:orange_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:magenta_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:light_blue_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:yellow_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:lime_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:pink_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:gray_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:light_gray_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:cyan_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:purple_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:blue_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:brown_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:green_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:red_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:black_stained_glass", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.2 }, { "block": "minecraft:glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:white_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:orange_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:magenta_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:light_blue_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:yellow_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:lime_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:pink_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:gray_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:light_gray_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:cyan_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:purple_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:blue_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:brown_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:green_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:red_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:black_stained_glass_pane", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "tag": "minecraft:beds", - "mass": 125.0 + "mass": 125.0, + "friction": 0.6, + "elasticity": 0.5 }, { "tag": "minecraft:carpets", - "mass": 20.0 + "mass": 20.0, + "friction": 0.6, + "elasticity": 0.05 }, { "tag": "minecraft:wool", - "mass": 450.0 + "mass": 450.0, + "friction": 0.6, + "elasticity": 0.5 }, { "block": "minecraft:bookshelf", - "mass": 650.0 + "mass": 650.0, + "friction": 0.5 }, { "block": "minecraft:chest", - "mass": 400.0 + "mass": 400.0, + "friction": 0.4 }, { "block": "minecraft:barrel", - "mass": 375.0 + "mass": 375.0, + "friction": 0.4 }, { "block": "minecraft:ladder", @@ -337,63 +411,84 @@ }, { "block": "minecraft:snow", - "mass": 25.0 + "mass": 25.0, + "friction": 0.2 }, { "block": "minecraft:snow_block", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:ice", - "mass": 830.0 + "mass": 830.0, + "friction": 0.05 }, { "block": "minecraft:packed_ice", - "mass": 875.0 + "mass": 875.0, + "friction": 0.02 }, { "block": "minecraft:blue_ice", - "mass": 920.0 + "mass": 920.0, + "friction": 0.0 }, { "block": "minecraft:jukebox", - "mass": 800.0 + "mass": 800.0, + "friction": 0.6 }, { "block": "minecraft:iron_bars", - "mass": 250.0 + "mass": 250.0, + "friction": 0.2 }, { "block": "minecraft:chain", - "mass": 50.0 + "mass": 50.0, + "friction": 0.7 + }, + { + "block": "minecraft:dragon_egg", + "mass": 1400.0, + "friction": 0.8 }, { "block": "minecraft:end_portal_frame", - "mass": 3000.0 + "mass": 3000.0, + "friction": 0.4 }, { "block": "minecraft:ender_chest", - "mass": 800.0 + "mass": 800.0, + "friction": 0.4 }, { "block": "minecraft:slime_block", - "mass": 1100.0 + "mass": 1100.0, + "friction": 1.0, + "elasticity": 1.0 }, { "block": "minecraft:honey_block", - "mass": 1400.0 + "mass": 1400.0, + "friction": 1.0 }, { "block": "minecraft:honeycomb_block", - "mass": 900.0 + "mass": 900.0, + "friction": 0.8 }, { "block": "minecraft:bee_nest", - "mass": 400.0 + "mass": 400.0, + "friction": 0.5 }, { "block": "minecraft:beehive", - "mass": 450.0 + "mass": 450.0, + "friction": 0.4 }, { "block": "minecraft:turtle_egg", @@ -405,7 +500,9 @@ }, { "block": "minecraft:dried_kelp_block", - "mass": 1000.0 + "mass": 1000.0, + "friction": 0.6, + "elasticity": 0.3 }, { "tag": "minecraft:signs", @@ -417,15 +514,18 @@ }, { "block": "minecraft:cake", - "mass": 700.0 + "mass": 700.0, + "friction": 0.1 }, { "block": "minecraft:skeleton_skull", - "mass": 2.0 + "mass": 2.0, + "friction": 0.2 }, { "block": "minecraft:wither_skeleton_skull", - "mass": 2.0 + "mass": 2.0, + "friction": 0.2 }, { "block": "minecraft:zombie_head", @@ -445,11 +545,13 @@ }, { "block": "minecraft:skeleton_wall_skull", - "mass": 2.0 + "mass": 2.0, + "friction": 0.2 }, { "block": "minecraft:wither_skeleton_wall_skull", - "mass": 2.0 + "mass": 2.0, + "friction": 0.2 }, { "block": "minecraft:zombie_wall_head", @@ -469,15 +571,18 @@ }, { "block": "minecraft:lodestone", - "mass": 4450.0 + "mass": 4450.0, + "friction": 0.5 }, { "block": "minecraft:bell", - "mass": 1000.0 + "mass": 1000.0, + "friction": 0.2 }, { "block": "minecraft:respawn_anchor", - "mass": 2000.0 + "mass": 2000.0, + "friction": 0.7 }, { "tag": "minecraft:banners", diff --git a/common/src/main/resources/data/valkyrienskies/vs_mass/plants.json b/common/src/main/resources/data/valkyrienskies/vs_mass/plants.json index 96bfbcea6..9ae1a5cf2 100644 --- a/common/src/main/resources/data/valkyrienskies/vs_mass/plants.json +++ b/common/src/main/resources/data/valkyrienskies/vs_mass/plants.json @@ -5,7 +5,8 @@ }, { "tag": "minecraft:leaves", - "mass": 200.0 + "mass": 200.0, + "elasticity": 0.15 }, { "tag": "minecraft:small_flowers", @@ -89,95 +90,118 @@ }, { "block": "minecraft:sea_pickle", - "mass": 2.0 + "mass": 2.0, + "elasticity": 0.1 }, { "tag": "minecraft:coral_blocks", - "mass": 1500.0 + "mass": 1500.0, + "friction": 0.7 }, { "block": "minecraft:dead_tube_coral_block", - "mass": 1500.0 + "mass": 1500.0, + "friction": 0.7 }, { "block": "minecraft:dead_brain_coral_block", - "mass": 1500.0 + "mass": 1500.0, + "friction": 0.7 }, { "block": "minecraft:dead_bubble_coral_block", - "mass": 1500.0 + "mass": 1500.0, + "friction": 0.7 }, { "block": "minecraft:dead_fire_coral_block", - "mass": 1500.0 + "mass": 1500.0, + "friction": 0.7 }, { "block": "minecraft:dead_horn_coral_block", - "mass": 1500.0 + "mass": 1500.0, + "friction": 0.7 }, { "tag": "minecraft:corals", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_tube_coral", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_brain_coral", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_bubble_coral", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_fire_coral", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_horn_coral", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_tube_coral_fan", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_brain_coral_fan", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_bubble_coral_fan", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_fire_coral_fan", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_horn_coral_fan", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_tube_coral_wall_fan", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_brain_coral_wall_fan", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_bubble_coral_wall_fan", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_fire_coral_wall_fan", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_horn_coral_wall_fan", - "mass": 5.0 + "mass": 5.0, + "friction": 0.7 }, { "block": "minecraft:dead_bush", @@ -197,7 +221,8 @@ }, { "block": "minecraft:melon", - "mass": 600.0 + "mass": 600.0, + "friction": 0.2 }, { "block": "minecraft:pumpkin_stem", @@ -209,7 +234,8 @@ }, { "block": "minecraft:pumpkin", - "mass": 600.0 + "mass": 600.0, + "friction": 0.3 }, { "block": "minecraft:warped_fungus", @@ -253,7 +279,8 @@ }, { "tag": "minecraft:wart_blocks", - "mass": 600.0 + "mass": 600.0, + "elasticity": 0.1 }, { "block": "minecraft:shroomlight", @@ -261,23 +288,31 @@ }, { "block": "minecraft:chorus_plant", - "mass": 30.0 + "mass": 30.0, + "friction": 0.6 }, { "block": "minecraft:chorus_flower", - "mass": 50.0 + "mass": 50.0, + "friction": 0.4 }, { "block": "minecraft:brown_mushroom_block", - "mass": 400.0 + "mass": 400.0, + "friction": 0.2, + "elasticity": 0.1 }, { "block": "minecraft:red_mushroom_block", - "mass": 400.0 + "mass": 400.0, + "friction": 0.2, + "elasticity": 0.1 }, { "block": "minecraft:mushroom_stem", - "mass": 600.0 + "mass": 600.0, + "friction": 0.2, + "elasticity": 0.1 }, { "block": "minecraft:brown_mushroom", diff --git a/common/src/main/resources/data/valkyrienskies/vs_mass/redstone_components.json b/common/src/main/resources/data/valkyrienskies/vs_mass/redstone_components.json index 994ede13d..65540b04b 100644 --- a/common/src/main/resources/data/valkyrienskies/vs_mass/redstone_components.json +++ b/common/src/main/resources/data/valkyrienskies/vs_mass/redstone_components.json @@ -5,47 +5,58 @@ }, { "block": "minecraft:dispenser", - "mass": 2800.0 + "mass": 2800.0, + "friction": 0.5 }, { "block": "minecraft:dropper", - "mass": 2800.0 + "mass": 2800.0, + "friction": 0.5 }, { "block": "minecraft:note_block", - "mass": 1200.0 + "mass": 1200.0, + "friction": 0.6 }, { "block": "minecraft:detector_rail", - "mass": 380.0 + "mass": 380.0, + "friction": 0.7 }, { "block": "minecraft:powered_rail", - "mass": 800.0 + "mass": 800.0, + "friction": 0.7 }, { "block": "minecraft:rail", - "mass": 330.0 + "mass": 330.0, + "friction": 0.7 }, { "block": "minecraft:activator_rail", - "mass": 330.0 + "mass": 330.0, + "friction": 0.7 }, { "block": "minecraft:piston", - "mass": 2800.0 + "mass": 2800.0, + "friction": 0.5 }, { "block": "minecraft:sticky_piston", - "mass": 2800.0 + "mass": 2800.0, + "friction": 0.5 }, { "block": "minecraft:piston_head", - "mass": 0.0 + "mass": 0.1, + "friction": 0.5 }, { "block": "minecraft:moving_piston", - "mass": 0.0 + "mass": 0.1, + "friction": 0.5 }, { "block": "minecraft:tnt", @@ -97,23 +108,27 @@ }, { "block": "minecraft:tripwire", - "mass": 0.0 + "mass": 0.1 }, { "block": "minecraft:daylight_detector", - "mass": 1200.0 + "mass": 1200.0, + "friction": 0.2 }, { "block": "minecraft:redstone_block", - "mass": 1350.0 + "mass": 1350.0, + "friction": 0.4 }, { "block": "minecraft:observer", - "mass": 2800.0 + "mass": 2800.0, + "friction": 0.5 }, { "block": "minecraft:target", - "mass": 200.0 + "mass": 200.0, + "elasticity": 0.3 }, { "block": "minecraft:lectern", @@ -125,23 +140,28 @@ }, { "block": "minecraft:redstone_lamp", - "mass": 1200.0 + "mass": 1200.0, + "friction": 0.2 }, { "block": "minecraft:comparator", - "mass": 250.0 + "mass": 250.0, + "friction": 0.3 }, { "block": "minecraft:repeater", - "mass": 250.0 + "mass": 250.0, + "friction": 0.3 }, { "block": "minecraft:hopper", - "mass": 3800.0 + "mass": 3800.0, + "friction": 0.3 }, { "tag": "minecraft:shulker_boxes", - "mass": 800.0 + "mass": 800.0, + "friction": 0.1 }, { "tag": "minecraft:fence_gates", @@ -153,7 +173,8 @@ }, { "block": "minecraft:iron_door", - "mass": 1000.0 + "mass": 1000.0, + "friction": 0.35 }, { "tag": "minecraft:wooden_trapdoors", @@ -161,6 +182,7 @@ }, { "block": "minecraft:iron_trapdoor", - "mass": 1000.0 + "mass": 1000.0, + "friction": 0.35 } ] diff --git a/common/src/main/resources/data/valkyrienskies/vs_mass/wood.json b/common/src/main/resources/data/valkyrienskies/vs_mass/wood.json index 25bac9acd..f1f037988 100644 --- a/common/src/main/resources/data/valkyrienskies/vs_mass/wood.json +++ b/common/src/main/resources/data/valkyrienskies/vs_mass/wood.json @@ -1,82 +1,302 @@ [ { - "tag": "minecraft:wooden_stairs", - "mass": 525.0 + "block": "minecraft:oak_wood", + "mass": 900.0, + "friction": 0.6 }, { - "tag": "minecraft:wooden_slabs", - "mass": 350.0 + "block": "minecraft:oak_log", + "mass": 900.0, + "friction": 0.6 + }, + { + "block": "minecraft:stripped_oak_wood", + "mass": 900.0, + "friction": 0.4 }, { - "tag": "minecraft:oak_logs", - "mass": 900.0 + "block": "minecraft:stripped_oak_log", + "mass": 900.0, + "friction": 0.4 }, { "block": "minecraft:oak_planks", - "mass": 600.0 + "mass": 600.0, + "friction": 0.5 + }, + { + "block": "minecraft:oak_slab", + "mass": 300.0, + "friction": 0.5 }, { - "tag": "minecraft:spruce_logs", - "mass": 780.0 + "block": "minecraft:oak_slab", + "mass": 450.0, + "friction": 0.5 + }, + { + "block": "minecraft:spruce_wood", + "mass": 780.0, + "friction": 0.6 + }, + { + "block": "minecraft:spruce_log", + "mass": 780.0, + "friction": 0.6 + }, + { + "block": "minecraft:stripped_spruce_wood", + "mass": 780.0, + "friction": 0.4 + }, + { + "block": "minecraft:stripped_spruce_log", + "mass": 780.0, + "friction": 0.4 }, { "block": "minecraft:spruce_planks", - "mass": 480.0 + "mass": 480.0, + "friction": 0.5 + }, + { + "block": "minecraft:spruce_slab", + "mass": 240.0, + "friction": 0.5 + }, + { + "block": "minecraft:spruce_stairs", + "mass": 360.0, + "friction": 0.5 + }, + { + "block": "minecraft:birch_wood", + "mass": 770.0, + "friction": 0.6 + }, + { + "block": "minecraft:birch_log", + "mass": 770.0, + "friction": 0.6 + }, + { + "block": "minecraft:stripped_birch_wood", + "mass": 770.0, + "friction": 0.4 }, { - "tag": "minecraft:birch_logs", - "mass": 770.0 + "block": "minecraft:stripped_birch_log", + "mass": 770.0, + "friction": 0.4 }, { "block": "minecraft:birch_planks", - "mass": 510.0 + "mass": 510.0, + "friction": 0.5 + }, + { + "block": "minecraft:birch_slab", + "mass": 255.0, + "friction": 0.5 + }, + { + "block": "minecraft:birch_stairs", + "mass": 380.0, + "friction": 0.5 + }, + { + "block": "minecraft:jungle_wood", + "mass": 850.0, + "friction": 0.6 + }, + { + "block": "minecraft:jungle_log", + "mass": 850.0, + "friction": 0.6 }, { - "tag": "minecraft:jungle_logs", - "mass": 850.0 + "block": "minecraft:stripped_jungle_wood", + "mass": 850.0, + "friction": 0.4 + }, + { + "block": "minecraft:stripped_jungle_log", + "mass": 850.0, + "friction": 0.4 }, { "block": "minecraft:jungle_planks", - "mass": 500.0 + "mass": 500.0, + "friction": 0.5 + }, + { + "block": "minecraft:jungle_slab", + "mass": 250.0, + "friction": 0.5 + }, + { + "block": "minecraft:jungle_stairs", + "mass": 375.0, + "friction": 0.5 + }, + { + "block": "minecraft:acacia_wood", + "mass": 770.0, + "friction": 0.6 + }, + { + "block": "minecraft:acacia_log", + "mass": 770.0, + "friction": 0.6 }, { - "tag": "minecraft:acacia_logs", - "mass": 770.0 + "block": "minecraft:stripped_acacia_wood", + "mass": 770.0, + "friction": 0.4 + }, + { + "block": "minecraft:stripped_acacia_log", + "mass": 770.0, + "friction": 0.4 }, { "block": "minecraft:acacia_planks", - "mass": 650.0 + "mass": 550.0, + "friction": 0.5 + }, + { + "block": "minecraft:acacia_slab", + "mass": 275.0, + "friction": 0.5 + }, + { + "block": "minecraft:acacia_stairs", + "mass": 410.0, + "friction": 0.5 }, { - "tag": "minecraft:dark_oak_logs", - "mass": 800.0 + "block": "minecraft:dark_oak_wood", + "mass": 800.0, + "friction": 0.6 + }, + { + "block": "minecraft:dark_oak_log", + "mass": 800.0, + "friction": 0.6 + }, + { + "block": "minecraft:stripped_dark_oak_wood", + "mass": 800.0, + "friction": 0.4 + }, + { + "block": "minecraft:stripped_dark_oak_log", + "mass": 800.0, + "friction": 0.4 }, { "block": "minecraft:dark_oak_planks", - "mass": 700.0 + "mass": 650.0, + "friction": 0.5 + }, + { + "block": "minecraft:dark_oak_slab", + "mass": 325.0, + "friction": 0.5 + }, + { + "block": "minecraft:dark_oak_stairs", + "mass": 485.0, + "friction": 0.5 + }, + { + "block": "minecraft:warped_hyphae", + "mass": 980.0, + "friction": 0.6 + }, + { + "block": "minecraft:warped_stem", + "mass": 980.0, + "friction": 0.6 + }, + { + "block": "minecraft:stripped_warped_hyphae", + "mass": 980.0, + "friction": 0.4 }, { - "tag": "minecraft:warped_stems", - "mass": 980.0 + "block": "minecraft:stripped_warped_stem", + "mass": 980.0, + "friction": 0.4 }, { "block": "minecraft:warped_planks", - "mass": 910.0 + "mass": 910.0, + "friction": 0.5 + }, + { + "block": "minecraft:warped_slab", + "mass": 455.0, + "friction": 0.5 + }, + { + "block": "minecraft:warped_stairs", + "mass": 680.0, + "friction": 0.5 + }, + { + "block": "minecraft:crimson_hyphae", + "mass": 980.0, + "friction": 0.6 + }, + { + "block": "minecraft:crimson_stem", + "mass": 980.0, + "friction": 0.6 + }, + { + "block": "minecraft:stripped_crimson_hyphae", + "mass": 980.0, + "friction": 0.4 }, { - "tag": "minecraft:crimson_stems", - "mass": 1000.0 + "block": "minecraft:stripped_crimson_stem", + "mass": 980.0, + "friction": 0.4 }, { "block": "minecraft:crimson_planks", - "mass": 999.0 + "mass": 910.0, + "friction": 0.5 + }, + { + "block": "minecraft:crimson_slab", + "mass": 455.0, + "friction": 0.5 + }, + { + "block": "minecraft:crimson_stairs", + "mass": 680.0, + "friction": 0.5 }, { "tag": "minecraft:logs", - "mass": 800.0 + "mass": 800.0, + "friction": 0.6 }, { "tag": "minecraft:planks", - "mass": 700.0 + "mass": 700.0, + "friction": 0.5 + }, + { + "tag": "minecraft:wooden_stairs", + "mass": 525.0, + "friction": 0.5 + }, + { + "tag": "minecraft:wooden_slabs", + "mass": 350.0, + "friction": 0.5 } ] diff --git a/common/src/main/resources/valkyrienskies-common.accesswidener b/common/src/main/resources/valkyrienskies-common.accesswidener index 2f5276228..f9e167710 100644 --- a/common/src/main/resources/valkyrienskies-common.accesswidener +++ b/common/src/main/resources/valkyrienskies-common.accesswidener @@ -24,3 +24,5 @@ accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo mutable field net/minecraft/world/phys/HitResult location Lnet/minecraft/world/phys/Vec3; # Make the field public accessible field net/minecraft/world/phys/HitResult location Lnet/minecraft/world/phys/Vec3; + +accessible class net/minecraft/server/level/ChunkMap$DistanceManager diff --git a/common/src/main/resources/valkyrienskies-common.mixins.json b/common/src/main/resources/valkyrienskies-common.mixins.json index 8a4221b25..0c1e40ed0 100644 --- a/common/src/main/resources/valkyrienskies-common.mixins.json +++ b/common/src/main/resources/valkyrienskies-common.mixins.json @@ -7,10 +7,17 @@ "accessors.entity.EntityAccessor", "accessors.network.protocol.game.ClientboundSectionBlocksUpdatePacketAccessor", "accessors.resource.ResourceKeyAccessor", - "accessors.server.world.ChunkMapAccessor", + "accessors.server.level.ChunkMapAccessor", + "accessors.server.level.DistanceManagerAccessor", + "accessors.server.level.ServerChunkCacheAccessor", + "accessors.util.math.Matrix4fAccessor", + "accessors.world.level.block.SlabBlockAccessor", + "accessors.world.level.block.StairBlockAccessor", "accessors.world.level.pathfinder.PathAccessor", + "commands.argument.selector.MixinEntitySelectorParser", "entity.MixinEntity", "feature.ai.node_evaluator.PathNavigationRegionAccessor", + "feature.ai.node_evaluator.SwimNodeEvaluatorMixin", "feature.ai.node_evaluator.WalkNodeEvaluatorMixin", "feature.bed_fix.MixinServerPlayer", "feature.block_placement_orientation.MixinBlockItem", @@ -20,6 +27,7 @@ "feature.commands.MixinCommandSourceStack", "feature.conduit_fix.ConduitMixin", "feature.container_distance_check.MixinContainer", + "feature.dismount_dead_entities.MixinLivingEntity", "feature.dispensers.MixinDefaultDispenseItemBehavior", "feature.distance_replace.MixinEntity", "feature.entity_collision.MixinEntity", @@ -43,10 +51,43 @@ "feature.tick_ship_chunks.MixinChunkMap", "feature.world_border.MixinLevel", "feature.world_border.MixinWorldBorder", - "mod_compat.sodium.MixinChunkTracker", - "mod_compat.sodium.MixinRegionChunkRenderer", - "mod_compat.sodium.MixinRenderSectionManager", - "mod_compat.sodium.MixinSodiumWorldRenderer", + "mod_compat.create.IMixinDeployerHandler", + "mod_compat.create.IMixinDeployerMovementBehaviour", + "mod_compat.create.MixinAirCurrent", + "mod_compat.create.MixinAirFlowParticle", + "mod_compat.create.MixinBeltMovementHandler", + "mod_compat.create.MixinContraption", + "mod_compat.create.MixinContraptionCollider", + "mod_compat.create.MixinEntityLauncher", + "mod_compat.create.MixinRedstoneLinkNetworkHandler", + "mod_compat.create.MixinSharedDepotBlockMethods", + "mod_compat.create.accessors.Matrix3dAccessor", + "mod_compat.create.accessors.OutlineParamsAccessor", + "mod_compat.create.behaviour.MixinBlockBreakingMovementBehaviour", + "mod_compat.create.behaviour.MixinFilteringBehaviour", + "mod_compat.create.behaviour.MixinLinkBehaviour", + "mod_compat.create.behaviour.MixinScrollValueBehaviour", + "mod_compat.create.behaviour.MixinSidedFilteringBehaviour", + "mod_compat.create.block.MixinCrushingWheelBlock", + "mod_compat.create.block.MixinEjectorBlock", + "mod_compat.create.block.MixinRedstoneContactBlock", + "mod_compat.create.block.MixinStickerBlock", + "mod_compat.create.blockentity.IMixinMechanicalBearingTileEntity", + "mod_compat.create.blockentity.MixinCrushingWheelControllerTileEntity", + "mod_compat.create.blockentity.MixinEjectorTileEntity", + "mod_compat.create.blockentity.MixinEncasedFanTileEntity", + "mod_compat.create.entity.MixinAbstractContraptionEntity", + "mod_compat.create.entity.MixinCarriageContraptionEntity", + "mod_compat.create.entity.MixinControlledContraptionEntity", + "mod_compat.create.entity.MixinSeatEntity", + "mod_compat.create.packets.MixinControlsInputPacket", + "mod_compat.create.packets.MixinCurvedTrackDestroyPacket", + "mod_compat.create.packets.MixinSuperGlueRemovalPacket", + "mod_compat.create.packets.MixinTileEntityConfigurationPacket", + "mod_compat.create.packets.MixinTrainRelocationPacket", + "mod_compat.create.pr.MixinSeatBlock", + "mod_compat.create_big_cannons.MixinPitchOrientedContraptionEntity", + "mod_compat.reachentityattributes.MixinReachEntityAttributes", "server.MixinMinecraftServer", "server.MixinPlayerList", "server.command.MixinCommands", @@ -58,7 +99,11 @@ "world.chunk.MixinLevelChunk", "world.entity.MixinPlayer", "world.entity.projectile.ProjectileUtilMixin", - "world.level.MixinLevel" + "world.level.MixinBlockCollisions", + "world.level.MixinLevel", + "world.level.chunk.MixinChunkGenerator", + "world.level.levelgen.MixinFlatLevelSource", + "world.level.levelgen.MixinNoiseBasedChunkGenerator" ], "client": [ "accessors.client.multiplayer.ClientLevelAccessor", @@ -67,9 +112,9 @@ "accessors.client.render.ViewAreaAccessor", "accessors.client.render.chunk.RenderChunkAccessor", "accessors.client.world.ClientChunkCacheStorageAccessor", - "client.gui.screens.MixinConnectScreen", "client.MixinCamera", "client.MixinMinecraft", + "client.gui.screens.MixinConnectScreen", "client.multiplayer.MixinClientPacketListener", "client.player.MixinLocalPlayer", "client.player.MixinPlayer", @@ -77,6 +122,7 @@ "client.renderer.MixinLevelRenderer", "client.world.MixinClientChunkCache", "client.world.MixinClientLevel", + "feature.block_tint.MixinClientLevel", "feature.commands.MixinClientSuggestionProvider", "feature.fix_render_chunk_sorting.MixinRenderChunk", "feature.fluid_camera_fix.MixinCamera", @@ -94,14 +140,37 @@ "feature.transform_particles.MixinLevelRenderer", "feature.transform_particles.MixinParticle", "feature.vs2_alpha_hud.MixinGui", + "mod_compat.create.client.MixinAABBOutline", + "mod_compat.create.client.MixinBlockClusterOutline", + "mod_compat.create.client.MixinCarriageContraptionInstance", + "mod_compat.create.client.MixinCogwheelBlockItem", + "mod_compat.create.client.MixinCogwheelBlockItemHitOnShaft", + "mod_compat.create.client.MixinContraptionRenderDispatcher", + "mod_compat.create.client.MixinContraptionRenderInfo", + "mod_compat.create.client.MixinElevatorControlsHandler", + "mod_compat.create.client.MixinFilteringRenderer", + "mod_compat.create.client.MixinGhostBlockRenderer", + "mod_compat.create.client.MixinLinkRenderer", + "mod_compat.create.client.MixinMinecartInstance", + "mod_compat.create.client.MixinMultiplePlacementHelpers", + "mod_compat.create.client.MixinOrientedContraptionEntity", + "mod_compat.create.client.MixinOutline", + "mod_compat.create.client.MixinPlacementHelpers", + "mod_compat.create.client.MixinSoundScapes", + "mod_compat.create.client.MixinTileEntityRenderHelper", + "mod_compat.create.client.MixinTrackBlockOutline", + "mod_compat.create.client.MixinTrainRelocator", "mod_compat.flywheel.InstancingEngineAccessor", "mod_compat.flywheel.MixinBlockEntityInstanceManager", "mod_compat.flywheel.MixinInstanceManager", "mod_compat.flywheel.MixinInstanceWorld", "mod_compat.flywheel.MixinInstancingEngine", - "mod_compat.optifine.MixinViewAreaOptifine", "mod_compat.optifine.RenderChunkInfoAccessorOptifine", "mod_compat.optifine_vanilla.MixinLevelRenderer", + "mod_compat.sodium.MixinChunkTracker", + "mod_compat.sodium.MixinRegionChunkRenderer", + "mod_compat.sodium.MixinRenderSectionManager", + "mod_compat.sodium.MixinSodiumWorldRenderer", "mod_compat.sound_physics_remastered.MixinSoundPhysics", "mod_compat.vanilla_renderer.MixinLevelRendererVanilla", "mod_compat.vanilla_renderer.MixinViewAreaVanilla", diff --git a/fabric/build.gradle b/fabric/build.gradle index d6f119231..2ac0f49cc 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -25,7 +25,7 @@ loom { } dependencies { - include(annotationProcessor(implementation("com.github.LlamaLad7:MixinExtras:0.1.1"))) + include(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:0.2.0"))) modImplementation("net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}") @@ -37,11 +37,12 @@ dependencies { } // Depend on the fabric kotlin mod - include(modImplementation("net.fabricmc:fabric-language-kotlin:1.8.5+kotlin.1.7.20")) - include(modImplementation("me.shedaniel.cloth:cloth-config-fabric:11.0.99")) + include(modImplementation("net.fabricmc:fabric-language-kotlin:${kotlin_fabric_version}")) + include(modImplementation("me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}")) - modCompileOnly("maven.modrinth:sodium:mc1.20-0.4.10") - modImplementation("maven.modrinth:modmenu:7.1.0") + modImplementation("maven.modrinth:sodium:${sodium_version}") + modRuntimeOnly("maven.modrinth:indium:${indium_version}") + modImplementation("maven.modrinth:modmenu:${modmenu_version}") // Depend on the fabric API modImplementation("net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}") @@ -51,27 +52,42 @@ dependencies { exclude module: "netty-buffer" exclude module: "fastutil" exclude module: "kotlin-stdlib-jdk8" - exclude group: "com.google.guava" } // Shade vs-core shadowCommon("org.valkyrienskies.core:impl:${rootProject.vs_core_version}") { exclude module: "netty-buffer" exclude module: "fastutil" exclude module: "kotlin-stdlib-jdk8" // Don't shade kotlin-stdlib-jdk8, even though vs-core depends on it +<<<<<<<<< Temporary merge branch 1 exclude group: "com.google.guava" } // CC Restitched - // modImplementation("curse.maven:cc-restitched-462672:3908334") + modImplementation("curse.maven:cc-restitched-462672:3908334") +========= + exclude module: "jsonschema.module.addon" + } + + // CC Restitched + //modImplementation("curse.maven:cc-tweaked-282001:${cc_tweaked_version}") // Create compat - modImplementation("com.simibubi.create:create-fabric-${minecraft_version}:${create_fabric_version}") - // modImplementation("com.jozufozu.flywheel:flywheel-fabric-${minecraft_version}:0.6.9-4") + modImplementation("com.simibubi.create:create-fabric-${minecraft_version}:${create_fabric_version}") { + exclude group: 'com.github.AlphaMode', module: 'fakeconfigtoml' + } + modImplementation("com.jozufozu.flywheel:flywheel-fabric-${minecraft_version}:${flywheel_version_fabric}") modImplementation("com.tterrag.registrate_fabric:Registrate:${registrate_version}") - // modImplementation("io.github.fabricators_of_create.Porting-Lib:porting-lib:${port_lib_version}") - // modImplementation("net.minecraftforge:forgeconfigapiport-fabric:${forge_config_api_port_version}") - // modImplementation("com.jamieswhiteshirt:reach-entity-attributes:${reach_entity_attributes_version}") - // modImplementation("io.github.tropheusj:milk-lib:${milk_lib_version}") + + //modImplementation("io.github.fabricators_of_create.Porting-Lib:Porting-Lib:$port_lib_version") + for (String module in port_lib_modules.split(",")) { + modImplementation("io.github.fabricators_of_create.Porting-Lib:$module:$port_lib_version") + } + + //modImplementation("me.alphamode:ForgeTags:${forge_tags_version}") + modImplementation("net.minecraftforge:forgeconfigapiport-fabric:${forge_config_api_port_version}") + modImplementation("com.jamieswhiteshirt:reach-entity-attributes:${reach_entity_attributes_version}") + modImplementation("dev.cafeteria:fake-player-api:${fake_player_api_version}") + modImplementation("io.github.tropheusj:milk-lib:${milk_lib_version}") } // Copy the VS common access widener to the generated resources folder @@ -103,7 +119,7 @@ processResources { shadowJar { configurations = [project.configurations.shadowCommon] - classifier "dev-shadow" + archiveClassifier.set "dev-shadow" duplicatesStrategy DuplicatesStrategy.EXCLUDE // Ignore duplicate valkyrienskies-common.accesswidener files dependencies { exclude(dependency("org.jetbrains.kotlin:.*:.*")) // Don't shade kotlin! @@ -115,16 +131,17 @@ shadowJar { remapJar { input.set shadowJar.archiveFile dependsOn shadowJar - classifier null + archiveClassifier.set null duplicatesStrategy DuplicatesStrategy.EXCLUDE // Ignore duplicate valkyrienskies-common.accesswidener files } jar { - classifier "dev" + archiveClassifier.set "dev" duplicatesStrategy DuplicatesStrategy.EXCLUDE // Ignore duplicate valkyrienskies-common.accesswidener files } sourcesJar { + dependsOn "copyAccessWidener" duplicatesStrategy DuplicatesStrategy.EXCLUDE // Ignore duplicate valkyrienskies-common.accesswidener files def commonSources = project(":common").sourcesJar dependsOn commonSources diff --git a/fabric/gradle.properties b/fabric/gradle.properties index bc72e69e3..765de32ce 100644 --- a/fabric/gradle.properties +++ b/fabric/gradle.properties @@ -1,16 +1,41 @@ loader_platform=Fabric -create_version=0.5.1-c-build.1110+mc1.20.1 -# https://github.com/Fabricators-of-Create/Create/blob/mc1.18/fabric/dev/gradle.properties -config_api_id=4143545 -forge_config_api_port_version=4.2.10 -# https://maven.tterrag.com/com/jozufozu/flywheel/Flywheel-Fabric -flywheel_version=0.6.9-4 +create_version=0.5.1-c-build.1160+mc1.19.2 +# https://github.com/Fabricators-of-Create/Create/blob/4724359545de070788221dbb6387c31e582e9d45/gradle.properties#L24 +config_api_id=4583000 +# https://github.com/Fabricators-of-Create/Create/blob/4724359545de070788221dbb6387c31e582e9d45/gradle.properties#L25 +forge_config_api_port_version=4.2.9 +# https://github.com/CafeteriaGuild/fake-player-api/blob/1.19/gradle.properties +fake_player_api_version=0.6.0 +# https://github.com/JamiesWhiteShirt/reach-entity-attributes/tags reach_entity_attributes_version=2.4.0 -registrate_version=1.3.61-MC1.20 +# https://github.com/Fabricators-of-Create/Create/blob/4724359545de070788221dbb6387c31e582e9d45/gradle.properties#L32C14-L32C14 +registrate_version=1.3.62-MC1.20.1 + +forge_tags_version=2.1 +# https://github.com/Fabricators-of-Create/Create/blob/4724359545de070788221dbb6387c31e582e9d45/gradle.properties#L33 milk_lib_version=1.2.60 -port_lib_version=2.1.1056+1.20 +# https://github.com/Fabricators-of-Create/Create/blob/4724359545de070788221dbb6387c31e582e9d45/gradle.properties#L35 +port_lib_version=2.1.1127+1.20 +port_lib_modules = accessors,base,entity,extensions,fake_players,networking,obj_loader,tags,transfer,models,tool_actions,client_events,brewing night_config_core_version=3.6.3 night_config_toml_version=3.6.3 jsr305_version=3.0.2 # https://modrinth.com/mod/no-indium/ -no_indium_version=1.1.0+1.19 +no_indium_version=1.1.0+1.20 + +#https://modrinth.com/mod/sodium/versions +sodium_version = mc1.20-0.4.10 + +# https://modrinth.com/mod/cc-tweaked/version/Uq4DlqWv +cc_tweaked_version = 1.109.0 + +kotlin_fabric_version = 1.10.10+kotlin.1.9.10 + +# https://modrinth.com/mod/indium/version/1.0.9+mc1.19.2 +indium_version = 1.0.21+mc1.20.1 + +# https://linkie.shedaniel.me/dependencies?loader=fabric&version=1.19.2 +modmenu_version = 7.1.0 + +# https://linkie.shedaniel.me/dependencies?loader=fabric&version=1.19.2 +cloth_config_version = 11.1.106 diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/ValkyrienFabricMixinConfigPlugin.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/ValkyrienFabricMixinConfigPlugin.java deleted file mode 100644 index ae06dacd8..000000000 --- a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/ValkyrienFabricMixinConfigPlugin.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.valkyrienskies.mod.fabric.mixin; - -import com.llamalad7.mixinextras.MixinExtrasBootstrap; -import java.util.List; -import java.util.Set; -import org.objectweb.asm.tree.ClassNode; -import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; -import org.spongepowered.asm.mixin.extensibility.IMixinInfo; - -/** - * For now, just using this class as an abusive early entrypoint to run the updater - */ -public class ValkyrienFabricMixinConfigPlugin implements IMixinConfigPlugin { - - @Override - public void onLoad(final String s) { - MixinExtrasBootstrap.init(); - } - - @Override - public String getRefMapperConfig() { - return null; - } - - @Override - public boolean shouldApplyMixin(final String s, final String s1) { - return true; - } - - @Override - public void acceptTargets(final Set set, final Set set1) { - - } - - @Override - public List getMixins() { - return null; - } - - @Override - public void preApply(final String s, final ClassNode classNode, final String s1, final IMixinInfo iMixinInfo) { - - } - - @Override - public void postApply(final String s, final ClassNode classNode, final String s1, final IMixinInfo iMixinInfo) { - - } -} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinSpeakerPosition.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinSpeakerPosition.java index 22202c555..046ea6751 100644 --- a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinSpeakerPosition.java +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinSpeakerPosition.java @@ -1,50 +1,49 @@ -package org.valkyrienskies.mod.fabric.mixin.compat.cc_restitched; - -/* -import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Pseudo; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.valkyrienskies.core.api.ships.LoadedShip; -import org.valkyrienskies.core.api.ships.Ship; -import org.valkyrienskies.mod.common.VSGameUtilsKt; - -@Pseudo -@Mixin(SpeakerPosition.class) -public abstract class MixinSpeakerPosition { - @Shadow - public abstract Level level(); - - @Inject(method = "position", at = @At("RETURN"), remap = false, cancellable = true) - public void ValkyrienSkies2$position(final CallbackInfoReturnable cir) { - final Vec3 pos = cir.getReturnValue(); - final LoadedShip ship = VSGameUtilsKt.getShipObjectManagingPos(level(), pos.x, pos.y, pos.z); - if (ship != null) { - cir.setReturnValue(VSGameUtilsKt.toWorldCoordinates(level(), pos)); - } - } - - @Redirect( - method = "withinDistance", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/phys/Vec3;distanceToSqr(Lnet/minecraft/world/phys/Vec3;)D" - ) - ) - public double ValkyrienSkies$distanceToSqr(final Vec3 instance, final Vec3 d) { - final Ship ship = VSGameUtilsKt.getShipManagingPos(level(), instance); - if (ship != null) { - return VSGameUtilsKt.squaredDistanceBetweenInclShips(level(), instance.x, instance.y, instance.z, d.x, d.y, - d.z); - } - - return instance.distanceToSqr(d); - } -} -*/ +//package org.valkyrienskies.mod.fabric.mixin.compat.cc_restitched; +// +// +//import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.phys.Vec3; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Pseudo; +//import org.spongepowered.asm.mixin.Shadow; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.Inject; +//import org.spongepowered.asm.mixin.injection.Redirect; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +//import org.valkyrienskies.core.api.ships.LoadedShip; +//import org.valkyrienskies.core.api.ships.Ship; +//import org.valkyrienskies.mod.common.VSGameUtilsKt; +// +//@Pseudo +//@Mixin(SpeakerPosition.class) +//public abstract class MixinSpeakerPosition { +// @Shadow +// public abstract Level level(); +// +// @Inject(method = "position", at = @At("RETURN"), remap = false, cancellable = true) +// public void ValkyrienSkies2$position(final CallbackInfoReturnable cir) { +// final Vec3 pos = cir.getReturnValue(); +// final LoadedShip ship = VSGameUtilsKt.getShipObjectManagingPos(level(), pos.x, pos.y, pos.z); +// if (ship != null) { +// cir.setReturnValue(VSGameUtilsKt.toWorldCoordinates(level(), pos)); +// } +// } +// +// @Redirect( +// method = "withinDistance", +// at = @At( +// value = "INVOKE", +// target = "Lnet/minecraft/world/phys/Vec3;distanceToSqr(Lnet/minecraft/world/phys/Vec3;)D" +// ) +// ) +// public double ValkyrienSkies$distanceToSqr(final Vec3 instance, final Vec3 d) { +// final Ship ship = VSGameUtilsKt.getShipManagingPos(level(), instance); +// if (ship != null) { +// return VSGameUtilsKt.squaredDistanceBetweenInclShips(level(), instance.x, instance.y, instance.z, d.x, d.y, +// d.z); +// } +// +// return instance.distanceToSqr(d); +// } +//} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinTurtleBrain.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinTurtleBrain.java index 201b87997..d345e3103 100644 --- a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinTurtleBrain.java +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinTurtleBrain.java @@ -1,117 +1,115 @@ package org.valkyrienskies.mod.fabric.mixin.compat.cc_restitched; -/* -import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.turtle.core.TurtleBrain; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Vec3i; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import org.joml.Matrix4dc; -import org.joml.Vector3d; -import org.joml.Vector3dc; -import org.joml.primitives.AABBic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Pseudo; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.valkyrienskies.core.api.ships.Ship; -import org.valkyrienskies.mod.common.VSGameUtilsKt; -import org.valkyrienskies.mod.common.config.VSGameConfig; -import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; - -@Pseudo -@Mixin(TurtleBrain.class) -public abstract class MixinTurtleBrain { - @Shadow - public abstract TileTurtle getOwner(); - - @Shadow - public abstract void setOwner(TileTurtle owner); - - @Shadow - public abstract Level getLevel(); - - @ModifyVariable( - method = "Ldan200/computercraft/shared/turtle/core/TurtleBrain;teleportTo(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)Z", - at = @At(value = "HEAD"), - index = 2 - ) - private BlockPos ValkyrienSkies2$teleportToBlockPos(final BlockPos pos) { - final TileTurtle currentOwner = getOwner(); - final BlockPos oldPos = currentOwner.getBlockPos(); - final Level world = getLevel(); - - final Ship ship = VSGameUtilsKt.getShipManagingPos(world, oldPos); - if (ship != null) { - // THERE IS A SHIP - final Direction d = getNewDirection(ship, currentOwner.getDirection()); - if (!doesShipContainPoint(ship, pos)) { - // POSITION IS OUTSIDE THE SHIP'S AABB - - currentOwner.setDirection(d); - setOwner(currentOwner); - - if (!isShipScaled(ship)) { - // SHIP IS NOT SCALED - - return getWorldPosFromShipPos(ship, pos); - } else if (turtlesLeaveScaledShips()) { - // SHIP IS SCALED AND TURTLES CAN LEAVE SCALED SHIPS - - return getWorldPosFromShipPos(ship, pos); - } - } - } - return pos; - } - - // CUSTOM METHODS - - @Unique - private static Direction getNewDirection(final Ship ship, final Direction direction) { - final Matrix4dc matrix = ship.getShipToWorld(); - final Vec3i turtleDirectionVector = direction.getNormal(); - final Vector3d directionVec = - matrix.transformDirection(turtleDirectionVector.getX(), turtleDirectionVector.getY(), - turtleDirectionVector.getZ(), new Vector3d()); - final Direction dir = Direction.getNearest(directionVec.x, directionVec.y, directionVec.z); - - return dir; - } - - @Unique - private static boolean turtlesLeaveScaledShips() { - return VSGameConfig.SERVER.getComputerCraft().getCanTurtlesLeaveScaledShips(); - } - - @Unique - private static boolean isShipScaled(final Ship ship) { - final Vector3dc scale = ship.getTransform().getShipToWorldScaling(); - final Vector3dc normalScale = new Vector3d(1.000E+0, 1.000E+0, 1.000E+0); - return !scale.equals(normalScale); - } - - @Unique - private static boolean doesShipContainPoint(final Ship ship, final BlockPos pos) { - final AABBic shipAABB = ship.getShipAABB(); - - final AABB t = new AABB(shipAABB.maxX(), shipAABB.maxY(), shipAABB.maxZ(), shipAABB.minX(), shipAABB.minY(), - shipAABB.minZ()); - return t.intersects(new AABB(pos)); - } - - @Unique - private static BlockPos getWorldPosFromShipPos(final Ship ship, final BlockPos pos) { - final Vec3 tPos = VectorConversionsMCKt.toMinecraft( - VSGameUtilsKt.toWorldCoordinates(ship, pos.getX() + 0.5, pos.getY() + 0.5, - pos.getZ() + 0.5)); - final BlockPos newPos = new BlockPos(tPos.x, tPos.y, tPos.z); - return newPos; - } -} -*/ +//import dan200.computercraft.shared.turtle.blocks.TurtleBlockEntity; +//import dan200.computercraft.shared.turtle.core.TurtleBrain; +//import net.minecraft.core.BlockPos; +//import net.minecraft.core.Direction; +//import net.minecraft.core.Vec3i; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.phys.AABB; +//import net.minecraft.world.phys.Vec3; +//import org.joml.Matrix4dc; +//import org.joml.Vector3d; +//import org.joml.Vector3dc; +//import org.joml.primitives.AABBic; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Pseudo; +//import org.spongepowered.asm.mixin.Shadow; +//import org.spongepowered.asm.mixin.Unique; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.ModifyVariable; +//import org.valkyrienskies.core.api.ships.Ship; +//import org.valkyrienskies.mod.common.VSGameUtilsKt; +//import org.valkyrienskies.mod.common.config.VSGameConfig; +//import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; +// +//@Pseudo +//@Mixin(TurtleBrain.class) +//public abstract class MixinTurtleBrain { +// @Shadow +// public abstract TurtleBlockEntity getOwner(); +// +// @Shadow +// public abstract void setOwner(TurtleBlockEntity owner); +// +// @Shadow +// public abstract Level getLevel(); +// +// @ModifyVariable( +// method = "Ldan200/computercraft/shared/turtle/core/TurtleBrain;teleportTo(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)Z", +// at = @At(value = "HEAD"), +// index = 2 +// ) +// private BlockPos ValkyrienSkies2$teleportToBlockPos(final BlockPos pos) { +// final TurtleBlockEntity currentOwner = getOwner(); +// final BlockPos oldPos = currentOwner.getBlockPos(); +// final Level world = getLevel(); +// +// final Ship ship = VSGameUtilsKt.getShipManagingPos(world, oldPos); +// if (ship != null) { +// // THERE IS A SHIP +// final Direction d = getNewDirection(ship, currentOwner.getDirection()); +// if (!doesShipContainPoint(ship, pos)) { +// // POSITION IS OUTSIDE THE SHIP'S AABB +// +// currentOwner.setDirection(d); +// setOwner(currentOwner); +// +// if (!isShipScaled(ship)) { +// // SHIP IS NOT SCALED +// +// return getWorldPosFromShipPos(ship, pos); +// } else if (turtlesLeaveScaledShips()) { +// // SHIP IS SCALED AND TURTLES CAN LEAVE SCALED SHIPS +// +// return getWorldPosFromShipPos(ship, pos); +// } +// } +// } +// return pos; +// } +// +// // CUSTOM METHODS +// +// @Unique +// private static Direction getNewDirection(final Ship ship, final Direction direction) { +// final Matrix4dc matrix = ship.getShipToWorld(); +// final Vec3i turtleDirectionVector = direction.getNormal(); +// final Vector3d directionVec = +// matrix.transformDirection(turtleDirectionVector.getX(), turtleDirectionVector.getY(), +// turtleDirectionVector.getZ(), new Vector3d()); +// final Direction dir = Direction.getNearest(directionVec.x, directionVec.y, directionVec.z); +// +// return dir; +// } +// +// @Unique +// private static boolean turtlesLeaveScaledShips() { +// return VSGameConfig.SERVER.getComputerCraft().getCanTurtlesLeaveScaledShips(); +// } +// +// @Unique +// private static boolean isShipScaled(final Ship ship) { +// final Vector3dc scale = ship.getTransform().getShipToWorldScaling(); +// final Vector3dc normalScale = new Vector3d(1.000E+0, 1.000E+0, 1.000E+0); +// return !scale.equals(normalScale); +// } +// +// @Unique +// private static boolean doesShipContainPoint(final Ship ship, final BlockPos pos) { +// final AABBic shipAABB = ship.getShipAABB(); +// +// final AABB t = new AABB(shipAABB.maxX(), shipAABB.maxY(), shipAABB.maxZ(), shipAABB.minX(), shipAABB.minY(), +// shipAABB.minZ()); +// return t.intersects(new AABB(pos)); +// } +// +// @Unique +// private static BlockPos getWorldPosFromShipPos(final Ship ship, final BlockPos pos) { +// final Vec3 tPos = VectorConversionsMCKt.toMinecraft( +// VSGameUtilsKt.toWorldCoordinates(ship, pos.getX() + 0.5, pos.getY() + 0.5, +// pos.getZ() + 0.5)); +// final BlockPos newPos = BlockPos.containing(tPos.x, tPos.y, tPos.z); +// return newPos; +// } +//} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinTurtleMoveCommand.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinTurtleMoveCommand.java index c9350f27b..45da38805 100644 --- a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinTurtleMoveCommand.java +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinTurtleMoveCommand.java @@ -1,59 +1,59 @@ package org.valkyrienskies.mod.fabric.mixin.compat.cc_restitched; -/* -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.shared.turtle.core.TurtleMoveCommand; -import dan200.computercraft.shared.turtle.core.TurtlePlayer; -import java.util.List; -import javax.annotation.Nonnull; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import org.joml.Vector3d; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Pseudo; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.valkyrienskies.core.api.ships.Ship; -import org.valkyrienskies.mod.common.VSGameUtilsKt; +// +//import dan200.computercraft.api.turtle.TurtleCommandResult; +//import dan200.computercraft.shared.turtle.core.TurtleMoveCommand; +//import dan200.computercraft.shared.turtle.core.TurtlePlayer; +//import java.util.List; +//import net.minecraft.core.BlockPos; +//import net.minecraft.server.level.ServerLevel; +//import net.minecraft.world.level.ChunkPos; +//import net.minecraft.world.level.Level; +//import org.joml.Vector3d; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Pseudo; +//import org.spongepowered.asm.mixin.Unique; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.Inject; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +//import org.valkyrienskies.core.api.ships.Ship; +//import org.valkyrienskies.mod.common.VSGameUtilsKt; +// +//@Pseudo +//@Mixin(TurtleMoveCommand.class) +//public abstract class MixinTurtleMoveCommand { +// @Inject(method = "canEnter", at = @At("RETURN"), cancellable = true) +// private static void ValkyrienSkies2$canEnter( +// TurtlePlayer turtlePlayer, ServerLevel world, BlockPos position, +// CallbackInfoReturnable cir) { +// if (cir.getReturnValue().isSuccess()) { +// final Ship ship = VSGameUtilsKt.getShipManagingPos(world, position); +// if (ship == null) { +// final Ship iShip = VSGameUtilsKt.getShipManagingPos(world, getShipPosFromWorldPos(world, position)); +// if (iShip != null) { +// cir.setReturnValue(TurtleCommandResult.failure("ship")); +// } +// } else { +// final ChunkPos chunk = world.getChunkAt(position).getPos(); +// if (!ship.getChunkClaim().contains(chunk.x, chunk.z)) { +// cir.setReturnValue(TurtleCommandResult.failure("out of ship")); +// } +// } +// } +// } +// +// //CUSTOM METHODS +// @Unique +// private static Vector3d getShipPosFromWorldPos(final Level world, final BlockPos position) { +// final List detectedShips = +// VSGameUtilsKt.transformToNearbyShipsAndWorld(world, position.getX() + 0.5, position.getY() + 0.5, +// position.getZ() + 0.5, 0.1); +// for (final Vector3d vec : detectedShips) { +// if (vec != null) { +// return vec; +// } +// } +// return new Vector3d(position.getX(), position.getY(), position.getZ()); +// } +//} -@Pseudo -@Mixin(TurtleMoveCommand.class) -public abstract class MixinTurtleMoveCommand { - @Inject(method = "canEnter", at = @At("RETURN"), cancellable = true) - private static void ValkyrienSkies2$canEnter( - final TurtlePlayer turtlePlayer, final Level world, @Nonnull final BlockPos position, - final CallbackInfoReturnable cir) { - if (cir.getReturnValue().isSuccess()) { - final Ship ship = VSGameUtilsKt.getShipManagingPos(world, position); - if (ship == null) { - final Ship iShip = VSGameUtilsKt.getShipManagingPos(world, getShipPosFromWorldPos(world, position)); - if (iShip != null) { - cir.setReturnValue(TurtleCommandResult.failure("ship")); - } - } else { - final ChunkPos chunk = world.getChunkAt(position).getPos(); - if (!ship.getChunkClaim().contains(chunk.x, chunk.z)) { - cir.setReturnValue(TurtleCommandResult.failure("out of ship")); - } - } - } - } - - //CUSTOM METHODS - @Unique - private static Vector3d getShipPosFromWorldPos(final Level world, final BlockPos position) { - final List detectedShips = - VSGameUtilsKt.transformToNearbyShipsAndWorld(world, position.getX() + 0.5, position.getY() + 0.5, - position.getZ() + 0.5, 0.1); - for (final Vector3d vec : detectedShips) { - if (vec != null) { - return vec; - } - } - return new Vector3d(position.getX(), position.getY(), position.getZ()); - } -} -*/ diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinWirelessNetwork.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinWirelessNetwork.java index 163030682..e6082e180 100644 --- a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinWirelessNetwork.java +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/cc_restitched/MixinWirelessNetwork.java @@ -1,48 +1,45 @@ package org.valkyrienskies.mod.fabric.mixin.compat.cc_restitched; -/* -import dan200.computercraft.api.network.IPacketReceiver; -import dan200.computercraft.api.network.IPacketSender; -import dan200.computercraft.api.network.Packet; -import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Pseudo; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.valkyrienskies.mod.common.VSGameUtilsKt; - -@Pseudo -@Mixin(WirelessNetwork.class) -public class MixinWirelessNetwork { - private static IPacketReceiver shipReceiver; - private static IPacketSender shipSender; - - @ModifyVariable(method = "tryTransmit", - at = @At(value = "STORE"), - name = "distanceSq", - remap = false - ) - private static double ValkyrienSkies2$distanceSq(final double original) { - final Vec3 posOnShip = shipReceiver.getPosition(); - final Vec3 posInWorld = shipSender.getPosition(); - - final double distance = - VSGameUtilsKt.squaredDistanceBetweenInclShips(shipReceiver.getLevel(), - posOnShip.x, posOnShip.y, posOnShip.z, - posInWorld.x, posInWorld.y, posInWorld.z); - - return distance; - } - - @Inject(at = @At("HEAD"), method = "tryTransmit", remap = false) - private static void ValkyrienSkies2$tryTransmit(final IPacketReceiver receiver, final Packet packet, - final double range, - final boolean interdimensional, final CallbackInfo ci) { - shipReceiver = receiver; - shipSender = packet.sender(); - } -} -*/ +//import dan200.computercraft.api.network.Packet; +//import dan200.computercraft.api.network.PacketReceiver; +//import dan200.computercraft.api.network.PacketSender; +//import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork; +//import net.minecraft.world.phys.Vec3; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Pseudo; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.Inject; +//import org.spongepowered.asm.mixin.injection.ModifyVariable; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//import org.valkyrienskies.mod.common.VSGameUtilsKt; +// +//@Pseudo +//@Mixin(WirelessNetwork.class) +//public class MixinWirelessNetwork { +// private static PacketReceiver shipReceiver; +// private static PacketSender shipSender; +// +// @ModifyVariable(method = "tryTransmit", +// at = @At(value = "STORE"), +// name = "distanceSq", +// remap = false +// ) +// private static double ValkyrienSkies2$distanceSq(final double original) { +// final Vec3 posOnShip = shipReceiver.getPosition(); +// final Vec3 posInWorld = shipSender.getPosition(); +// +// final double distance = +// VSGameUtilsKt.squaredDistanceBetweenInclShips(shipReceiver.getLevel(), +// posOnShip.x, posOnShip.y, posOnShip.z, +// posInWorld.x, posInWorld.y, posInWorld.z); +// +// return distance; +// } +// +// @Inject(at = @At("HEAD"), method = "tryTransmit", remap = false) +// private static void ValkyrienSkies2$tryTransmit(PacketReceiver receiver, Packet packet, double range, +// boolean interdimensional, CallbackInfo ci) { +// shipReceiver = receiver; +// shipSender = packet.sender(); +// } +//} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/Matrix3dAccessor.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/Matrix3dAccessor.java deleted file mode 100644 index d9068f096..000000000 --- a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/Matrix3dAccessor.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.valkyrienskies.mod.fabric.mixin.compat.create; - -/* -import com.simibubi.create.foundation.collision.Matrix3d; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Pseudo; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Pseudo -@Mixin(Matrix3d.class) -public interface Matrix3dAccessor { - @Accessor("m00") - double getM00(); - - @Accessor("m01") - double getM01(); - - @Accessor("m02") - double getM02(); - - @Accessor("m10") - double getM10(); - - @Accessor("m11") - double getM11(); - - @Accessor("m12") - double getM12(); - - @Accessor("m20") - double getM20(); - - @Accessor("m21") - double getM21(); - - @Accessor("m22") - double getM22(); -} -*/ diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinAbstractContraptionEntity.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinAbstractContraptionEntity.java deleted file mode 100644 index 0eef2152c..000000000 --- a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinAbstractContraptionEntity.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.valkyrienskies.mod.fabric.mixin.compat.create; - -/* -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.Level; -import org.jetbrains.annotations.NotNull; -import org.joml.Matrix3d; -import org.joml.Matrix4d; -import org.joml.Matrix4dc; -import org.joml.Vector3d; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Pseudo; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.valkyrienskies.core.api.ships.ContraptionWingProvider; -import org.valkyrienskies.core.api.ships.LoadedServerShip; -import org.valkyrienskies.core.api.ships.WingManager; -import org.valkyrienskies.mod.common.VSGameUtilsKt; -import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; -import org.valkyrienskies.mod.fabric.common.CreateConversionsKt; - -@Pseudo -@Mixin(AbstractContraptionEntity.class) -public abstract class MixinAbstractContraptionEntity implements ContraptionWingProvider { - - @Unique - private int wingGroupId = -1; - - @Override - public int getWingGroupId() { - return wingGroupId; - } - - @Override - public void setWingGroupId(final int wingGroupId) { - this.wingGroupId = wingGroupId; - } - - @Inject(method = "tick", at = @At("HEAD")) - private void postTick(final CallbackInfo ci) { - final AbstractContraptionEntity thisAsAbstractContraptionEntity = AbstractContraptionEntity.class.cast(this); - final Level level = thisAsAbstractContraptionEntity.level; - if (wingGroupId != -1 && level instanceof ServerLevel serverLevel) { - final LoadedServerShip ship = VSGameUtilsKt.getShipObjectManagingPos(serverLevel, - VectorConversionsMCKt.toJOML(thisAsAbstractContraptionEntity.position())); - if (ship != null) { - ship.getAttachment(WingManager.class) - .setWingGroupTransform(wingGroupId, computeContraptionWingTransform()); - } - } - } - - @NotNull - @Override - public Matrix4dc computeContraptionWingTransform() { - final AbstractContraptionEntity thisAsAbstractContraptionEntity = AbstractContraptionEntity.class.cast(this); - final Matrix3d rotationMatrix = - CreateConversionsKt.toJOML(thisAsAbstractContraptionEntity.getRotationState().asMatrix()); - final Vector3d pos = VectorConversionsMCKt.toJOML(thisAsAbstractContraptionEntity.position()); - return new Matrix4d(rotationMatrix).setTranslation(pos); - } -} -*/ diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinBlockBreakingKineticTileEntity.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinBlockBreakingKineticTileEntity.java new file mode 100644 index 000000000..ef2cb5122 --- /dev/null +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinBlockBreakingKineticTileEntity.java @@ -0,0 +1,66 @@ +package org.valkyrienskies.mod.fabric.mixin.compat.create; + +import com.simibubi.create.content.kinetics.base.BlockBreakingKineticBlockEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(BlockBreakingKineticBlockEntity.class) +public abstract class MixinBlockBreakingKineticTileEntity { + + @Shadow + protected abstract BlockPos getBreakingPos(); + + @Redirect( + method = "tick", + at = @At( + value = "INVOKE", + target = "Lcom/simibubi/create/content/kinetics/base/BlockBreakingKineticBlockEntity;getBreakingPos()Lnet/minecraft/core/BlockPos;" + ) + ) + private BlockPos getBreakingBlockPos(final BlockBreakingKineticBlockEntity self) { + final BlockPos orig = this.getBreakingPos(); + final Vec3 origin; + final Vec3 target; + final Ship ship = VSGameUtilsKt.getShipManagingPos(self.getLevel(), self.getBlockPos()); + + if (ship != null) { + origin = VectorConversionsMCKt.toMinecraft( + ship.getShipToWorld() + .transformPosition(VectorConversionsMCKt.toJOMLD(self.getBlockPos()).add(0.5, 0.5, 0.5)) + ); + target = VectorConversionsMCKt.toMinecraft( + ship.getShipToWorld().transformPosition(VectorConversionsMCKt.toJOMLD(orig).add(0.5, 0.5, 0.5)) + ); + } else { + origin = Vec3.atCenterOf(self.getBlockPos()); + target = Vec3.atCenterOf(orig); + } + + final Vec3 diff = target.subtract(origin); + final BlockHitResult result = self.getLevel().clip(new ClipContext( + origin.add(diff.scale(0.4)), + target.add(diff.scale(0.2)), + ClipContext.Block.COLLIDER, + ClipContext.Fluid.NONE, + null + )); + + if (result.getType() == HitResult.Type.MISS) { + return orig; + } + + return result.getBlockPos(); + } + +} + diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinBlocks.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinBlocks.java new file mode 100644 index 000000000..8585dd93a --- /dev/null +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinBlocks.java @@ -0,0 +1,62 @@ +package org.valkyrienskies.mod.fabric.mixin.compat.create; + +import com.simibubi.create.content.kinetics.millstone.MillstoneBlock; +import com.simibubi.create.content.logistics.chute.AbstractChuteBlock; +import com.simibubi.create.content.processing.basin.BasinBlock; +import java.util.Iterator; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(value = { + MillstoneBlock.class, + BasinBlock.class, + AbstractChuteBlock.class +}) +public class MixinBlocks { + + @Redirect( + method = "updateEntityAfterFallOn", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/Entity;blockPosition()Lnet/minecraft/core/BlockPos;" + ), + require = 0 + ) + protected BlockPos redirectBlockPosition(final Entity entity) { + final Iterator ships = + VSGameUtilsKt.getShipsIntersecting(entity.level(), entity.getBoundingBox()).iterator(); + if (ships.hasNext()) { + final Vector3d pos = ships.next().getWorldToShip() + .transformPosition(VectorConversionsMCKt.toJOML(entity.position())); + return BlockPos.containing(Math.floor(pos.x), Math.floor(pos.y), Math.floor(pos.z)); + } else { + return entity.blockPosition(); + } + } + + @Redirect( + method = "updateEntityAfterFallOn", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/Entity;position()Lnet/minecraft/world/phys/Vec3;" + ), + require = 0 + ) + Vec3 redirectPosition(final Entity entity) { + final Iterator ships = VSGameUtilsKt.getShipsIntersecting(entity.level(), entity.getBoundingBox()).iterator(); + if (ships.hasNext()) { + return VectorConversionsMCKt.toMinecraft(ships.next().getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(entity.position()))); + } else { + return entity.position(); + } + } + +} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinControlledContraptionEntity.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinControlledContraptionEntity.java new file mode 100644 index 000000000..7d2e49ff9 --- /dev/null +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/MixinControlledContraptionEntity.java @@ -0,0 +1,40 @@ +package org.valkyrienskies.mod.fabric.mixin.compat.create; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.bearing.BearingContraption; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import net.minecraft.core.Direction; +import net.minecraft.core.Vec3i; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.joml.Math; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ControlledContraptionEntity.class) +public abstract class MixinControlledContraptionEntity extends AbstractContraptionEntity { + public MixinControlledContraptionEntity(EntityType entityTypeIn, Level worldIn) { + super(entityTypeIn, worldIn); + } + + //Region start - fix actors in the center of a bearing contraption not triggering correctly (vanilla create bug) + @Shadow + protected float angleDelta; + + @Redirect(method = "shouldActorTrigger", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lcom/simibubi/create/content/contraptions/behaviour/MovementContext;motion:Lnet/minecraft/world/phys/Vec3;")) + private void redirectPutMotion(MovementContext instance, Vec3 value) { + BearingContraption bc = (BearingContraption) contraption; + Direction facing = bc.getFacing(); + Vec3i dir = facing.getNormal(); + + double scalar = Math.abs(angleDelta / 360.0) * Math.signum(dir.getX() + dir.getY() + dir.getZ()); + + instance.motion = new Vec3(Math.abs(dir.getX()), Math.abs(dir.getY()), Math.abs(dir.getZ())).scale(scalar); + } + //Region end +} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinContraptionHandlerClient.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinContraptionHandlerClient.java new file mode 100644 index 000000000..ec38248d9 --- /dev/null +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinContraptionHandlerClient.java @@ -0,0 +1,43 @@ +package org.valkyrienskies.mod.fabric.mixin.compat.create.client; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.ContraptionHandlerClient; +import net.minecraft.client.Minecraft; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.joml.primitives.AABBdc; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(ContraptionHandlerClient.class) +public class MixinContraptionHandlerClient { + // Fixes raytracing contraptions on ships + @WrapOperation(method = "rayTraceContraption", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/AbstractContraptionEntity;toLocalVector(Lnet/minecraft/world/phys/Vec3;F)Lnet/minecraft/world/phys/Vec3;")) + private static Vec3 wrapRayTraceContraptionToLocalVector( + final AbstractContraptionEntity instance, final Vec3 localVec, final float partialTicks, final Operation toLocalVector + ) { + final ClientShip clientShip = VSGameUtilsKt.getShipObjectManagingPos(Minecraft.getInstance().level, instance.getAnchorVec().x, instance.getAnchorVec().y, instance.getAnchorVec().z); + if (clientShip != null) { + final Vec3 newLocalVec = VectorConversionsMCKt.toMinecraft(clientShip.getRenderTransform().getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(localVec))); + return toLocalVector.call(instance, newLocalVec, partialTicks); + } + return toLocalVector.call(instance, localVec, partialTicks); + } + + // Fixes raytracing contraptions on ships + @WrapOperation(method = "rightClickingOnContraptionsGetsHandledLocally", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/AbstractContraptionEntity;getBoundingBox()Lnet/minecraft/world/phys/AABB;")) + private static AABB wrapRightClickingOnContraptionsGetsHandledLocallyGetBoundingBox(final AbstractContraptionEntity instance, final Operation getBoundingBox) { + final ClientShip clientShip = VSGameUtilsKt.getShipObjectManagingPos(Minecraft.getInstance().level, instance.getAnchorVec().x, instance.getAnchorVec().y, instance.getAnchorVec().z); + if (clientShip != null) { + final AABB original = getBoundingBox.call(instance); + final AABBdc modified = VectorConversionsMCKt.toJOML(original).transform(clientShip.getRenderTransform().getShipToWorld()); + return VectorConversionsMCKt.toMinecraft(modified); + } + return getBoundingBox.call(instance); + } +} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinContraptionRenderInfo.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinContraptionRenderInfo.java new file mode 100644 index 000000000..912c0a79d --- /dev/null +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinContraptionRenderInfo.java @@ -0,0 +1,26 @@ +package org.valkyrienskies.mod.fabric.mixin.compat.create.client; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.render.ContraptionRenderInfo; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.world.phys.AABB; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(ContraptionRenderInfo.class) +public class MixinContraptionRenderInfo { + + @Redirect( + at = @At( + value = "INVOKE", + target = "Lcom/simibubi/create/content/contraptions/AbstractContraptionEntity;getBoundingBoxForCulling()Lnet/minecraft/world/phys/AABB;" + ), + method = "beginFrame" + ) + private AABB redirectGetAABBForCulling(final AbstractContraptionEntity receiver) { + return VSGameUtilsKt.transformRenderAABBToWorld(((ClientLevel) receiver.level()), receiver.position(), + receiver.getBoundingBoxForCulling()); + } +} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinCullingBlockEntityIterator.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinCullingBlockEntityIterator.java new file mode 100644 index 000000000..60e8b7ecc --- /dev/null +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinCullingBlockEntityIterator.java @@ -0,0 +1,26 @@ +package org.valkyrienskies.mod.fabric.mixin.compat.create.client; + +import io.github.fabricators_of_create.porting_lib.block.CullingBlockEntityIterator; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.culling.Frustum; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(CullingBlockEntityIterator.class) +public abstract class MixinCullingBlockEntityIterator { + @Redirect(method = "nextCulled", at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/culling/Frustum;isVisible(Lnet/minecraft/world/phys/AABB;)Z") + ) + private boolean inject(final Frustum instance, final AABB arg) { + AABB newAABB = arg; + final Level level = Minecraft.getInstance().level; + if (level != null) { + newAABB = VSGameUtilsKt.transformAabbToWorld(level, arg); + } + return instance.isVisible(newAABB); + } +} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinFlwContraption.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinFlwContraption.java new file mode 100644 index 000000000..f7dfcb979 --- /dev/null +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinFlwContraption.java @@ -0,0 +1,60 @@ +package org.valkyrienskies.mod.fabric.mixin.compat.create.client; + +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.render.ContraptionRenderInfo; +import com.simibubi.create.content.contraptions.render.FlwContraption; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.AABB; +import org.joml.Matrix4f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.mod.common.VSClientGameUtils; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +@Mixin(FlwContraption.class) +public class MixinFlwContraption extends ContraptionRenderInfo { + + public MixinFlwContraption( + final Contraption contraption, + final VirtualRenderWorld renderWorld) { + super(contraption, renderWorld); + } + + @Inject(at = @At("HEAD"), method = "setupModelViewPartial", cancellable = true, remap = false) + private static void beforeSetupModelViewPartial(Matrix4f matrix, Matrix4f modelMatrix, + AbstractContraptionEntity entity, double camX, double camY, double camZ, float pt, CallbackInfo ci) { + + if (VSGameUtilsKt.getShipManaging(entity) instanceof final ClientShip ship) { + VSClientGameUtils.transformRenderWithShip(ship.getRenderTransform(), + matrix, + Mth.lerp(pt, entity.xOld, entity.getX()), + Mth.lerp(pt, entity.yOld, entity.getY()), + Mth.lerp(pt, entity.zOld, entity.getZ()), + camX, + camY, + camZ + ); + + matrix.mul(modelMatrix); + ci.cancel(); + } + } + + @Redirect( + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/phys/AABB;move(DDD)Lnet/minecraft/world/phys/AABB;" + ), + method = "beginFrame" + ) + private AABB transformLightboxToWorld(final AABB aabb, final double negCamX, final double negCamY, + final double negCamZ) { + return VSGameUtilsKt.transformAabbToWorld(this.contraption.entity.level(), aabb).move(negCamX, negCamY, negCamZ); + } +} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinSuperGlueSelectionHandler.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinSuperGlueSelectionHandler.java new file mode 100644 index 000000000..9375965f1 --- /dev/null +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinSuperGlueSelectionHandler.java @@ -0,0 +1,68 @@ +package org.valkyrienskies.mod.fabric.mixin.compat.create.client; + +import com.jamieswhiteshirt.reachentityattributes.ReachEntityAttributes; +import com.simibubi.create.content.contraptions.glue.SuperGlueSelectionHandler; +import com.simibubi.create.foundation.utility.RaycastHelper; +import java.util.Iterator; +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.joml.Matrix4d; +import org.joml.Quaterniond; +import org.joml.Vector3d; +import org.joml.primitives.AABBic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(SuperGlueSelectionHandler.class) +public abstract class MixinSuperGlueSelectionHandler { + @Unique + private Vec3 newTarget; + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/foundation/utility/RaycastHelper;getTraceOrigin(Lnet/minecraft/world/entity/player/Player;)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 redirectGetTraceOrigin(Player playerIn) { + Minecraft mc = Minecraft.getInstance(); + double range = ReachEntityAttributes.getReachDistance(playerIn, playerIn.isCreative() ? 5.0 : 4.5); // PlatformUtils.getReachDistance(playerIn) + 1; + Vec3 origin = RaycastHelper.getTraceOrigin(playerIn); + Vec3 target = RaycastHelper.getTraceTarget(playerIn, range, origin); + + + AABB searchAABB = new AABB(origin, target).inflate(0.25, 2, 0.25); + final Iterator ships = VSGameUtilsKt.getShipsIntersecting(playerIn.level(), searchAABB).iterator(); + + if (ships.hasNext()) { + Ship ship = ships.next(); + + Matrix4d world2Ship = (Matrix4d) ship.getTransform().getWorldToShip(); + AABBic shAABBi = ship.getShipAABB(); + AABB shipAABB = new AABB(shAABBi.minX(), shAABBi.minY(), shAABBi.minZ(), shAABBi.maxX(), shAABBi.maxY(), shAABBi.maxZ()); + + + origin = VectorConversionsMCKt.toMinecraft(world2Ship.transformPosition(VectorConversionsMCKt.toJOML(origin))); + target = VectorConversionsMCKt.toMinecraft(world2Ship.transformPosition(VectorConversionsMCKt.toJOML(target))); + + Quaterniond tempQuat = new Quaterniond(); + if (playerIn.getVehicle() != null && playerIn.getVehicle().getBoundingBox().intersects(shipAABB.inflate(20))) { + ship.getTransform().getWorldToShip().getNormalizedRotation(tempQuat); + tempQuat.invert(); + Vector3d offset = VectorConversionsMCKt.toJOML(target.subtract(origin)); + tempQuat.transform(offset); + target = origin.add(VectorConversionsMCKt.toMinecraft(offset)); + } + } + + newTarget = target; + return origin; + } + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/foundation/utility/RaycastHelper;getTraceTarget(Lnet/minecraft/world/entity/player/Player;DLnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 redirectGetTraceTarget(final Player playerIn, final double range, final Vec3 origin) { + return newTarget; + } +} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinValueBox.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinValueBox.java new file mode 100644 index 000000000..b946ce720 --- /dev/null +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/compat/create/client/MixinValueBox.java @@ -0,0 +1,25 @@ +package org.valkyrienskies.mod.fabric.mixin.compat.create.client; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.mod.common.VSClientGameUtils; + +@Mixin(ValueBox.class) +public class MixinValueBox { + + @Redirect( + method = "render", + at = @At( + value = "INVOKE", + target = "Lcom/mojang/blaze3d/vertex/PoseStack;translate(DDD)V" + ), + require = 0 + ) + public void redirectTranslate(final PoseStack instance, final double x, final double y, final double z) { + VSClientGameUtils.transformRenderIfInShipyard(instance, x, y, z); + } + +} diff --git a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/world/level/block/FireMixin.java b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/world/level/block/FireMixin.java index 638a8ad42..ca05d28ff 100644 --- a/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/world/level/block/FireMixin.java +++ b/fabric/src/main/java/org/valkyrienskies/mod/fabric/mixin/world/level/block/FireMixin.java @@ -30,9 +30,8 @@ public abstract class FireMixin { public static IntegerProperty AGE; @Inject(method = "tick", at = @At("TAIL")) - public void fireTickMixin(final BlockState state, final ServerLevel level, final BlockPos pos, - final RandomSource random, - final CallbackInfo ci) { + public void fireTickMixin(BlockState state, ServerLevel level, BlockPos pos, + RandomSource random, CallbackInfo ci) { if (isModifyingFireTick) { return; } diff --git a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ContraptionShipyardEntityHandlerFabric.kt b/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ContraptionShipyardEntityHandlerFabric.kt index 303d23d44..81b8f43ac 100644 --- a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ContraptionShipyardEntityHandlerFabric.kt +++ b/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ContraptionShipyardEntityHandlerFabric.kt @@ -1,7 +1,6 @@ package org.valkyrienskies.mod.fabric.common -/* -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity +import com.simibubi.create.content.contraptions.AbstractContraptionEntity import net.minecraft.core.BlockPos import net.minecraft.world.entity.Entity import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate @@ -39,4 +38,3 @@ object ContraptionShipyardEntityHandlerFabric: AbstractShipyardEntityHandler() { } } } - */ diff --git a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/CreateConversions.kt b/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/CreateConversions.kt deleted file mode 100644 index da12d1706..000000000 --- a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/CreateConversions.kt +++ /dev/null @@ -1,15 +0,0 @@ -package org.valkyrienskies.mod.fabric.common - -/* -import org.joml.Matrix3d -import org.valkyrienskies.mod.fabric.mixin.compat.create.Matrix3dAccessor - -fun com.simibubi.create.foundation.collision.Matrix3d.toJOML(): Matrix3d { - val accessor = this as Matrix3dAccessor - return Matrix3d( - accessor.m00, accessor.m01, accessor.m02, - accessor.m10, accessor.m11, accessor.m12, - accessor.m20, accessor.m21, accessor.m22 - ) -} -*/ diff --git a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt b/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt index 5379e98b4..e9762703c 100644 --- a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt +++ b/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt @@ -21,15 +21,18 @@ import net.minecraft.util.profiling.ProfilerFiller import net.minecraft.world.entity.EntityType import net.minecraft.world.entity.MobCategory import net.minecraft.world.item.BlockItem +import net.minecraft.world.item.CreativeModeTab import net.minecraft.world.item.Item import net.minecraft.world.item.Item.Properties import net.minecraft.world.level.block.Block import org.valkyrienskies.core.apigame.VSCoreFactory import org.valkyrienskies.mod.client.EmptyRenderer +import org.valkyrienskies.mod.client.VSPhysicsEntityRenderer import org.valkyrienskies.mod.common.ValkyrienSkiesMod import org.valkyrienskies.mod.common.block.TestChairBlock import org.valkyrienskies.mod.common.block.TestFlapBlock import org.valkyrienskies.mod.common.block.TestHingeBlock +import org.valkyrienskies.mod.common.block.TestSphereBlock import org.valkyrienskies.mod.common.block.TestWingBlock import org.valkyrienskies.mod.common.blockentity.TestHingeBlockEntity import org.valkyrienskies.mod.common.command.VSCommands @@ -38,7 +41,10 @@ import org.valkyrienskies.mod.common.config.VSEntityHandlerDataLoader import org.valkyrienskies.mod.common.config.VSGameConfig import org.valkyrienskies.mod.common.config.VSKeyBindings import org.valkyrienskies.mod.common.entity.ShipMountingEntity +import org.valkyrienskies.mod.common.entity.VSPhysicsEntity +import org.valkyrienskies.mod.common.entity.handling.VSEntityManager import org.valkyrienskies.mod.common.hooks.VSGameEvents +import org.valkyrienskies.mod.common.item.PhysicsEntityCreatorItem import org.valkyrienskies.mod.common.item.ShipAssemblerItem import org.valkyrienskies.mod.common.item.ShipCreatorItem import java.util.concurrent.CompletableFuture @@ -58,6 +64,7 @@ class ValkyrienSkiesModFabric : ModInitializer { ValkyrienSkiesMod.TEST_HINGE = TestHingeBlock ValkyrienSkiesMod.TEST_FLAP = TestFlapBlock ValkyrienSkiesMod.TEST_WING = TestWingBlock + ValkyrienSkiesMod.TEST_SPHERE = TestSphereBlock ValkyrienSkiesMod.SHIP_CREATOR_ITEM = ShipCreatorItem( Properties(), { 1.0 }, @@ -69,12 +76,22 @@ class ValkyrienSkiesModFabric : ModInitializer { { VSGameConfig.SERVER.miniShipSize }, { VSGameConfig.SERVER.minScaling } ) + ValkyrienSkiesMod.PHYSICS_ENTITY_CREATOR_ITEM = PhysicsEntityCreatorItem(Properties()) ValkyrienSkiesMod.SHIP_MOUNTING_ENTITY_TYPE = EntityType.Builder.of( ::ShipMountingEntity, MobCategory.MISC ).sized(.3f, .3f) .build(ResourceLocation(ValkyrienSkiesMod.MOD_ID, "ship_mounting_entity").toString()) + + ValkyrienSkiesMod.PHYSICS_ENTITY_TYPE = EntityType.Builder.of( + ::VSPhysicsEntity, + MobCategory.MISC + ).sized(.3f, .3f) + .updateInterval(1) + .clientTrackingRange(10) + .build(ResourceLocation(ValkyrienSkiesMod.MOD_ID, "vs_physics_entity").toString()) + ValkyrienSkiesMod.TEST_HINGE_BLOCK_ENTITY_TYPE = FabricBlockEntityTypeBuilder.create(::TestHingeBlockEntity, ValkyrienSkiesMod.TEST_HINGE).build() @@ -92,12 +109,13 @@ class ValkyrienSkiesModFabric : ModInitializer { if (isClient) onInitializeClient() ValkyrienSkiesMod.init(vsCore) - // VSEntityManager.registerContraptionHandler(ContraptionShipyardEntityHandlerFabric) + VSEntityManager.registerContraptionHandler(ContraptionShipyardEntityHandlerFabric) - ValkyrienSkiesMod.TEST_CHAIR_ITEM = registerBlockAndItem("test_chair", ValkyrienSkiesMod.TEST_CHAIR) - ValkyrienSkiesMod.TEST_HINGE_ITEM =registerBlockAndItem("test_hinge", ValkyrienSkiesMod.TEST_HINGE) - ValkyrienSkiesMod.TEST_FLAP_ITEM = registerBlockAndItem("test_flap", ValkyrienSkiesMod.TEST_FLAP) - ValkyrienSkiesMod.TEST_WING_ITEM = registerBlockAndItem("test_wing", ValkyrienSkiesMod.TEST_WING) + registerBlockAndItem("test_chair", ValkyrienSkiesMod.TEST_CHAIR) + registerBlockAndItem("test_hinge", ValkyrienSkiesMod.TEST_HINGE) + registerBlockAndItem("test_flap", ValkyrienSkiesMod.TEST_FLAP) + registerBlockAndItem("test_wing", ValkyrienSkiesMod.TEST_WING) + registerBlockAndItem("test_sphere", ValkyrienSkiesMod.TEST_SPHERE) Registry.register( BuiltInRegistries.ITEM, ResourceLocation(ValkyrienSkiesMod.MOD_ID, "ship_assembler"), ValkyrienSkiesMod.SHIP_ASSEMBLER_ITEM @@ -110,10 +128,18 @@ class ValkyrienSkiesModFabric : ModInitializer { BuiltInRegistries.ITEM, ResourceLocation(ValkyrienSkiesMod.MOD_ID, "ship_creator_smaller"), ValkyrienSkiesMod.SHIP_CREATOR_ITEM_SMALLER ) + Registry.register( + BuiltInRegistries.ITEM, ResourceLocation(ValkyrienSkiesMod.MOD_ID, "physics_entity_creator"), + ValkyrienSkiesMod.PHYSICS_ENTITY_CREATOR_ITEM + ) Registry.register( BuiltInRegistries.ENTITY_TYPE, ResourceLocation(ValkyrienSkiesMod.MOD_ID, "ship_mounting_entity"), ValkyrienSkiesMod.SHIP_MOUNTING_ENTITY_TYPE ) + Registry.register( + BuiltInRegistries.ENTITY_TYPE, ResourceLocation(ValkyrienSkiesMod.MOD_ID, "vs_physics_entity"), + ValkyrienSkiesMod.PHYSICS_ENTITY_TYPE + ) Registry.register( BuiltInRegistries.BLOCK_ENTITY_TYPE, ResourceLocation(ValkyrienSkiesMod.MOD_ID, "test_hinge_block_entity"), ValkyrienSkiesMod.TEST_HINGE_BLOCK_ENTITY_TYPE @@ -125,7 +151,7 @@ class ValkyrienSkiesModFabric : ModInitializer { ValkyrienSkiesMod.createCreativeTab() ) - CommandRegistrationCallback.EVENT.register { dispatcher, _, _ -> + CommandRegistrationCallback.EVENT.register { dispatcher ,d, _ -> VSCommands.registerServerCommands(dispatcher) } @@ -175,6 +201,14 @@ class ValkyrienSkiesModFabric : ModInitializer { ) } + EntityRendererRegistry.register( + ValkyrienSkiesMod.PHYSICS_ENTITY_TYPE + ) { context: Context -> + VSPhysicsEntityRenderer( + context + ) + } + VSKeyBindings.clientSetup { KeyBindingHelper.registerKeyBinding(it) } diff --git a/fabric/src/main/resources/valkyrienskies-fabric.mixins.json b/fabric/src/main/resources/valkyrienskies-fabric.mixins.json index d88663706..7fc83c134 100644 --- a/fabric/src/main/resources/valkyrienskies-fabric.mixins.json +++ b/fabric/src/main/resources/valkyrienskies-fabric.mixins.json @@ -2,17 +2,24 @@ "required": true, "package": "org.valkyrienskies.mod.fabric.mixin", "compatibilityLevel": "JAVA_8", - "plugin": "org.valkyrienskies.mod.fabric.mixin.ValkyrienFabricMixinConfigPlugin", "mixins": [ + "compat.create.MixinBlockBreakingKineticTileEntity", + "compat.create.MixinBlocks", + "compat.create.MixinControlledContraptionEntity", "compat.sodium.MixinRenderSectionManager", "feature.explosions.ClipContextMixin", - "feature.water_in_ships_entity.MixinEntity", "server.network.MixinServerGamePacketListenerImpl", "server.network.MixinServerPlayerGameMode", "world.level.block.FireMixin" ], "client": [ "client.render.MixinLevelRenderer", + "compat.create.client.MixinContraptionHandlerClient", + "compat.create.client.MixinContraptionRenderInfo", + "compat.create.client.MixinCullingBlockEntityIterator", + "compat.create.client.MixinFlwContraption", + "compat.create.client.MixinSuperGlueSelectionHandler", + "compat.create.client.MixinValueBox", "feature.duplicate_keybindings.KeyMappingAccessor", "feature.duplicate_keybindings.MixinKeyMapping" ], diff --git a/forge/build.gradle b/forge/build.gradle index 2b5184ba1..368b8faff 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -51,7 +51,8 @@ configurations { } dependencies { - include(forgeRuntimeLibrary(annotationProcessor(implementation("com.github.LlamaLad7:MixinExtras:0.1.1")))) + implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:0.2.0")) + implementation(include("io.github.llamalad7:mixinextras-forge:0.2.0")) forge "net.minecraftforge:forge:${rootProject.forge_version}" @@ -63,60 +64,66 @@ dependencies { transitive = false } - modImplementation("curse.maven:rubidium-574856:4573226") + //modCompileOnly("curse.maven:rubidium-574856:4024781") + modCompileOnly("maven.modrinth:embeddium:${embeddium_version}") // Create compat - modImplementation("com.simibubi.create:create-${minecraft_version}:${create_version}:all") { transitive = false } - modImplementation("com.jozufozu.flywheel:flywheel-forge-1.20:${flywheel_version}") + modImplementation("com.simibubi.create:create-${minecraft_version}:${create_version}:slim") { transitive = false } + modImplementation("com.jozufozu.flywheel:flywheel-forge-${minecraft_version}:${flywheel_version}") modImplementation("com.tterrag.registrate:Registrate:${registrate_version}") // CC Tweaked - // modCompileOnly("curse.maven:cc-tweaked-282001:4061947") + modCompileOnly("maven.modrinth:cc-tweaked:${cc_tweaked_version}") // TIS-3d - // modCompileOnly("curse.maven:tis3d-238603:3738437") - //modImplementation("curse.maven:tis3d-238603:3738437") - //modImplementation("curse.maven:markdownmanual-502485:3738124") + modCompileOnly("maven.modrinth:tis3d:${tis3d_version}") - // Add Kotlin for Forge. - forgeRuntimeLibrary('curse.maven:kotlinforforge-351264:4578885') + // Add Kotlin for Forge (3.12.0) + forgeRuntimeLibrary("maven.modrinth:kotlin-for-forge:${kotlin_version}") // Cloth for config - include(modImplementation("me.shedaniel.cloth:cloth-config-forge:11.0.99")) + include(modImplementation("me.shedaniel.cloth:cloth-config-forge:${cloth_config_version}")) // Shade vs-core - implementation("org.valkyrienskies.core:impl:${rootProject.vs_core_version}") + implementation("org.valkyrienskies.core:impl:${rootProject.vs_core_version}"){ + exclude group: 'org.joml', module: 'joml' + } forgeRuntimeLibrary shadowCommon("org.valkyrienskies.core:impl:${rootProject.vs_core_version}") { + exclude group: 'org.joml', module: 'joml' transitive = false - exclude group: "com.google.guava" } // region Manually include every single dependency of vs-core (total meme) forgeRuntimeLibrary include("org.valkyrienskies.core:api:${rootProject.vs_core_version}") { + exclude group: 'org.joml', module: 'joml' transitive = false - exclude group: "com.google.guava" } forgeRuntimeLibrary shadowCommon("org.valkyrienskies.core:api-game:${rootProject.vs_core_version}") { + exclude group: 'org.joml', module: 'joml' + transitive = false + } + + forgeRuntimeLibrary include("org.valkyrienskies.core:util:${rootProject.vs_core_version}") { + exclude group: 'org.joml', module: 'joml' transitive = false - exclude group: "com.google.guava" } - forgeRuntimeLibrary shadowCommon("org.valkyrienskies:physics_api_krunch:1.0.0+eb3ae45554") { + forgeRuntimeLibrary shadowCommon("org.valkyrienskies:physics_api_krunch:1.0.0+10c94b01e2") { + exclude group: 'org.joml', module: 'joml' transitive = false - exclude group: "com.google.guava" } - forgeRuntimeLibrary shadowCommon("org.valkyrienskies:physics_api:1.0.0+0b6f5db802") { + forgeRuntimeLibrary shadowCommon("org.valkyrienskies:physics_api:1.0.0+94304c13aa") { + exclude group: 'org.joml', module: 'joml' transitive = false - exclude group: "com.google.guava" } forgeRuntimeLibrary include("javax.inject:javax.inject:1") { transitive = false } // JOML for Math - forgeRuntimeLibrary include("org.joml:joml-primitives:1.10.0") { transitive = false } + forgeRuntimeLibrary include("org.joml:joml-primitives:1.10.0") // Apache Commons Math for Linear Programming forgeRuntimeLibrary include("org.apache.commons:commons-math3:3.6.1") { transitive = false } @@ -134,7 +141,6 @@ dependencies { forgeRuntimeLibrary include("com.networknt:json-schema-validator:1.0.71") { transitive = false } forgeRuntimeLibrary include("com.ethlo.time:itu:1.7.0") { transitive = false } - forgeRuntimeLibrary include("com.github.imifou:jsonschema-module-addon:1.2.1") { transitive = false } forgeRuntimeLibrary include("com.github.victools:jsonschema-module-jackson:4.25.0") { transitive = false } forgeRuntimeLibrary include("com.github.victools:jsonschema-generator:4.25.0") { transitive = false } forgeRuntimeLibrary include("com.fasterxml:classmate:1.5.1") { transitive = false } @@ -161,13 +167,13 @@ shadowJar { exclude "net/optifine/**" configurations = [project.configurations.shadowCommon] - classifier "dev-shadow" + archiveClassifier.set "dev-shadow" } remapJar { input.set shadowJar.archiveFile dependsOn shadowJar - classifier null + archiveClassifier.set null } compileKotlin { @@ -175,7 +181,7 @@ compileKotlin { } jar { - classifier "dev" + archiveClassifier.set "dev" } sourcesJar { diff --git a/forge/gradle.properties b/forge/gradle.properties index b858e6dd0..3efbace5d 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -1,7 +1,18 @@ loader_platform=Forge loom.platform=forge kotlin.stdlib.default.dependency=false +#Deps +kotlin_version = 3.12.0 +cloth_config_version = 8.3.103 + #Compat -create_version=0.5.1.d-9 -flywheel_version=0.6.9-4 -registrate_version=MC1.20-1.3.3 +# https://github.com/Creators-of-Create/Create/wiki/Depending-on-Create +create_version = 0.5.1.e-22 +flywheel_version = 0.6.10-7 +registrate_version = MC1.20-1.3.3 +cc_tweaked_version = 1.109.0 +#Extra +# https://modrinth.com/mod/tis3d/version/MC1.19.2-forge-1.7.4 +tis3d_version = MC1.20.1-forge-1.7.5 +# https://modrinth.com/mod/embeddium/versions +embeddium_version = 0.2.9+mc1.20.1 diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/ValkyrienForgeMixinConfigPlugin.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/ValkyrienForgeMixinConfigPlugin.java deleted file mode 100644 index f8ed1ff8c..000000000 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/ValkyrienForgeMixinConfigPlugin.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.valkyrienskies.mod.forge.mixin; - -import com.llamalad7.mixinextras.MixinExtrasBootstrap; -import java.util.List; -import java.util.Set; -import org.objectweb.asm.tree.ClassNode; -import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; -import org.spongepowered.asm.mixin.extensibility.IMixinInfo; - -/** - * For now, just using this class as an abusive early entrypoint to run the updater - */ -public class ValkyrienForgeMixinConfigPlugin implements IMixinConfigPlugin { - - @Override - public void onLoad(final String s) { - MixinExtrasBootstrap.init(); - } - - @Override - public String getRefMapperConfig() { - return null; - } - - @Override - public boolean shouldApplyMixin(final String s, final String s1) { - return true; - } - - @Override - public void acceptTargets(final Set set, final Set set1) { - - } - - @Override - public List getMixins() { - return null; - } - - @Override - public void preApply(final String s, final ClassNode classNode, final String s1, final IMixinInfo iMixinInfo) { - - } - - @Override - public void postApply(final String s, final ClassNode classNode, final String s1, final IMixinInfo iMixinInfo) { - - } -} diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinSpeakerPosition.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinSpeakerPosition.java index abb0e5e16..7b50b3865 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinSpeakerPosition.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinSpeakerPosition.java @@ -1,49 +1,47 @@ -package org.valkyrienskies.mod.forge.mixin.compat.cc_tweaked; - -/* -import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Pseudo; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.valkyrienskies.core.api.ships.Ship; -import org.valkyrienskies.mod.common.VSGameUtilsKt; - -@Pseudo -@Mixin(SpeakerPosition.class) -public abstract class MixinSpeakerPosition { - @Shadow - public abstract Level level(); - - @Inject(method = "position", at = @At("RETURN"), remap = false, cancellable = true) - public void ValkyrienSkies2$position(final CallbackInfoReturnable cir) { - final Vec3 pos = cir.getReturnValue(); - final Ship ship = VSGameUtilsKt.getShipObjectManagingPos(level(), pos.x, pos.y, pos.z); - if (ship != null) { - cir.setReturnValue(VSGameUtilsKt.toWorldCoordinates(level(), pos)); - } - } - - @Redirect( - method = "withinDistance", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/phys/Vec3;distanceToSqr(Lnet/minecraft/world/phys/Vec3;)D" - ) - ) - public double ValkyrienSkies$distanceToSqr(final Vec3 instance, final Vec3 d) { - final Ship ship = VSGameUtilsKt.getShipManagingPos(level(), instance); - if (ship != null) { - return VSGameUtilsKt.squaredDistanceBetweenInclShips(level(), instance.x, instance.y, instance.z, d.x, d.y, - d.z); - } - - return instance.distanceToSqr(d); - } -} -*/ +//package org.valkyrienskies.mod.forge.mixin.compat.cc_tweaked; +// +//import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.phys.Vec3; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Pseudo; +//import org.spongepowered.asm.mixin.Shadow; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.Inject; +//import org.spongepowered.asm.mixin.injection.Redirect; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +//import org.valkyrienskies.core.api.ships.Ship; +//import org.valkyrienskies.mod.common.VSGameUtilsKt; +// +//@Pseudo +//@Mixin(SpeakerPosition.class) +//public abstract class MixinSpeakerPosition { +// @Shadow +// public abstract Level level(); +// +// @Inject(method = "position", at = @At("RETURN"), remap = false, cancellable = true) +// public void ValkyrienSkies2$position(final CallbackInfoReturnable cir) { +// final Vec3 pos = cir.getReturnValue(); +// final Ship ship = VSGameUtilsKt.getShipObjectManagingPos(level(), pos.x, pos.y, pos.z); +// if (ship != null) { +// cir.setReturnValue(VSGameUtilsKt.toWorldCoordinates(level(), pos)); +// } +// } +// +// @Redirect( +// method = "withinDistance", +// at = @At( +// value = "INVOKE", +// target = "Lnet/minecraft/world/phys/Vec3;distanceToSqr(Lnet/minecraft/world/phys/Vec3;)D" +// ) +// ) +// public double ValkyrienSkies$distanceToSqr(final Vec3 instance, final Vec3 d) { +// final Ship ship = VSGameUtilsKt.getShipManagingPos(level(), instance); +// if (ship != null) { +// return VSGameUtilsKt.squaredDistanceBetweenInclShips(level(), instance.x, instance.y, instance.z, d.x, d.y, +// d.z); +// } +// +// return instance.distanceToSqr(d); +// } +//} diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinTurtleBrain.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinTurtleBrain.java index 9e19fae7a..b0b4da969 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinTurtleBrain.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinTurtleBrain.java @@ -1,118 +1,116 @@ -package org.valkyrienskies.mod.forge.mixin.compat.cc_tweaked; - -/* -import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.turtle.core.TurtleBrain; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Vec3i; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import org.joml.Matrix4dc; -import org.joml.Vector3d; -import org.joml.Vector3dc; -import org.joml.primitives.AABBic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Pseudo; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.valkyrienskies.core.api.ships.Ship; -import org.valkyrienskies.mod.common.VSGameUtilsKt; -import org.valkyrienskies.mod.common.config.VSGameConfig; -import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; - -@Pseudo -@Mixin(TurtleBrain.class) -public abstract class MixinTurtleBrain { - @Shadow - public abstract TileTurtle getOwner(); - - @Shadow - public abstract void setOwner(TileTurtle owner); - - @Shadow - public abstract Level getLevel(); - - @ModifyVariable( - method = "Ldan200/computercraft/shared/turtle/core/TurtleBrain;teleportTo(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)Z", - at = @At(value = "HEAD"), - index = 2, - remap = false - ) - private BlockPos ValkyrienSkies2$teleportToBlockPos(final BlockPos pos) { - final TileTurtle currentOwner = getOwner(); - final BlockPos oldPos = currentOwner.getAccess().getPosition(); - final Level world = getLevel(); - - final Ship ship = VSGameUtilsKt.getShipManagingPos(world, oldPos); - if (ship != null) { - // THERE IS A SHIP - final Direction d = getNewDirection(ship, currentOwner.getDirection()); - if (!doesShipContainPoint(ship, pos)) { - // POSITION IS OUTSIDE THE SHIP'S AABB - - currentOwner.setDirection(d); - setOwner(currentOwner); - - if (!isShipScaled(ship)) { - // SHIP IS NOT SCALED - - return getWorldPosFromShipPos(ship, pos); - } else if (turtlesLeaveScaledShips()) { - // SHIP IS SCALED AND TURTLES CAN LEAVE SCALED SHIPS - - return getWorldPosFromShipPos(ship, pos); - } - } - } - return pos; - } - - // CUSTOM METHODS - - @Unique - private static Direction getNewDirection(final Ship ship, final Direction direction) { - final Matrix4dc matrix = ship.getShipToWorld(); - final Vec3i turtleDirectionVector = direction.getNormal(); - final Vector3d directionVec = - matrix.transformDirection(turtleDirectionVector.getX(), turtleDirectionVector.getY(), - turtleDirectionVector.getZ(), new Vector3d()); - final Direction dir = Direction.getNearest(directionVec.x, directionVec.y, directionVec.z); - - return dir; - } - - @Unique - private static boolean turtlesLeaveScaledShips() { - return VSGameConfig.SERVER.getComputerCraft().getCanTurtlesLeaveScaledShips(); - } - - @Unique - private static boolean isShipScaled(final Ship ship) { - final Vector3dc scale = ship.getTransform().getShipToWorldScaling(); - final Vector3dc normalScale = new Vector3d(1.000E+0, 1.000E+0, 1.000E+0); - return !scale.equals(normalScale); - } - - @Unique - private static boolean doesShipContainPoint(final Ship ship, final BlockPos pos) { - final AABBic shipAABB = ship.getShipAABB(); - - final AABB t = new AABB(shipAABB.maxX(), shipAABB.maxY(), shipAABB.maxZ(), shipAABB.minX(), shipAABB.minY(), - shipAABB.minZ()); - return t.intersects(new AABB(pos)); - } - - @Unique - private static BlockPos getWorldPosFromShipPos(final Ship ship, final BlockPos pos) { - final Vec3 tPos = VectorConversionsMCKt.toMinecraft( - VSGameUtilsKt.toWorldCoordinates(ship, pos.getX() + 0.5, pos.getY() + 0.5, - pos.getZ() + 0.5)); - final BlockPos newPos = new BlockPos(tPos.x, tPos.y, tPos.z); - return newPos; - } -} -*/ +//package org.valkyrienskies.mod.forge.mixin.compat.cc_tweaked; +// +//import dan200.computercraft.shared.turtle.blocks.TurtleBlockEntity; +//import dan200.computercraft.shared.turtle.core.TurtleBrain; +//import net.minecraft.core.BlockPos; +//import net.minecraft.core.Direction; +//import net.minecraft.core.Vec3i; +//import net.minecraft.world.level.Level; +//import net.minecraft.world.phys.AABB; +//import net.minecraft.world.phys.Vec3; +//import org.joml.Matrix4dc; +//import org.joml.Vector3d; +//import org.joml.Vector3dc; +//import org.joml.primitives.AABBic; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Pseudo; +//import org.spongepowered.asm.mixin.Shadow; +//import org.spongepowered.asm.mixin.Unique; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.ModifyVariable; +//import org.valkyrienskies.core.api.ships.Ship; +//import org.valkyrienskies.mod.common.VSGameUtilsKt; +//import org.valkyrienskies.mod.common.config.VSGameConfig; +//import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; +// +//@Pseudo +//@Mixin(TurtleBrain.class) +//public abstract class MixinTurtleBrain { +// @Shadow +// public abstract TurtleBlockEntity getOwner(); +// +// @Shadow +// public abstract void setOwner(TurtleBlockEntity owner); +// +// @Shadow +// public abstract Level getLevel(); +// +// @ModifyVariable( +// method = "Ldan200/computercraft/shared/turtle/core/TurtleBrain;teleportTo(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)Z", +// at = @At(value = "HEAD"), +// index = 2, +// remap = false +// ) +// private BlockPos ValkyrienSkies2$teleportToBlockPos(final BlockPos pos) { +// final TurtleBlockEntity currentOwner = getOwner(); +// final BlockPos oldPos = currentOwner.getAccess().getPosition(); +// final Level world = getLevel(); +// +// final Ship ship = VSGameUtilsKt.getShipManagingPos(world, oldPos); +// if (ship != null) { +// // THERE IS A SHIP +// final Direction d = getNewDirection(ship, currentOwner.getDirection()); +// if (!doesShipContainPoint(ship, pos)) { +// // POSITION IS OUTSIDE THE SHIP'S AABB +// +// currentOwner.setDirection(d); +// setOwner(currentOwner); +// +// if (!isShipScaled(ship)) { +// // SHIP IS NOT SCALED +// +// return getWorldPosFromShipPos(ship, pos); +// } else if (turtlesLeaveScaledShips()) { +// // SHIP IS SCALED AND TURTLES CAN LEAVE SCALED SHIPS +// +// return getWorldPosFromShipPos(ship, pos); +// } +// } +// } +// return pos; +// } +// +// // CUSTOM METHODS +// +// @Unique +// private static Direction getNewDirection(final Ship ship, final Direction direction) { +// final Matrix4dc matrix = ship.getShipToWorld(); +// final Vec3i turtleDirectionVector = direction.getNormal(); +// final Vector3d directionVec = +// matrix.transformDirection(turtleDirectionVector.getX(), turtleDirectionVector.getY(), +// turtleDirectionVector.getZ(), new Vector3d()); +// final Direction dir = Direction.getNearest(directionVec.x, directionVec.y, directionVec.z); +// +// return dir; +// } +// +// @Unique +// private static boolean turtlesLeaveScaledShips() { +// return VSGameConfig.SERVER.getComputerCraft().getCanTurtlesLeaveScaledShips(); +// } +// +// @Unique +// private static boolean isShipScaled(final Ship ship) { +// final Vector3dc scale = ship.getTransform().getShipToWorldScaling(); +// final Vector3dc normalScale = new Vector3d(1.000E+0, 1.000E+0, 1.000E+0); +// return !scale.equals(normalScale); +// } +// +// @Unique +// private static boolean doesShipContainPoint(final Ship ship, final BlockPos pos) { +// final AABBic shipAABB = ship.getShipAABB(); +// +// final AABB t = new AABB(shipAABB.maxX(), shipAABB.maxY(), shipAABB.maxZ(), shipAABB.minX(), shipAABB.minY(), +// shipAABB.minZ()); +// return t.intersects(new AABB(pos)); +// } +// +// @Unique +// private static BlockPos getWorldPosFromShipPos(final Ship ship, final BlockPos pos) { +// final Vec3 tPos = VectorConversionsMCKt.toMinecraft( +// VSGameUtilsKt.toWorldCoordinates(ship, pos.getX() + 0.5, pos.getY() + 0.5, +// pos.getZ() + 0.5)); +// final BlockPos newPos = BlockPos.containing(tPos.x, tPos.y, tPos.z); +// return newPos; +// } +//} diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinTurtleMoveCommand.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinTurtleMoveCommand.java index d2f7d8d3f..422a245f4 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinTurtleMoveCommand.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinTurtleMoveCommand.java @@ -1,59 +1,58 @@ -package org.valkyrienskies.mod.forge.mixin.compat.cc_tweaked; - -/* -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.shared.turtle.core.TurtleMoveCommand; -import dan200.computercraft.shared.turtle.core.TurtlePlayer; -import java.util.List; -import javax.annotation.Nonnull; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import org.joml.Vector3d; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Pseudo; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.valkyrienskies.core.api.ships.Ship; -import org.valkyrienskies.mod.common.VSGameUtilsKt; - -@Pseudo -@Mixin(TurtleMoveCommand.class) -public abstract class MixinTurtleMoveCommand { - @Inject(method = "canEnter", at = @At("RETURN"), remap = false, cancellable = true) - private static void ValkyrienSkies2$canEnter( - final TurtlePlayer turtlePlayer, final Level world, @Nonnull final BlockPos position, - final CallbackInfoReturnable cir) { - if (cir.getReturnValue().isSuccess()) { - final Ship ship = VSGameUtilsKt.getShipManagingPos(world, position); - if (ship == null) { - final Ship iShip = VSGameUtilsKt.getShipManagingPos(world, getShipPosFromWorldPos(world, position)); - if (iShip != null) { - cir.setReturnValue(TurtleCommandResult.failure("ship")); - } - } else { - final ChunkPos chunk = world.getChunkAt(position).getPos(); - if (!ship.getChunkClaim().contains(chunk.x, chunk.z)) { - cir.setReturnValue(TurtleCommandResult.failure("out of ship")); - } - } - } - } - - //CUSTOM METHODS - @Unique - private static Vector3d getShipPosFromWorldPos(final Level world, final BlockPos position) { - final List detectedShips = - VSGameUtilsKt.transformToNearbyShipsAndWorld(world, position.getX() + 0.5, position.getY() + 0.5, - position.getZ() + 0.5, 0.1); - for (final Vector3d vec : detectedShips) { - if (vec != null) { - return vec; - } - } - return new Vector3d(position.getX(), position.getY(), position.getZ()); - } -} -*/ +//package org.valkyrienskies.mod.forge.mixin.compat.cc_tweaked; +// +//import dan200.computercraft.api.turtle.TurtleCommandResult; +//import dan200.computercraft.shared.turtle.core.TurtleMoveCommand; +//import dan200.computercraft.shared.turtle.core.TurtlePlayer; +//import java.util.List; +//import javax.annotation.Nonnull; +//import net.minecraft.core.BlockPos; +//import net.minecraft.world.level.ChunkPos; +//import net.minecraft.world.level.Level; +//import org.joml.Vector3d; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Pseudo; +//import org.spongepowered.asm.mixin.Unique; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.Inject; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +//import org.valkyrienskies.core.api.ships.Ship; +//import org.valkyrienskies.mod.common.VSGameUtilsKt; +// +//@Pseudo +//@Mixin(TurtleMoveCommand.class) +//public abstract class MixinTurtleMoveCommand { +// @Inject(method = "canEnter", at = @At("RETURN"), remap = false, cancellable = true) +// private static void ValkyrienSkies2$canEnter( +// final TurtlePlayer turtlePlayer, final Level world, @Nonnull final BlockPos position, +// final CallbackInfoReturnable cir) { +// if (cir.getReturnValue().isSuccess()) { +// final Ship ship = VSGameUtilsKt.getShipManagingPos(world, position); +// if (ship == null) { +// final Ship iShip = VSGameUtilsKt.getShipManagingPos(world, getShipPosFromWorldPos(world, position)); +// if (iShip != null) { +// cir.setReturnValue(TurtleCommandResult.failure("ship")); +// } +// } else { +// final ChunkPos chunk = world.getChunkAt(position).getPos(); +// if (!ship.getChunkClaim().contains(chunk.x, chunk.z)) { +// cir.setReturnValue(TurtleCommandResult.failure("out of ship")); +// } +// } +// } +// } +// +// //CUSTOM METHODS +// @Unique +// private static Vector3d getShipPosFromWorldPos(final Level world, final BlockPos position) { +// final List detectedShips = +// VSGameUtilsKt.transformToNearbyShipsAndWorld(world, position.getX() + 0.5, position.getY() + 0.5, +// position.getZ() + 0.5, 0.1); +// for (final Vector3d vec : detectedShips) { +// if (vec != null) { +// return vec; +// } +// } +// return new Vector3d(position.getX(), position.getY(), position.getZ()); +// } +//} +// diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinWirelessNetwork.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinWirelessNetwork.java index f406eae1e..1dbb0e7c1 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinWirelessNetwork.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/cc_tweaked/MixinWirelessNetwork.java @@ -1,43 +1,41 @@ -package org.valkyrienskies.mod.forge.mixin.compat.cc_tweaked; - -/* -import dan200.computercraft.api.network.IPacketReceiver; -import dan200.computercraft.api.network.IPacketSender; -import dan200.computercraft.api.network.Packet; -import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Pseudo; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.valkyrienskies.mod.common.VSGameUtilsKt; - -@Pseudo -@Mixin(WirelessNetwork.class) -public class MixinWirelessNetwork { - private static IPacketReceiver shipReceiver; - private static IPacketSender shipSender; - - @Redirect( - method = "tryTransmit", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/phys/Vec3;distanceToSqr(Lnet/minecraft/world/phys/Vec3;)D" - ) - ) - private static double ValkyrienSkies$distanceToSqr(final Vec3 instance, final Vec3 d) { - return VSGameUtilsKt.squaredDistanceBetweenInclShips(shipReceiver.getLevel(), instance.x, instance.y, - instance.z, d.x, d.y, d.z); - } - - @Inject(at = @At("HEAD"), method = "tryTransmit", remap = false) - private static void ValkyrienSkies2$tryTransmit(final IPacketReceiver receiver, final Packet packet, - final double range, - final boolean interdimensional, final CallbackInfo ci) { - shipReceiver = receiver; - shipSender = packet.sender(); - } -} -*/ +//package org.valkyrienskies.mod.forge.mixin.compat.cc_tweaked; +// +//import dan200.computercraft.api.network.Packet; +//import dan200.computercraft.api.network.PacketReceiver; +//import dan200.computercraft.api.network.PacketSender; +//import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork; +//import net.minecraft.world.phys.Vec3; +//import org.spongepowered.asm.mixin.Mixin; +//import org.spongepowered.asm.mixin.Pseudo; +//import org.spongepowered.asm.mixin.injection.At; +//import org.spongepowered.asm.mixin.injection.Inject; +//import org.spongepowered.asm.mixin.injection.Redirect; +//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//import org.valkyrienskies.mod.common.VSGameUtilsKt; +// +//@Pseudo +//@Mixin(WirelessNetwork.class) +//public class MixinWirelessNetwork { +// private static PacketReceiver shipReceiver; +// private static PacketSender shipSender; +// +// @Redirect( +// method = "tryTransmit", +// at = @At( +// value = "INVOKE", +// target = "Lnet/minecraft/world/phys/Vec3;distanceToSqr(Lnet/minecraft/world/phys/Vec3;)D" +// ) +// ) +// private static double ValkyrienSkies$distanceToSqr(final Vec3 instance, final Vec3 d) { +// return VSGameUtilsKt.squaredDistanceBetweenInclShips(shipReceiver.getLevel(), instance.x, instance.y, +// instance.z, d.x, d.y, d.z); +// } +// +// @Inject(at = @At("HEAD"), method = "tryTransmit", remap = false) +// private static void ValkyrienSkies2$tryTransmit(final PacketReceiver receiver, final Packet packet, +// final double range, +// final boolean interdimensional, final CallbackInfo ci) { +// shipReceiver = receiver; +// shipSender = packet.sender(); +// } +//} diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinAbstractContraptionEntity.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinAbstractContraptionEntity.java deleted file mode 100644 index aacce9751..000000000 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinAbstractContraptionEntity.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.valkyrienskies.mod.forge.mixin.compat.create; - -/* -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.Level; -import org.jetbrains.annotations.NotNull; -import org.joml.Matrix3d; -import org.joml.Matrix4d; -import org.joml.Matrix4dc; -import org.joml.Vector3d; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.valkyrienskies.core.api.ships.ContraptionWingProvider; -import org.valkyrienskies.core.api.ships.LoadedServerShip; -import org.valkyrienskies.core.api.ships.WingManager; -import org.valkyrienskies.mod.common.VSGameUtilsKt; -import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; -import org.valkyrienskies.mod.forge.common.CreateConversionsKt; - -@Mixin(AbstractContraptionEntity.class) -public abstract class MixinAbstractContraptionEntity implements ContraptionWingProvider { - - @Unique - private int wingGroupId = -1; - - @Override - public int getWingGroupId() { - return wingGroupId; - } - - @Override - public void setWingGroupId(final int wingGroupId) { - this.wingGroupId = wingGroupId; - } - - @Inject(method = "tick", at = @At("HEAD")) - private void postTick(final CallbackInfo ci) { - final AbstractContraptionEntity thisAsAbstractContraptionEntity = AbstractContraptionEntity.class.cast(this); - final Level level = thisAsAbstractContraptionEntity.level; - if (wingGroupId != -1 && level instanceof ServerLevel serverLevel) { - final LoadedServerShip ship = VSGameUtilsKt.getShipObjectManagingPos(serverLevel, - VectorConversionsMCKt.toJOML(thisAsAbstractContraptionEntity.position())); - ship.getAttachment(WingManager.class).setWingGroupTransform(wingGroupId, computeContraptionWingTransform()); - } - } - - @NotNull - @Override - public Matrix4dc computeContraptionWingTransform() { - final AbstractContraptionEntity thisAsAbstractContraptionEntity = AbstractContraptionEntity.class.cast(this); - final Matrix3d rotationMatrix = - CreateConversionsKt.toJOML(thisAsAbstractContraptionEntity.getRotationState().asMatrix()); - final Vector3d pos = VectorConversionsMCKt.toJOML(thisAsAbstractContraptionEntity.position()); - return new Matrix4d(rotationMatrix).setTranslation(pos); - } -} -*/ diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinBlockBreakingKineticTileEntity.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinBlockBreakingKineticTileEntity.java index 7aec0dc69..8a926d0fb 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinBlockBreakingKineticTileEntity.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinBlockBreakingKineticTileEntity.java @@ -1,7 +1,6 @@ package org.valkyrienskies.mod.forge.mixin.compat.create; -/* -import com.simibubi.create.content.contraptions.components.actors.BlockBreakingKineticTileEntity; +import com.simibubi.create.content.kinetics.base.BlockBreakingKineticBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.world.level.ClipContext; import net.minecraft.world.phys.BlockHitResult; @@ -15,7 +14,7 @@ import org.valkyrienskies.mod.common.VSGameUtilsKt; import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; -@Mixin(BlockBreakingKineticTileEntity.class) +@Mixin(BlockBreakingKineticBlockEntity.class) public abstract class MixinBlockBreakingKineticTileEntity { @Shadow @@ -25,10 +24,10 @@ public abstract class MixinBlockBreakingKineticTileEntity { method = "tick", at = @At( value = "INVOKE", - target = "Lcom/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity;getBreakingPos()Lnet/minecraft/core/BlockPos;" + target = "Lcom/simibubi/create/content/kinetics/base/BlockBreakingKineticBlockEntity;getBreakingPos()Lnet/minecraft/core/BlockPos;" ), remap = false ) - private BlockPos getBreakingBlockPos(final BlockBreakingKineticTileEntity self) { + private BlockPos getBreakingBlockPos(final BlockBreakingKineticBlockEntity self) { final BlockPos orig = this.getBreakingPos(); final Vec3 origin; final Vec3 target; @@ -64,4 +63,4 @@ private BlockPos getBreakingBlockPos(final BlockBreakingKineticTileEntity self) } } -*/ + diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinBlocks.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinBlocks.java index 52b7b1e79..8c33c3bd6 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinBlocks.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinBlocks.java @@ -1,9 +1,8 @@ package org.valkyrienskies.mod.forge.mixin.compat.create; -/* -import com.simibubi.create.content.contraptions.components.millstone.MillstoneBlock; -import com.simibubi.create.content.contraptions.processing.BasinBlock; -import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock; +import com.simibubi.create.content.kinetics.millstone.MillstoneBlock; +import com.simibubi.create.content.logistics.chute.AbstractChuteBlock; +import com.simibubi.create.content.processing.basin.BasinBlock; import java.util.Iterator; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; @@ -33,11 +32,11 @@ public class MixinBlocks { ) protected BlockPos redirectBlockPosition(final Entity entity) { final Iterator ships = - VSGameUtilsKt.getShipsIntersecting(entity.level, entity.getBoundingBox()).iterator(); + VSGameUtilsKt.getShipsIntersecting(entity.level(), entity.getBoundingBox()).iterator(); if (ships.hasNext()) { final Vector3d pos = ships.next().getWorldToShip() .transformPosition(VectorConversionsMCKt.toJOML(entity.position())); - return new BlockPos(Math.floor(pos.x), Math.floor(pos.y), Math.floor(pos.z)); + return BlockPos.containing(Math.floor(pos.x), Math.floor(pos.y), Math.floor(pos.z)); } else { return entity.blockPosition(); } @@ -53,7 +52,7 @@ protected BlockPos redirectBlockPosition(final Entity entity) { ) Vec3 redirectPosition(final Entity entity) { final Iterator ships = - VSGameUtilsKt.getShipsIntersecting(entity.level, entity.getBoundingBox()).iterator(); + VSGameUtilsKt.getShipsIntersecting(entity.level(), entity.getBoundingBox()).iterator(); if (ships.hasNext()) { return VectorConversionsMCKt.toMinecraft(ships.next().getWorldToShip() .transformPosition(VectorConversionsMCKt.toJOML(entity.position()))); @@ -63,4 +62,3 @@ Vec3 redirectPosition(final Entity entity) { } } -*/ diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinControlledContraptionEntity.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinControlledContraptionEntity.java new file mode 100644 index 000000000..9bfa2693e --- /dev/null +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/MixinControlledContraptionEntity.java @@ -0,0 +1,41 @@ +package org.valkyrienskies.mod.forge.mixin.compat.create; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.bearing.BearingContraption; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import net.minecraft.core.Direction; +import net.minecraft.core.Vec3i; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.joml.Math; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ControlledContraptionEntity.class) +public abstract class MixinControlledContraptionEntity extends AbstractContraptionEntity { + public MixinControlledContraptionEntity(EntityType entityTypeIn, Level worldIn) { + super(entityTypeIn, worldIn); + } + + //Region start - fix actors in the center of a bearing contraption not triggering correctly (vanilla create bug) + @Shadow + protected float angleDelta; + + @Redirect(method = "shouldActorTrigger", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lcom/simibubi/create/content/contraptions/behaviour/MovementContext;motion:Lnet/minecraft/world/phys/Vec3;"), + remap = false) + private void redirectPutMotion(MovementContext instance, Vec3 value) { + BearingContraption bc = (BearingContraption) contraption; + Direction facing = bc.getFacing(); + Vec3i dir = facing.getNormal(); + + double scalar = Math.abs(angleDelta / 360.0) * Math.signum(dir.getX() + dir.getY() + dir.getZ()); + + instance.motion = new Vec3(Math.abs(dir.getX()), Math.abs(dir.getY()), Math.abs(dir.getZ())).scale(scalar); + } + //Region end +} diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinContraptionHandlerClient.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinContraptionHandlerClient.java new file mode 100644 index 000000000..7d2797ece --- /dev/null +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinContraptionHandlerClient.java @@ -0,0 +1,43 @@ +package org.valkyrienskies.mod.forge.mixin.compat.create.client; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.ContraptionHandlerClient; +import net.minecraft.client.Minecraft; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.joml.primitives.AABBdc; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(ContraptionHandlerClient.class) +public class MixinContraptionHandlerClient { + // Fixes raytracing contraptions on ships + @WrapOperation(method = "rayTraceContraption", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/AbstractContraptionEntity;toLocalVector(Lnet/minecraft/world/phys/Vec3;F)Lnet/minecraft/world/phys/Vec3;"), remap = false) + private static Vec3 wrapRayTraceContraptionToLocalVector( + final AbstractContraptionEntity instance, final Vec3 localVec, final float partialTicks, final Operation toLocalVector + ) { + final ClientShip clientShip = VSGameUtilsKt.getShipObjectManagingPos(Minecraft.getInstance().level, instance.getAnchorVec().x, instance.getAnchorVec().y, instance.getAnchorVec().z); + if (clientShip != null) { + final Vec3 newLocalVec = VectorConversionsMCKt.toMinecraft(clientShip.getRenderTransform().getWorldToShip().transformPosition(VectorConversionsMCKt.toJOML(localVec))); + return toLocalVector.call(instance, newLocalVec, partialTicks); + } + return toLocalVector.call(instance, localVec, partialTicks); + } + + // Fixes raytracing contraptions on ships + @WrapOperation(method = "rightClickingOnContraptionsGetsHandledLocally", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/content/contraptions/AbstractContraptionEntity;getBoundingBox()Lnet/minecraft/world/phys/AABB;")) + private static AABB wrapRightClickingOnContraptionsGetsHandledLocallyGetBoundingBox(final AbstractContraptionEntity instance, final Operation getBoundingBox) { + final ClientShip clientShip = VSGameUtilsKt.getShipObjectManagingPos(Minecraft.getInstance().level, instance.getAnchorVec().x, instance.getAnchorVec().y, instance.getAnchorVec().z); + if (clientShip != null) { + final AABB original = getBoundingBox.call(instance); + final AABBdc modified = VectorConversionsMCKt.toJOML(original).transform(clientShip.getRenderTransform().getShipToWorld()); + return VectorConversionsMCKt.toMinecraft(modified); + } + return getBoundingBox.call(instance); + } +} diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinContraptionRenderInfo.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinContraptionRenderInfo.java index f6da6c505..b26c3021d 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinContraptionRenderInfo.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinContraptionRenderInfo.java @@ -1,8 +1,7 @@ package org.valkyrienskies.mod.forge.mixin.compat.create.client; -/* -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderInfo; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.render.ContraptionRenderInfo; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.phys.AABB; import org.spongepowered.asm.mixin.Mixin; @@ -12,17 +11,15 @@ @Mixin(ContraptionRenderInfo.class) public class MixinContraptionRenderInfo { - @Redirect( at = @At( value = "INVOKE", - target = "Lcom/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity;getBoundingBoxForCulling()Lnet/minecraft/world/phys/AABB;" + target = "Lcom/simibubi/create/content/contraptions/AbstractContraptionEntity;getBoundingBoxForCulling()Lnet/minecraft/world/phys/AABB;" ), method = "beginFrame" ) private AABB redirectGetAABBForCulling(final AbstractContraptionEntity receiver) { - return VSGameUtilsKt.transformRenderAABBToWorld(((ClientLevel) receiver.level), receiver.position(), + return VSGameUtilsKt.transformRenderAABBToWorld(((ClientLevel) receiver.level()), receiver.position(), receiver.getBoundingBoxForCulling()); } } -*/ diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinFlwContraption.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinFlwContraption.java index 9b4fd1575..61db03642 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinFlwContraption.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinFlwContraption.java @@ -1,14 +1,14 @@ package org.valkyrienskies.mod.forge.mixin.compat.create.client; -/* + import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.mojang.math.Matrix4f; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderInfo; -import com.simibubi.create.content.contraptions.components.structureMovement.render.FlwContraption; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.render.ContraptionRenderInfo; +import com.simibubi.create.content.contraptions.render.FlwContraption; import net.minecraft.util.Mth; import net.minecraft.world.phys.AABB; +import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -43,7 +43,7 @@ private static void beforeSetupModelViewPartial(final Matrix4f matrix, final Mat camZ ); - matrix.multiply(modelMatrix); + matrix.mul(modelMatrix); ci.cancel(); } } @@ -57,7 +57,7 @@ private static void beforeSetupModelViewPartial(final Matrix4f matrix, final Mat ) private AABB transformLightboxToWorld(final AABB aabb, final double negCamX, final double negCamY, final double negCamZ) { - return VSGameUtilsKt.transformAabbToWorld(this.contraption.entity.level, aabb).move(negCamX, negCamY, negCamZ); + return VSGameUtilsKt.transformAabbToWorld(this.contraption.entity.level(), aabb).move(negCamX, negCamY, negCamZ); } } -*/ + diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinScrollValueBehaviour.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinScrollValueBehaviour.java deleted file mode 100644 index aec0210d3..000000000 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinScrollValueBehaviour.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.valkyrienskies.mod.forge.mixin.compat.create.client; - -/* -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; -import net.minecraft.client.Minecraft; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.valkyrienskies.mod.common.VSGameUtilsKt; - -@Mixin(ScrollValueBehaviour.class) -public class MixinScrollValueBehaviour { - - @Redirect( - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/phys/Vec3;subtract(Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;" - ), - method = "testHit" - ) - private Vec3 transformHitToShip(final Vec3 hitPos, final Vec3 blockPos) { - final Vec3 inShipHit = VSGameUtilsKt.toShipRenderCoordinates(Minecraft.getInstance().level, blockPos, hitPos); - return inShipHit.subtract(blockPos); - } - -} -*/ diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinSuperGlueSelectionHandler.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinSuperGlueSelectionHandler.java new file mode 100644 index 000000000..9782855f0 --- /dev/null +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinSuperGlueSelectionHandler.java @@ -0,0 +1,68 @@ +package org.valkyrienskies.mod.forge.mixin.compat.create.client; + +import com.simibubi.create.content.contraptions.glue.SuperGlueSelectionHandler; +import com.simibubi.create.foundation.utility.RaycastHelper; +import java.util.Iterator; +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.ForgeMod; +import org.joml.Matrix4d; +import org.joml.Quaterniond; +import org.joml.Vector3d; +import org.joml.primitives.AABBic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; + +@Mixin(SuperGlueSelectionHandler.class) +public abstract class MixinSuperGlueSelectionHandler { + @Unique + private Vec3 newTarget; + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/foundation/utility/RaycastHelper;getTraceOrigin(Lnet/minecraft/world/entity/player/Player;)Lnet/minecraft/world/phys/Vec3;"), remap = false) + private Vec3 redirectGetTraceOrigin(Player playerIn) { + Minecraft mc = Minecraft.getInstance(); + double range = playerIn.getAttribute(ForgeMod.ENTITY_REACH.get()).getValue() + 1; + Vec3 origin = RaycastHelper.getTraceOrigin(playerIn); + Vec3 target = RaycastHelper.getTraceTarget(playerIn, range, origin); + + + AABB searchAABB = new AABB(origin, target).inflate(0.25, 2, 0.25); + final Iterator ships = VSGameUtilsKt.getShipsIntersecting(playerIn.level(), searchAABB).iterator(); + + if (ships.hasNext()) { + Ship ship = ships.next(); + + Matrix4d world2Ship = (Matrix4d) ship.getTransform().getWorldToShip(); + AABBic shAABBi = ship.getShipAABB(); + AABB shipAABB = new AABB(shAABBi.minX(), shAABBi.minY(), shAABBi.minZ(), shAABBi.maxX(), shAABBi.maxY(), shAABBi.maxZ()); + + + origin = VectorConversionsMCKt.toMinecraft(world2Ship.transformPosition(VectorConversionsMCKt.toJOML(origin))); + target = VectorConversionsMCKt.toMinecraft(world2Ship.transformPosition(VectorConversionsMCKt.toJOML(target))); + + Quaterniond tempQuat = new Quaterniond(); + if (playerIn.getVehicle() != null && playerIn.getVehicle().getBoundingBox().intersects(shipAABB.inflate(20))) { + ship.getTransform().getWorldToShip().getNormalizedRotation(tempQuat); + tempQuat.invert(); + Vector3d offset = VectorConversionsMCKt.toJOML(target.subtract(origin)); + tempQuat.transform(offset); + target = origin.add(VectorConversionsMCKt.toMinecraft(offset)); + } + } + + newTarget = target; + return origin; + } + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lcom/simibubi/create/foundation/utility/RaycastHelper;getTraceTarget(Lnet/minecraft/world/entity/player/Player;DLnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;"), remap = false) + private Vec3 redirectGetTraceTarget(final Player playerIn, final double range, final Vec3 origin) { + return newTarget; + } +} diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinValueBox.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinValueBox.java index a2a07dba1..2c842d2f2 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinValueBox.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/create/client/MixinValueBox.java @@ -1,8 +1,8 @@ package org.valkyrienskies.mod.forge.mixin.compat.create.client; -/* + import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -10,7 +10,6 @@ @Mixin(ValueBox.class) public class MixinValueBox { - @Redirect( method = "render", at = @At( @@ -22,6 +21,5 @@ public class MixinValueBox { public void redirectTranslate(final PoseStack instance, final double x, final double y, final double z) { VSClientGameUtils.transformRenderIfInShipyard(instance, x, y, z); } - } -*/ + diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/sodium/MixinRenderSectionManager.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/sodium/MixinRenderSectionManager.java index bed0d55cf..87e9fb10b 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/sodium/MixinRenderSectionManager.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/sodium/MixinRenderSectionManager.java @@ -2,11 +2,12 @@ import me.jellysquid.mods.sodium.client.gl.device.CommandList; import me.jellysquid.mods.sodium.client.gl.device.RenderDevice; -import me.jellysquid.mods.sodium.client.render.chunk.ChunkCameraContext; import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderMatrices; -import me.jellysquid.mods.sodium.client.render.chunk.RegionChunkRenderer; +import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderer; import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager; -import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPass; +import me.jellysquid.mods.sodium.client.render.chunk.lists.SortedRenderLists; +import me.jellysquid.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; +import me.jellysquid.mods.sodium.client.render.viewport.CameraTransform; import org.joml.Matrix4d; import org.joml.Matrix4f; import org.joml.Vector3dc; @@ -16,18 +17,21 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; import org.valkyrienskies.mod.mixinducks.mod_compat.sodium.RegionChunkRendererDuck; -import org.valkyrienskies.mod.mixinducks.mod_compat.sodium.RenderSectionManagerDuck; @Mixin(value = RenderSectionManager.class, remap = false) public class MixinRenderSectionManager { + @Shadow @Final - private RegionChunkRenderer chunkRenderer; + private ChunkRenderer chunkRenderer; + + @Shadow + private SortedRenderLists renderLists; @Redirect(at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/gl/device/CommandList;flush()V"), method = "renderLayer") private void redirectRenderLayer(final CommandList list, final ChunkRenderMatrices matrices, - final BlockRenderPass pass, final double camX, final double camY, final double camZ) { + final TerrainRenderPass pass, final double camX, final double camY, final double camZ) { RenderDevice.INSTANCE.makeActive(); @@ -44,7 +48,7 @@ private void redirectRenderLayer(final CommandList list, final ChunkRenderMatric new ChunkRenderMatrices(matrices.projection(), new Matrix4f(newModelView)); ((RegionChunkRendererDuck) chunkRenderer).setCameraForCulling(camX, camY, camZ); chunkRenderer.render(newMatrices, list, renderList, pass, - new ChunkCameraContext(center.x(), center.y(), center.z())); + new CameraTransform(center.x(), center.y(), center.z())); list.close(); }); } diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/sodium/RenderSectionManagerDuck.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/sodium/RenderSectionManagerDuck.java new file mode 100644 index 000000000..f1d3e9121 --- /dev/null +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/sodium/RenderSectionManagerDuck.java @@ -0,0 +1,10 @@ +package org.valkyrienskies.mod.forge.mixin.compat.sodium; + +import java.util.WeakHashMap; +import me.jellysquid.mods.sodium.client.render.chunk.lists.ChunkRenderListIterable; +import org.valkyrienskies.core.api.ships.ClientShip; + +public interface RenderSectionManagerDuck { + WeakHashMap getShipRenderLists(); + +} diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinCasingTileEntityRender.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinCasingTileEntityRender.java index fd3eb77ec..56518b307 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinCasingTileEntityRender.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinCasingTileEntityRender.java @@ -1,7 +1,6 @@ package org.valkyrienskies.mod.forge.mixin.compat.tis3d; -/* -import li.cil.tis3d.client.renderer.tileentity.CasingTileEntityRenderer; +import li.cil.tis3d.client.renderer.block.entity.CasingBlockEntityRenderer; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.world.phys.Vec3; @@ -14,9 +13,9 @@ import org.valkyrienskies.mod.common.VSGameUtilsKt; @Pseudo -@Mixin(CasingTileEntityRenderer.class) +@Mixin(CasingBlockEntityRenderer.class) public abstract class MixinCasingTileEntityRender { - @ModifyVariable(remap = false, method = "isBackFace(Lnet/minecraft/core/BlockPos;Lli/cil/tis3d/api/machine/Face;)Z", + @ModifyVariable(remap = false, method = "isBackFace", at = @At("STORE"), ordinal = 0) private Vec3 vs$isBackFace(final Vec3 original, final BlockPos position) { final ClientShip ship = VSGameUtilsKt.getShipObjectManagingPos(Minecraft.getInstance().level, position); @@ -29,4 +28,4 @@ public abstract class MixinCasingTileEntityRender { } } } -*/ + diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinInfraredPacketEntity.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinInfraredPacketEntity.java index 61f2958ec..2521ef964 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinInfraredPacketEntity.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinInfraredPacketEntity.java @@ -1,6 +1,6 @@ package org.valkyrienskies.mod.forge.mixin.compat.tis3d; -/* + import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import li.cil.tis3d.common.entity.InfraredPacketEntity; @@ -32,4 +32,4 @@ public class MixinInfraredPacketEntity { new Tis3dClipContext(start, target, Block.VISUAL, Fluid.ANY, null)); } } -*/ + diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinRenderContextImpl.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinRenderContextImpl.java index 024c53f5b..c00cea355 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinRenderContextImpl.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/compat/tis3d/MixinRenderContextImpl.java @@ -1,6 +1,6 @@ package org.valkyrienskies.mod.forge.mixin.compat.tis3d; -/* + import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import li.cil.tis3d.client.renderer.RenderContextImpl; @@ -40,4 +40,4 @@ public abstract class MixinRenderContextImpl { } } } -*/ + diff --git a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/world/level/block/FireMixin.java b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/world/level/block/FireMixin.java index 5877ad190..b6f121125 100644 --- a/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/world/level/block/FireMixin.java +++ b/forge/src/main/java/org/valkyrienskies/mod/forge/mixin/world/level/block/FireMixin.java @@ -30,8 +30,7 @@ public abstract class FireMixin { public static IntegerProperty AGE; @Inject(method = "tick", at = @At("TAIL")) - public void fireTickMixin(final BlockState state, final ServerLevel level, final BlockPos pos, - final RandomSource random, + public void fireTickMixin(final BlockState state, final ServerLevel level, final BlockPos pos, final RandomSource random, final CallbackInfo ci) { if (isModifyingFireTick) { return; diff --git a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ContraptionShipyardEntityHandlerForge.kt b/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ContraptionShipyardEntityHandlerForge.kt index f565ebf70..2770a0b09 100644 --- a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ContraptionShipyardEntityHandlerForge.kt +++ b/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ContraptionShipyardEntityHandlerForge.kt @@ -1,7 +1,6 @@ package org.valkyrienskies.mod.forge.common -/* -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity +import com.simibubi.create.content.contraptions.AbstractContraptionEntity import net.minecraft.core.BlockPos import net.minecraft.world.entity.Entity import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate @@ -39,4 +38,3 @@ object ContraptionShipyardEntityHandlerForge: AbstractShipyardEntityHandler() { } } } -*/ diff --git a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt b/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt index 4a7d3e997..354982fb0 100644 --- a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt +++ b/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt @@ -1,6 +1,7 @@ package org.valkyrienskies.mod.forge.common -import net.minecraft.commands.Commands.CommandSelection.* +import net.minecraft.commands.Commands.CommandSelection.ALL +import net.minecraft.commands.Commands.CommandSelection.INTEGRATED import net.minecraft.core.registries.Registries import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.EntityType @@ -19,8 +20,8 @@ import net.minecraftforge.event.TagsUpdatedEvent import net.minecraftforge.fml.ModLoadingContext import net.minecraftforge.fml.common.Mod import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext import net.minecraftforge.fml.loading.FMLEnvironment import net.minecraftforge.registries.DeferredRegister import net.minecraftforge.registries.ForgeRegistries @@ -29,11 +30,13 @@ import org.valkyrienskies.core.apigame.VSCoreFactory import org.valkyrienskies.core.impl.config.VSConfigClass import org.valkyrienskies.core.impl.config.VSCoreConfig import org.valkyrienskies.mod.client.EmptyRenderer +import org.valkyrienskies.mod.client.VSPhysicsEntityRenderer import org.valkyrienskies.mod.common.ValkyrienSkiesMod import org.valkyrienskies.mod.common.ValkyrienSkiesMod.MOD_ID import org.valkyrienskies.mod.common.block.TestChairBlock import org.valkyrienskies.mod.common.block.TestFlapBlock import org.valkyrienskies.mod.common.block.TestHingeBlock +import org.valkyrienskies.mod.common.block.TestSphereBlock import org.valkyrienskies.mod.common.block.TestWingBlock import org.valkyrienskies.mod.common.blockentity.TestHingeBlockEntity import org.valkyrienskies.mod.common.command.VSCommands @@ -42,7 +45,10 @@ import org.valkyrienskies.mod.common.config.VSEntityHandlerDataLoader import org.valkyrienskies.mod.common.config.VSGameConfig import org.valkyrienskies.mod.common.config.VSKeyBindings import org.valkyrienskies.mod.common.entity.ShipMountingEntity +import org.valkyrienskies.mod.common.entity.VSPhysicsEntity +import org.valkyrienskies.mod.common.entity.handling.VSEntityManager import org.valkyrienskies.mod.common.hooks.VSGameEvents +import org.valkyrienskies.mod.common.item.PhysicsEntityCreatorItem import org.valkyrienskies.mod.common.item.ShipAssemblerItem import org.valkyrienskies.mod.common.item.ShipCreatorItem import org.valkyrienskies.mod.compat.clothconfig.VSClothConfig @@ -54,16 +60,15 @@ class ValkyrienSkiesModForge { private val ENTITIES = DeferredRegister.create(ForgeRegistries.ENTITY_TYPES, ValkyrienSkiesMod.MOD_ID) private val BLOCK_ENTITIES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, ValkyrienSkiesMod.MOD_ID) private val TEST_CHAIR_REGISTRY: RegistryObject - private val TEST_CHAIR_REGISTRY_ITEM: RegistryObject private val TEST_HINGE_REGISTRY: RegistryObject - private val TEST_HINGE_REGISTRY_ITEM: RegistryObject private val TEST_FLAP_REGISTRY: RegistryObject - private val TEST_FLAP_REGISTRY_ITEM: RegistryObject private val TEST_WING_REGISTRY: RegistryObject - private val TEST_WING_REGISTRY_ITEM: RegistryObject + private val TEST_SPHERE_REGISTRY: RegistryObject private val SHIP_CREATOR_ITEM_REGISTRY: RegistryObject private val SHIP_CREATOR_SMALLER_ITEM_REGISTRY: RegistryObject + private val PHYSICS_ENTITY_CREATOR_ITEM_REGISTRY: RegistryObject private val SHIP_MOUNTING_ENTITY_REGISTRY: RegistryObject> + private val PHYSICS_ENTITY_TYPE_REGISTRY: RegistryObject> private val SHIP_ASSEMBLER_ITEM_REGISTRY: RegistryObject private val TEST_HINGE_BLOCK_ENTITY_TYPE_REGISTRY: RegistryObject> @@ -72,13 +77,13 @@ class ValkyrienSkiesModForge { val vsCore = if (isClient) { VSCoreFactory.instance.newVsCoreClient(ForgeHooksImpl) } else { - org.valkyrienskies.core.apigame.VSCoreFactory.instance.newVsCoreServer(ForgeHooksImpl) + VSCoreFactory.instance.newVsCoreServer(ForgeHooksImpl) } VSForgeNetworking.registerPacketHandlers(vsCore.hooks) ValkyrienSkiesMod.init(vsCore) - // VSEntityManager.registerContraptionHandler(ContraptionShipyardEntityHandlerForge) + VSEntityManager.registerContraptionHandler(ContraptionShipyardEntityHandlerForge) val modBus = Bus.MOD.bus().get() val forgeBus = Bus.FORGE.bus().get() @@ -87,13 +92,10 @@ class ValkyrienSkiesModForge { ITEMS.register(modBus) ENTITIES.register(modBus) BLOCK_ENTITIES.register(modBus) - - // Only run these on client to prevent loading client classes on server if (isClient) { modBus.addListener(::registerKeyBindings) modBus.addListener(::entityRenderers) } - modBus.addListener(::loadComplete) forgeBus.addListener(::registerCommands) @@ -110,22 +112,11 @@ class ValkyrienSkiesModForge { } } - val testChairPair = registerBlockAndItem("test_chair") { TestChairBlock } - TEST_CHAIR_REGISTRY = testChairPair.first - TEST_CHAIR_REGISTRY_ITEM = testChairPair.second - - val testHingePair = registerBlockAndItem("test_hinge") { TestHingeBlock } - TEST_HINGE_REGISTRY = testHingePair.first - TEST_HINGE_REGISTRY_ITEM = testHingePair.second - - val testFlapPair = registerBlockAndItem("test_flap") { TestFlapBlock } - TEST_FLAP_REGISTRY = testFlapPair.first - TEST_FLAP_REGISTRY_ITEM = testFlapPair.second - - val testWingPair = registerBlockAndItem("test_wing") { TestWingBlock } - TEST_WING_REGISTRY = testWingPair.first - TEST_WING_REGISTRY_ITEM = testWingPair.second - + TEST_CHAIR_REGISTRY = registerBlockAndItem("test_chair") { TestChairBlock } + TEST_HINGE_REGISTRY = registerBlockAndItem("test_hinge") { TestHingeBlock } + TEST_FLAP_REGISTRY = registerBlockAndItem("test_flap") { TestFlapBlock } + TEST_WING_REGISTRY = registerBlockAndItem("test_wing") { TestWingBlock } + TEST_SPHERE_REGISTRY = registerBlockAndItem("test_sphere") { TestSphereBlock } SHIP_CREATOR_ITEM_REGISTRY = ITEMS.register("ship_creator") { ShipCreatorItem(Properties(), @@ -140,6 +131,14 @@ class ValkyrienSkiesModForge { { VSGameConfig.SERVER.minScaling } ) } + + PHYSICS_ENTITY_CREATOR_ITEM_REGISTRY = + ITEMS.register("physics_entity_creator") { + PhysicsEntityCreatorItem( + Properties(), + ) + } + SHIP_MOUNTING_ENTITY_REGISTRY = ENTITIES.register("ship_mounting_entity") { EntityType.Builder.of( ::ShipMountingEntity, @@ -147,6 +146,17 @@ class ValkyrienSkiesModForge { ).sized(.3f, .3f) .build(ResourceLocation(ValkyrienSkiesMod.MOD_ID, "ship_mounting_entity").toString()) } + + PHYSICS_ENTITY_TYPE_REGISTRY = ENTITIES.register("vs_physics_entity") { + EntityType.Builder.of( + ::VSPhysicsEntity, + MobCategory.MISC + ).sized(.3f, .3f) + .setUpdateInterval(1) + .clientTrackingRange(10) + .build(ResourceLocation(ValkyrienSkiesMod.MOD_ID, "vs_physics_entity").toString()) + } + SHIP_ASSEMBLER_ITEM_REGISTRY = ITEMS.register("ship_assembler") { ShipAssemblerItem(Properties()) } TEST_HINGE_BLOCK_ENTITY_TYPE_REGISTRY = BLOCK_ENTITIES.register("test_hinge_block_entity") { @@ -173,12 +183,13 @@ class ValkyrienSkiesModForge { private fun entityRenderers(event: EntityRenderersEvent.RegisterRenderers) { event.registerEntityRenderer(SHIP_MOUNTING_ENTITY_REGISTRY.get(), ::EmptyRenderer) + event.registerEntityRenderer(PHYSICS_ENTITY_TYPE_REGISTRY.get(), ::VSPhysicsEntityRenderer) } - private fun registerBlockAndItem(registryName: String, blockSupplier: () -> Block): Pair, RegistryObject> { + private fun registerBlockAndItem(registryName: String, blockSupplier: () -> Block): RegistryObject { val blockRegistry = BLOCKS.register(registryName, blockSupplier) - val itemRegister = ITEMS.register(registryName) { BlockItem(blockRegistry.get(), Properties()) } - return Pair(blockRegistry, itemRegister) + ITEMS.register(registryName) { BlockItem(blockRegistry.get(), Properties()) } + return blockRegistry } private fun registerCommands(event: RegisterCommandsEvent) { @@ -195,16 +206,14 @@ class ValkyrienSkiesModForge { private fun loadComplete(event: FMLLoadCompleteEvent) { ValkyrienSkiesMod.TEST_CHAIR = TEST_CHAIR_REGISTRY.get() - ValkyrienSkiesMod.TEST_CHAIR_ITEM = TEST_CHAIR_REGISTRY_ITEM.get() ValkyrienSkiesMod.TEST_HINGE = TEST_HINGE_REGISTRY.get() - ValkyrienSkiesMod.TEST_HINGE_ITEM = TEST_HINGE_REGISTRY_ITEM.get() ValkyrienSkiesMod.TEST_FLAP = TEST_FLAP_REGISTRY.get() - ValkyrienSkiesMod.TEST_FLAP_ITEM = TEST_FLAP_REGISTRY_ITEM.get() ValkyrienSkiesMod.TEST_WING = TEST_WING_REGISTRY.get() - ValkyrienSkiesMod.TEST_WING_ITEM = TEST_WING_REGISTRY_ITEM.get() + ValkyrienSkiesMod.TEST_SPHERE = TEST_SPHERE_REGISTRY.get() ValkyrienSkiesMod.SHIP_CREATOR_ITEM = SHIP_CREATOR_ITEM_REGISTRY.get() ValkyrienSkiesMod.SHIP_CREATOR_ITEM_SMALLER = SHIP_CREATOR_SMALLER_ITEM_REGISTRY.get() ValkyrienSkiesMod.SHIP_MOUNTING_ENTITY_TYPE = SHIP_MOUNTING_ENTITY_REGISTRY.get() + ValkyrienSkiesMod.PHYSICS_ENTITY_TYPE = PHYSICS_ENTITY_TYPE_REGISTRY.get() ValkyrienSkiesMod.SHIP_ASSEMBLER_ITEM = SHIP_ASSEMBLER_ITEM_REGISTRY.get() ValkyrienSkiesMod.TEST_HINGE_BLOCK_ENTITY_TYPE = TEST_HINGE_BLOCK_ENTITY_TYPE_REGISTRY.get() } diff --git a/forge/src/main/resources/META-INF/mods.toml b/forge/src/main/resources/META-INF/mods.toml index cbcf33fb1..17fb532c3 100644 --- a/forge/src/main/resources/META-INF/mods.toml +++ b/forge/src/main/resources/META-INF/mods.toml @@ -16,7 +16,7 @@ logoFile = "icon.png" [[dependencies.valkyrienskies]] modId = "forge" mandatory = true -versionRange = "[40.1.69,)" +versionRange = "[40.2.4,)" ordering = "NONE" side = "BOTH" diff --git a/forge/src/main/resources/valkyrienskies-forge.mixins.json b/forge/src/main/resources/valkyrienskies-forge.mixins.json index 4e4304464..0b83f0895 100644 --- a/forge/src/main/resources/valkyrienskies-forge.mixins.json +++ b/forge/src/main/resources/valkyrienskies-forge.mixins.json @@ -2,17 +2,27 @@ "required": true, "package": "org.valkyrienskies.mod.forge.mixin", "compatibilityLevel": "JAVA_17", - "plugin": "org.valkyrienskies.mod.forge.mixin.ValkyrienForgeMixinConfigPlugin", "mixins": [ + "compat.create.MixinBlockBreakingKineticTileEntity", + "compat.create.MixinBlocks", + "compat.create.MixinControlledContraptionEntity", "compat.immersivengineering.MixinBlockEntityInventory", "compat.thermalexpansion.MixinTileCoFH", + "compat.tis3d.MixinInfraredPacketEntity", "feature.forge_interact.MixinIForgePlayer", "feature.water_in_ships_entity.MixinEntity", "world.level.block.FireMixin" ], "client": [ "client.render.MixinLevelRenderer", - "compat.sodium.MixinRenderSectionManager" + "compat.create.client.MixinContraptionHandlerClient", + "compat.create.client.MixinContraptionRenderInfo", + "compat.create.client.MixinFlwContraption", + "compat.create.client.MixinSuperGlueSelectionHandler", + "compat.create.client.MixinValueBox", + "compat.sodium.MixinRenderSectionManager", + "compat.tis3d.MixinCasingTileEntityRender", + "compat.tis3d.MixinRenderContextImpl" ], "injectors": { "defaultRequire": 1 diff --git a/gradle.properties b/gradle.properties index d3002e387..f6bf0becc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,14 +1,32 @@ org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=1G minecraft_version=1.20.1 enabled_platforms=quilt,fabric,forge -archives_base_name=valkyrienskies-1201 -mod_version=2.3.0-beta.5 +archives_base_name=valkyrienskies-120 +mod_version=2.1.4 maven_group=org.valkyrienskies.mod -architectury_version=6.3.49 -fabric_loader_version=0.14.21 -fabric_api_version=0.84.0+1.20.1 -forge_version=1.20.1-47.0.18 -create_fabric_version=0.5.1-c-build.1110+mc1.20.1 + +# https://www.curseforge.com/minecraft/mc-mods/architectury-api/files/ +architectury_version=9.1.12 + +# https://fabricmc.net/develop/ +fabric_loader_version=0.14.24 + +# https://fabricmc.net/develop/ +fabric_api_version=0.90.7+1.20.1 + +# https://files.minecraftforge.net/net/minecraftforge/forge/ +forge_version=1.20.1-47.2.0 + +# https://modrinth.com/mod/create-fabric/versions +create_fabric_version=0.5.1-d-build.1161+mc1.20.1 + +# https://github.com/Fabricators-of-Create/Create/blob/mc1.19/fabric/dev/gradle.properties +flywheel_version_fabric=0.6.9-6 + +# https://modrinth.com/mod/create-big-cannons/versions +createbigcannons_version= 0.5.2.a + +vs_core_version=1.1.0+f2a6aaad81 # Prevent kotlin from autoincluding stdlib as a dependency, which breaks # gradle's composite builds (includeBuild) for some reason. We'll add it manually kotlin.stdlib.default.dependency=false diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 00e33edef..27313fbc8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index d61563cbc..e4f82deee 100644 --- a/settings.gradle +++ b/settings.gradle @@ -42,6 +42,12 @@ dependencyResolutionManagement { include("common") include("fabric") include("forge") -includeBuild("vs-core") + +try { + def core = file("../vs-core") + if (core.isDirectory()) { + includeBuild(core) + } +} catch (SecurityException ignore) {} rootProject.name = "valkyrienskies" diff --git a/vs-core b/vs-core deleted file mode 160000 index 9c5b345b1..000000000 --- a/vs-core +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9c5b345b16b72c9c2dcf34678f24ec0d9a0efdee