diff --git a/.github/workflows/publish-on-release.yml b/.github/workflows/publish-on-release.yml index d18f1bc94..e42f9fd89 100644 --- a/.github/workflows/publish-on-release.yml +++ b/.github/workflows/publish-on-release.yml @@ -18,7 +18,7 @@ jobs: fileNames=(${{ github.event.release.assets[0].name }} ${{ github.event.release.assets[1].name }} ${{ github.event.release.assets[2].name }}) filePaths=(${{ github.event.release.assets[0].browser_download_url }} ${{ github.event.release.assets[1].browser_download_url }} ${{ github.event.release.assets[2].browser_download_url }}) - for i in 0 1 2 + for i in 0 1 2 3 do echo "${fileNames[i]}" echo "${filePaths[i]}" @@ -29,18 +29,20 @@ jobs: if [[ "${fileNames[i]}" == *"fabric"* ]]; then echo "FABRIC_FILE_NAME=${fileNames[i]}" >> $GITHUB_OUTPUT echo "FABRIC_FILE_PATH=./${fileNames[i]}" >> $GITHUB_OUTPUT - fi - if [[ "${fileNames[i]}" == *"forge"* ]]; then + elif [[ "${fileNames[i]}" == *"neoforge"* ]]; then + echo "NEOFORGE_FILE_NAME=${fileNames[i]}" >> $GITHUB_OUTPUT + echo "NEOFORGE_FILE_PATH=./${fileNames[i]}" >> $GITHUB_OUTPUT + elif [[ "${fileNames[i]}" == *"forge"* ]]; then echo "FORGE_FILE_NAME=${fileNames[i]}" >> $GITHUB_OUTPUT echo "FORGE_FILE_PATH=./${fileNames[i]}" >> $GITHUB_OUTPUT - fi - if [[ "${fileNames[i]}" == *"quilt"* ]]; then + elif [[ "${fileNames[i]}" == *"quilt"* ]]; then echo "QUILT_FILE_NAME=${fileNames[i]}" >> $GITHUB_OUTPUT echo "QUILT_FILE_PATH=./${fileNames[i]}" >> $GITHUB_OUTPUT fi done ls -l - run: echo "fabric is ${{ steps.assets.outputs.FABRIC_FILE_NAME }}" + - run: echo "neoforge is ${{ steps.assets.outputs.NEOFORGE_FILE_NAME }}" - run: echo "forge is ${{ steps.assets.outputs.FORGE_FILE_NAME }}" - run: echo "quilt is ${{ steps.assets.outputs.QUILT_FILE_NAME }}" @@ -49,7 +51,7 @@ jobs: shell: bash run: | parse_fabric () { - unzip -j "$1" "$2" -d ./fabric + unzip -o -j "$1" "$2" -d ./fabric deps=false bracket=false parsedVersion="" @@ -75,11 +77,29 @@ jobs: fi done < ./fabric/$2 } + parse_forge () { + unzip -o -j "$1" "META-INF/mods.toml" -d ./forge + minecraftDep=false + minecraftIdReg='modId\s+=\s+"minecraft"' + versionRangeReg='versionRange\s+=\s+"(.+?)"' + while read -r; do + if [[ $REPLY =~ $minecraftIdReg ]]; then + minecraftDep=true + echo "$REPLY" + elif [[ $REPLY =~ $versionRangeReg && $minecraftDep == "true" ]]; then + parsedVersion="${BASH_REMATCH[1]}" + echo "${BASH_REMATCH[0]}" + echo "${BASH_REMATCH[1]}" + fi + done < ./forge/mods.toml + } file="" if [ -n "${{ steps.assets.outputs.FABRIC_FILE_NAME }}" ]; then file="${{ steps.assets.outputs.FABRIC_FILE_NAME }}" elif [ -n "${{ steps.assets.outputs.FORGE_FILE_NAME }}" ]; then file="${{ steps.assets.outputs.FORGE_FILE_NAME }}" + elif [ -n "${{ steps.assets.outputs.NEOFORGE_FILE_NAME }}" ]; then + file="${{ steps.assets.outputs.NEOFORGE_FILE_NAME }}" else file="${{ steps.assets.outputs.QUILT_FILE_NAME }}" fi @@ -120,26 +140,19 @@ jobs: loaders_quilt="quilt" fi loaders_forge="forge" + loaders_neoforge="neoforge" if [ -n "${{ steps.assets.outputs.FABRIC_FILE_NAME }}" ]; then parse_fabric ${{ steps.assets.outputs.FABRIC_FILE_NAME }} "fabric.mod.json" echo "FABRIC_MC_VERSIONS="${parsedVersion}"" >> $GITHUB_OUTPUT fi if [ -n "${{ steps.assets.outputs.FORGE_FILE_NAME }}" ]; then - unzip -j "${{ steps.assets.outputs.FORGE_FILE_NAME }}" "META-INF/mods.toml" -d ./forge - minecraftDep=false - minecraftIdReg='modId\s+=\s+"minecraft"' - versionRangeReg='versionRange\s+=\s+"(.+?)"' - while read -r; do - if [[ $REPLY =~ $minecraftIdReg ]]; then - minecraftDep=true - echo "$REPLY" - elif [[ $REPLY =~ $versionRangeReg && $minecraftDep == "true" ]]; then - echo "FORGE_MC_VERSIONS="${BASH_REMATCH[1]}"" >> $GITHUB_OUTPUT - echo "${BASH_REMATCH[0]}" - echo "${BASH_REMATCH[1]}" - fi - done < ./forge/mods.toml + parse_forge ${{ steps.assets.outputs.FORGE_FILE_NAME }} + echo "FORGE_MC_VERSIONS="${parsedVersion}"" >> $GITHUB_OUTPUT + fi + if [ -n "${{ steps.assets.outputs.NEOFORGE_FILE_NAME }}" ]; then + parse_forge ${{ steps.assets.outputs.NEOFORGE_FILE_NAME }} + echo "NEOFORGE_MC_VERSIONS="${parsedVersion}"" >> $GITHUB_OUTPUT fi if [ -n "${{ steps.assets.outputs.QUILT_FILE_NAME }}" ]; then parse_fabric ${{ steps.assets.outputs.QUILT_FILE_NAME }} "quilt.mod.json" @@ -151,6 +164,8 @@ jobs: echo "loaders forge: ${loaders_forge}" echo "LOADERS_FORGE=${loaders_forge}" >> $GITHUB_OUTPUT + echo "loaders neoforge: ${loaders_neoforge}" + echo "LOADERS_NEOFORGE=${loaders_neoforge}" >> $GITHUB_OUTPUT echo "loaders quilt: ${loaders_quilt}" echo "LOADERS_QUILT=${loaders_quilt}" >> $GITHUB_OUTPUT @@ -160,6 +175,8 @@ jobs: echo "VERSION_NAME_FABRIC=${mod_name}-fabric" >> $GITHUB_OUTPUT echo "file name forge: '${mod_name}-forge'" echo "VERSION_NAME_FORGE=${mod_name}-forge" >> $GITHUB_OUTPUT + echo "file name neoforge: '${mod_name}-neoforge'" + echo "VERSION_NAME_NEOFORGE=${mod_name}-neoforge" >> $GITHUB_OUTPUT echo "file name quilt: '${mod_name}-quilt'" echo "VERSION_NAME_QUILT=${mod_name}-quilt" >> $GITHUB_OUTPUT @@ -167,6 +184,7 @@ jobs: base_version="$mc_version-${array[2]}" echo "MOD_VERSION_FABRIC=${base_version}-fabric" >> $GITHUB_OUTPUT echo "MOD_VERSION_FORGE=${base_version}-forge" >> $GITHUB_OUTPUT + echo "MOD_VERSION_NEOFORGE=${base_version}-neoforge" >> $GITHUB_OUTPUT echo "MOD_VERSION_QUILT=${base_version}-quilt" >> $GITHUB_OUTPUT echo "MOD_VERSION=${base_version}" >> $GITHUB_OUTPUT @@ -178,6 +196,9 @@ jobs: - run: echo "forge mc versions are ${{ steps.version.outputs.FORGE_MC_VERSIONS }}" - run: echo "forge mod version ${{ steps.version.outputs.MOD_VERSION_FORGE }}" + - run: echo "neoforge mc versions are ${{ steps.version.outputs.NEOFORGE_MC_VERSIONS }}" + - run: echo "neoforge mod version ${{ steps.version.outputs.MOD_VERSION_NEOFORGE }}" + - run: echo "quilt mc versions are ${{ steps.version.outputs.QUILT_MC_VERSIONS }}" - run: echo "quilt mod version ${{ steps.version.outputs.MOD_VERSION_QUILT }}" @@ -221,6 +242,26 @@ jobs: loaders: "${{ steps.version.outputs.LOADERS_FORGE}}" #game-versions: "${{ steps.version.outputs.FORGE_MC_VERSIONS }}" + - name: publish neoforge + if: steps.assets.outputs.NEOFORGE_FILE_PATH != '' + uses: Kir-Antipov/mc-publish@v3.3 + with: + modrinth-id: wGoQDPN5 + modrinth-token: ${{ secrets.MODRINTH_TOKEN }} + modrinth-featured: false + + curseforge-id: 667903 + curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }} + + files: ${{ steps.assets.outputs.NEOFORGE_FILE_PATH }} + + name: "${{ steps.version.outputs.VERSION_NAME_NEOFORGE }}" + version: "${{ steps.version.outputs.MOD_VERSION_NEOFORGE }}" + version-type: "${{ steps.version.outputs.RELEASE_TYPE }}" + + loaders: "${{ steps.version.outputs.LOADERS_NEOFORGE}}" + #game-versions: "${{ steps.version.outputs.FORGE_MC_VERSIONS }}" + - name: publish quilt if: steps.assets.outputs.QUILT_FILE_PATH != '' uses: Kir-Antipov/mc-publish@v3.3 @@ -243,18 +284,18 @@ jobs: # update forge versions json - name: checkout repo forge-versions - if: steps.assets.outputs.FORGE_FILE_PATH != '' + if: steps.assets.outputs.FORGE_FILE_PATH != '' || steps.assets.outputs.NEOFORGE_FILE_PATH != '' uses: actions/checkout@v4 with: ref: 'forge-versions' - name: setup python - if: steps.assets.outputs.FORGE_FILE_PATH != '' + if: steps.assets.outputs.FORGE_FILE_PATH != '' || steps.assets.outputs.NEOFORGE_FILE_PATH != '' uses: actions/setup-python@v4 with: python-version: '3.10' - - name: execute py script to update json + - name: execute py script to update forge json if: steps.assets.outputs.FORGE_FILE_PATH != '' run: | python -c " @@ -278,9 +319,49 @@ jobs: with open('forge_updates.json', 'w') as outfile: outfile.write(json.dumps(jsonContent, indent='\t')) " "${{ steps.version.outputs.FORGE_MC_VERSIONS }}" "${{ steps.version.outputs.MOD_VERSION }}" "${{ steps.version.outputs.RELEASE_TYPE }}" - - name: push new update json - if: steps.assets.outputs.FORGE_FILE_PATH != '' + + - name: execute py script to update neoforge json + if: steps.assets.outputs.NEOFORGE_FILE_PATH != '' + run: | + python -c " + import sys, json + print(sys.argv) + mc_version = sys.argv[1] + mod_version = sys.argv[2] + release_type = sys.argv[3] + jsonContent = {} + with open('neoforge_updates.json', 'r') as infile: + jsonContent = json.load(infile) + for str in mc_version.split(','): + version = str.strip('[]\" ') + if version != '' and version[-1:] != ')' and version[:1] != '(': + jsonContent['promos'][version + '-latest'] = mod_version + print('added ' + version + '-latest:' + mod_version) + if release_type == 'release': + jsonContent['promos'][version + '-recommended'] = mod_version + print('added ' + version + '-recommended:' + mod_version) + print(json.dumps(jsonContent, indent='\t')) + with open('neoforge_updates.json', 'w') as outfile: + outfile.write(json.dumps(jsonContent, indent='\t')) + " "${{ steps.version.outputs.NEOFORGE_MC_VERSIONS }}" "${{ steps.version.outputs.MOD_VERSION }}" "${{ steps.version.outputs.RELEASE_TYPE }}" + + - name: push new update json forge + if: steps.assets.outputs.FORGE_FILE_PATH != '' && steps.assets.outputs.NEOFORGE_FILE_PATH == '' + uses: EndBug/add-and-commit@v9 + with: + message: 'update forge ${{ steps.version.outputs.FORGE_MC_VERSIONS }} to ${{ steps.version.outputs.MOD_VERSION }}' + push: true + + - name: push new update json neoforge + if: steps.assets.outputs.FORGE_FILE_PATH == '' && steps.assets.outputs.NEOFORGE_FILE_PATH != '' + uses: EndBug/add-and-commit@v9 + with: + message: 'update neoforge ${{ steps.version.outputs.NEOFORGE_MC_VERSIONS }} to ${{ steps.version.outputs.MOD_VERSION }}' + push: true + + - name: push new update json forge+neoforge + if: steps.assets.outputs.FORGE_FILE_PATH != '' && steps.assets.outputs.NEOFORGE_FILE_PATH != '' uses: EndBug/add-and-commit@v9 with: - message: 'update ${{ steps.version.outputs.FORGE_MC_VERSIONS }} to ${{ steps.version.outputs.MOD_VERSION }}' + message: 'update forge ${{ steps.version.outputs.FORGE_MC_VERSIONS }} to ${{ steps.version.outputs.MOD_VERSION }} and update neoforge ${{ steps.version.outputs.NEOFORGE_MC_VERSIONS }} to ${{ steps.version.outputs.MOD_VERSION }}' push: true diff --git a/build.gradle b/build.gradle index 7cb380fff..43a607f95 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "architectury-plugin" version "3.4-SNAPSHOT" - id "dev.architectury.loom" version "1.3-SNAPSHOT" apply false + id "dev.architectury.loom" version "1.5-SNAPSHOT" apply false id 'io.github.juuxel.loom-quiltflower' version '1.8.0' apply false } @@ -44,7 +44,7 @@ subprojects { task copyJarToMain(type: Copy) { duplicatesStrategy = "include" - if (project.name != "common") { + if (project.name != "common" && project.name != "stubs") { from remapJar into "../build/libs" } diff --git a/common/build.gradle b/common/build.gradle index 5ee21d4ca..da1c061a0 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -7,44 +7,38 @@ loom { } dependencies { + compileOnly project(':stubs') // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies // Do NOT use other classes from fabric loader modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - modApi("dev.architectury:architectury-fabric:${rootProject.architectury_version}") + modApi("dev.architectury:architectury-fabric:${rootProject.architectury_version}") { exclude group: "net.fabricmc" exclude group: "net.fabricmc.fabric-api" } // for sodium compat - modCompileOnly "maven.modrinth:sodium:mc1.19.2-0.4.4" - modCompileOnly "maven.modrinth:sodium:mc1.19.3-0.4.9" - modCompileOnly "883067831485366304:1076634925077364786:sodium-fabric-mc1.19.3-0.4.10rev.c131708-dirty:jar" - modCompileOnly("maven.modrinth:rubidium:0.6.1") - compileOnly 'org.joml:joml:1.10.4' //temp sodium + modCompileOnly "maven.modrinth:sodium:mc1.19.4-0.4.10" // for iris compat - modCompileOnly "maven.modrinth:iris:1.6.5+1.19.2" + modCompileOnly "maven.modrinth:iris:1.6.11+1.19.4" // for REI compat - modCompileOnly "me.shedaniel:RoughlyEnoughItems-fabric:9.1.619" + modCompileOnly("me.shedaniel:RoughlyEnoughItems-fabric:11.0.683") { exclude group: "net.fabricmc" exclude group: "net.fabricmc.fabric-api" exclude group: "dev.architectury" } // for Pehkui compat - modApi("com.github.Virtuoel:Pehkui:3.7.7", { exclude group: "net.fabricmc.fabric-api" }) + modApi("com.github.Virtuoel:Pehkui:3.7.12") { exclude group: "net.fabricmc" exclude group: "net.fabricmc.fabric-api" } // other mods - modCompileOnly "maven.modrinth:dynamic-fps:3.2.0" + modCompileOnly "maven.modrinth:dynamic-fps:3.4.2" // modCompileOnly("com.simibubi.create:create-fabric-1.19.2:0.5.0.i-969+1.19.2") - modCompileOnly "maven.modrinth:lithium:mc1.19.2-0.11.1" - modCompileOnly "maven.modrinth:indium:1.0.9+mc1.19.2" - modCompileOnly "maven.modrinth:resolution-control-plus:1.20-3.0.0" + // modCompileOnly "maven.modrinth:lithium:mc1.19.4-0.11.1" + // modCompileOnly "maven.modrinth:indium:1.0.19+mc1.19.4" + modCompileOnly "maven.modrinth:resolution-control-plus:1.19.4-3.0.0" + modCompileOnly "maven.modrinth:better-combat:1.7.1+1.19.4-fabric" // for immersive portals compat - modCompileOnly('com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:v2.3.1-1.19') { - exclude(group: "net.fabricmc.fabric-api") - transitive(false) - } - modCompileOnly('com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:v2.3.1-1.19') { - exclude(group: "net.fabricmc.fabric-api") - transitive(false) - } + modCompileOnly('com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:v2.7.5-mc1.19.4') { transitive false } + + //for epic fight compat + modCompileOnly("maven.modrinth:epic-fight:20.6.3") // needed dependencies compileOnly("com.google.code.findbugs:jsr305:3.0.2") @@ -52,7 +46,6 @@ dependencies { //LaunchPopup implementation 'com.github.fayer3:LaunchPopup:master-SNAPSHOT' - } // extract the LaunchPopup classes jar { diff --git a/common/src/main/java/org/vivecraft/MixinConfig.java b/common/src/main/java/org/vivecraft/MixinConfig.java index 4ce3225d4..d17f4fbc4 100644 --- a/common/src/main/java/org/vivecraft/MixinConfig.java +++ b/common/src/main/java/org/vivecraft/MixinConfig.java @@ -6,10 +6,10 @@ import org.spongepowered.asm.service.MixinService; import org.vivecraft.client.Xplat; import org.vivecraft.client_vr.settings.VRSettings; -import org.vivecraft.mod_compat_vr.iris.mixin.IrisChunkProgramOverridesMixinSodium_0_4_11; -import org.vivecraft.mod_compat_vr.iris.mixin.IrisChunkProgramOverridesMixinSodium_0_4_8; -import org.vivecraft.mod_compat_vr.iris.mixin.IrisChunkProgramOverridesMixinSodium_0_4_9; -import org.vivecraft.mod_compat_vr.sodium.mixin.RenderSectionManagerVRMixin; +import org.vivecraft.mod_compat_vr.iris.mixin.coderbot.IrisChunkProgramOverridesMixinSodium_0_4_11; +import org.vivecraft.mod_compat_vr.iris.mixin.coderbot.IrisChunkProgramOverridesMixinSodium_0_4_9; +import org.vivecraft.mod_compat_vr.iris.mixin.irisshaders.IrisChunkProgramOverridesMixinSodium_0_6; +import org.vivecraft.mod_compat_vr.sodium.SodiumHelper; import java.io.IOException; import java.util.Collections; @@ -78,15 +78,8 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { neededClass = "me.jellysquid.mods.sodium.client.render.vertex.type.ChunkVertexType"; } else if (mixinClassName.equals(IrisChunkProgramOverridesMixinSodium_0_4_11.class.getName())) { neededClass = "me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType"; - } else if (mixinClassName.equals(RenderSectionManagerVRMixin.class.getName())) { - neededClass = "me.jellysquid.mods.sodium.client.render.chunk.lists.ChunkRenderList"; - try { - MixinService.getService().getBytecodeProvider().getClassNode(neededClass); - ClassNode node = MixinService.getService().getBytecodeProvider().getClassNode(targetClassName); - return node.fields.stream().anyMatch(field -> field.name.equals("chunkRenderList")); - } catch (ClassNotFoundException | IOException e) { - return false; - } + } else if (mixinClassName.equals(IrisChunkProgramOverridesMixinSodium_0_6.class.getName())) { + neededClass = "net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType"; } if (!neededClass.isEmpty()) { @@ -99,6 +92,6 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { } } - return !mixinClassName.contains("NoSodium") || (!Xplat.isModLoaded("sodium") && !Xplat.isModLoaded("rubidium")); + return !mixinClassName.contains("NoSodium") || !SodiumHelper.isLoaded(); } } diff --git a/common/src/main/java/org/vivecraft/client/VRPlayersClient.java b/common/src/main/java/org/vivecraft/client/VRPlayersClient.java index aa607f0a3..6b3e0c1b6 100644 --- a/common/src/main/java/org/vivecraft/client/VRPlayersClient.java +++ b/common/src/main/java/org/vivecraft/client/VRPlayersClient.java @@ -6,6 +6,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; +import org.vivecraft.client.extensions.SparkParticleExtension; import org.vivecraft.client.utils.Utils; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRData; @@ -35,7 +36,11 @@ public static VRPlayersClient getInstance() { } public static void clear() { - instance = null; + if (instance != null) { + instance.vivePlayers.clear(); + instance.vivePlayersLast.clear(); + instance.vivePlayersReceived.clear(); + } } private VRPlayersClient() { @@ -149,6 +154,7 @@ public void tick() { if (particle != null) { particle.setColor(0.5F + this.rand.nextFloat() / 2.0F, 0.5F + this.rand.nextFloat() / 2.0F, 0.5F + this.rand.nextFloat() / 2.0F); + ((SparkParticleExtension) particle).vivecraft$setPlayerUUID(player.getUUID()); } } } diff --git a/common/src/main/java/org/vivecraft/client/VivecraftVRMod.java b/common/src/main/java/org/vivecraft/client/VivecraftVRMod.java index 1649f5adb..cb13468ef 100644 --- a/common/src/main/java/org/vivecraft/client/VivecraftVRMod.java +++ b/common/src/main/java/org/vivecraft/client/VivecraftVRMod.java @@ -37,6 +37,19 @@ public class VivecraftVRMod { public final KeyMapping keyMenuButton = new KeyMapping("vivecraft.key.ingameMenuButton", -1, "key.categories.ui"); public final KeyMapping keyMoveThirdPersonCam = new KeyMapping("vivecraft.key.moveThirdPersonCam", -1, "key.categories.misc"); public final KeyMapping keyQuickHandheldCam = new KeyMapping("vivecraft.key.quickHandheldCam", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand1 = new KeyMapping("vivecraft.key.quickcommand1", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand2 = new KeyMapping("vivecraft.key.quickcommand2", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand3 = new KeyMapping("vivecraft.key.quickcommand3", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand4 = new KeyMapping("vivecraft.key.quickcommand4", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand5 = new KeyMapping("vivecraft.key.quickcommand5", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand6 = new KeyMapping("vivecraft.key.quickcommand6", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand7 = new KeyMapping("vivecraft.key.quickcommand7", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand8 = new KeyMapping("vivecraft.key.quickcommand8", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand9 = new KeyMapping("vivecraft.key.quickcommand9", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand10 = new KeyMapping("vivecraft.key.quickcommand10", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand11 = new KeyMapping("vivecraft.key.quickcommand11", -1, "key.categories.misc"); + public final KeyMapping keyQuickCommand12 = new KeyMapping("vivecraft.key.quickcommand12", -1, "key.categories.misc"); + public final KeyMapping[] keyQuickCommands = new KeyMapping[]{keyQuickCommand1, keyQuickCommand2, keyQuickCommand3, keyQuickCommand4, keyQuickCommand5, keyQuickCommand6, keyQuickCommand7, keyQuickCommand8, keyQuickCommand9, keyQuickCommand10, keyQuickCommand11, keyQuickCommand12}; public final KeyMapping keyQuickTorch = new KeyMapping("vivecraft.key.quickTorch", -1, "key.categories.gameplay"); public final KeyMapping keyRadialMenu = new KeyMapping("vivecraft.key.radialMenu", -1, "key.categories.ui"); public final KeyMapping keyRotateAxis = new KeyMapping("vivecraft.key.rotateAxis", -1, "key.categories.movement"); @@ -72,6 +85,19 @@ private void setupKeybindingSets() { this.userKeyBindingSet.add(this.keyTogglePlayerList); this.userKeyBindingSet.add(this.keyToggleHandheldCam); this.userKeyBindingSet.add(this.keyQuickHandheldCam); + this.userKeyBindingSet.add(this.keyToggleKeyboard); + this.userKeyBindingSet.add(this.keyQuickCommand1); + this.userKeyBindingSet.add(this.keyQuickCommand2); + this.userKeyBindingSet.add(this.keyQuickCommand3); + this.userKeyBindingSet.add(this.keyQuickCommand4); + this.userKeyBindingSet.add(this.keyQuickCommand5); + this.userKeyBindingSet.add(this.keyQuickCommand6); + this.userKeyBindingSet.add(this.keyQuickCommand7); + this.userKeyBindingSet.add(this.keyQuickCommand8); + this.userKeyBindingSet.add(this.keyQuickCommand9); + this.userKeyBindingSet.add(this.keyQuickCommand10); + this.userKeyBindingSet.add(this.keyQuickCommand11); + this.userKeyBindingSet.add(this.keyQuickCommand12); this.hiddenKeyBindingSet.add(GuiHandler.keyLeftClick); this.hiddenKeyBindingSet.add(GuiHandler.keyRightClick); @@ -88,7 +114,6 @@ private void setupKeybindingSets() { this.hiddenKeyBindingSet.add(this.keyClimbeyJump); this.hiddenKeyBindingSet.add(this.keyMenuButton); this.hiddenKeyBindingSet.add(this.keyRadialMenu); - this.hiddenKeyBindingSet.add(this.keyToggleKeyboard); this.hiddenKeyBindingSet.add(this.keyHotbarSwipeX); this.hiddenKeyBindingSet.add(this.keyHotbarSwipeY); this.hiddenKeyBindingSet.add(this.keyTrackpadTouch); diff --git a/common/src/main/java/org/vivecraft/client/Xplat.java b/common/src/main/java/org/vivecraft/client/Xplat.java index 66be65a4f..8c2b0b77e 100644 --- a/common/src/main/java/org/vivecraft/client/Xplat.java +++ b/common/src/main/java/org/vivecraft/client/Xplat.java @@ -4,6 +4,8 @@ import dev.architectury.injectables.annotations.ExpectPlatform; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeSpecialEffects; @@ -84,4 +86,9 @@ static Biome.ClimateSettings getBiomeClimateSettings(Biome biome) { static BiomeSpecialEffects getBiomeEffects(Biome biome) { return null; } + + @ExpectPlatform + static double getItemEntityReach(double baseRange, ItemStack itemStack, EquipmentSlot slot) { + return 0; + } } diff --git a/common/src/main/java/org/vivecraft/client/extensions/SparkParticleExtension.java b/common/src/main/java/org/vivecraft/client/extensions/SparkParticleExtension.java new file mode 100644 index 000000000..daf98708b --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/extensions/SparkParticleExtension.java @@ -0,0 +1,7 @@ +package org.vivecraft.client.extensions; + +import java.util.UUID; + +public interface SparkParticleExtension { + void vivecraft$setPlayerUUID(UUID playerUUID); +} diff --git a/common/src/main/java/org/vivecraft/client/gui/framework/GuiVROptionSlider.java b/common/src/main/java/org/vivecraft/client/gui/framework/GuiVROptionSlider.java index b5e87ba85..dc7818efd 100644 --- a/common/src/main/java/org/vivecraft/client/gui/framework/GuiVROptionSlider.java +++ b/common/src/main/java/org/vivecraft/client/gui/framework/GuiVROptionSlider.java @@ -11,23 +11,30 @@ public class GuiVROptionSlider extends AbstractSliderButton implements GuiVROpti @Nullable private final VRSettings.VrOptions enumOptions; private int id = -1; + private final boolean valueOnly; - public GuiVROptionSlider(int id, int x, int y, int width, int height, VRSettings.VrOptions option) { + public GuiVROptionSlider(int id, int x, int y, int width, int height, VRSettings.VrOptions option, boolean valueOnly) { super(x, y, width, height, - Component.literal(ClientDataHolderVR.getInstance().vrSettings.getButtonDisplayString(option)), + Component.literal(ClientDataHolderVR.getInstance().vrSettings.getButtonDisplayString(option, valueOnly)), option.normalizeValue(ClientDataHolderVR.getInstance().vrSettings.getOptionFloatValue(option))); this.id = id; this.enumOptions = option; + this.valueOnly = valueOnly; + + ClientDataHolderVR dataholder = ClientDataHolderVR.getInstance(); + if (dataholder.vrSettings.overrides.hasSetting(option) && dataholder.vrSettings.overrides.getSetting(option).isValueOverridden()) { + this.active = false; + } } public GuiVROptionSlider(int id, int x, int y, VRSettings.VrOptions option) { - this(id, x, y, 150, 20, option); + this(id, x, y, 150, 20, option, false); } @Override protected void updateMessage() { - this.setMessage(Component.literal(ClientDataHolderVR.getInstance().vrSettings.getButtonDisplayString(this.enumOptions))); + this.setMessage(Component.literal(ClientDataHolderVR.getInstance().vrSettings.getButtonDisplayString(this.enumOptions, valueOnly))); } @Override diff --git a/common/src/main/java/org/vivecraft/client/gui/framework/GuiVROptionsBase.java b/common/src/main/java/org/vivecraft/client/gui/framework/GuiVROptionsBase.java index e6e20f1e0..6b7f9fc97 100644 --- a/common/src/main/java/org/vivecraft/client/gui/framework/GuiVROptionsBase.java +++ b/common/src/main/java/org/vivecraft/client/gui/framework/GuiVROptionsBase.java @@ -175,7 +175,14 @@ protected void init(VRSettings.VrOptions[] settings, boolean clear) { public void render(PoseStack poseStack, int pMouseX, int pMouseY, float pPartialTicks) { if (this.reinit) { this.reinit = false; + VRSettings.VrOptions selected = this.getFocused() instanceof GuiVROptionButton option ? option.getOption() : null; this.init(); + if (selected != null) { + List items = this.children().stream().filter(listener -> listener instanceof GuiVROptionButton o && o.getOption() == selected).toList(); + if (!items.isEmpty()) { + this.setFocused((GuiEventListener) items.get(0)); + } + } } this.renderBackground(poseStack); @@ -229,12 +236,13 @@ public boolean mouseDragged(double pMouseX, double p_94741_, int pMouseY, double return this.visibleList != null ? this.visibleList.mouseDragged(pMouseX, p_94741_, pMouseY, p_94743_, pButton) : super.mouseDragged(pMouseX, p_94741_, pMouseY, p_94743_, pButton); } - public boolean mouseScrolled(double pMouseX, double p_94735_, double pMouseY) { + @Override + public boolean mouseScrolled(double x, double y, double scrollAmountY) { if (this.visibleList != null) { - this.visibleList.mouseScrolled(pMouseX, p_94735_, pMouseY); + this.visibleList.mouseScrolled(x, y, scrollAmountY); } - return super.mouseScrolled(pMouseX, p_94735_, pMouseY); + return super.mouseScrolled(x, y, scrollAmountY); } public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) { @@ -246,7 +254,14 @@ public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) { return true; } else { - return this.visibleList != null && this.visibleList.keyPressed(pKeyCode, pScanCode, pModifiers) || super.keyPressed(pKeyCode, pScanCode, pModifiers); + if (super.keyPressed(pKeyCode, pScanCode, pModifiers)) { + if (this.getFocused() instanceof AbstractWidget widget) { + this.actionPerformed(widget); + } + return true; + } else { + return this.visibleList != null && this.visibleList.keyPressed(pKeyCode, pScanCode, pModifiers); + } } } @@ -255,20 +270,39 @@ public boolean charTyped(char pCodePoint, int pModifiers) { } private void renderTooltip(PoseStack pMatrixStack, int pMouseX, int pMouseY) { - AbstractWidget hover = null; + GuiEventListener hover = null; + + if (this.minecraft.getLastInputType().isKeyboard()) { + // only show focused tooltip when navigating with keyboard, so a click with the mouse removes it + hover = this.getFocused(); + } // find active button - for (GuiEventListener child : children()) { - if (child instanceof AbstractWidget && child.isMouseOver(pMouseX, pMouseY)) { - hover = (AbstractWidget) child; + if (hover == null) { + for (GuiEventListener child : children()) { + if (child instanceof AbstractWidget widget && this.isMouseOver(widget, pMouseX, pMouseY)) { + hover = child; + } } } if (hover != null) { if (hover instanceof GuiVROption guiHover) { if (guiHover.getOption() != null) { String tooltipString = "vivecraft.options." + guiHover.getOption().name() + ".tooltip"; + String tooltip = ""; // check if it has a tooltip if (I18n.exists(tooltipString)) { - String tooltip = I18n.get(tooltipString, (Object) null); + tooltip = I18n.get(tooltipString, (Object) null); + } + + if (dataholder.vrSettings.overrides.hasSetting(guiHover.getOption())) { + VRSettings.ServerOverrides.Setting setting = dataholder.vrSettings.overrides.getSetting(guiHover.getOption()); + if (setting.isValueOverridden()) { + tooltip = I18n.get("vivecraft.message.overriddenbyserver") + tooltip; + } else if (setting.isFloat() && (setting.isValueMinOverridden() || setting.isValueMaxOverridden())) { + tooltip = I18n.get("vivecraft.message.limitedbyserver", setting.getValueMin(), setting.getValueMax()) + tooltip; + } + } + if (!tooltip.isEmpty()) { // add format reset at line ends tooltip = tooltip.replace("\n", "§r\n"); @@ -287,4 +321,8 @@ private void renderTooltip(PoseStack pMatrixStack, int pMouseX, int pMouseY) { } } } + + private boolean isMouseOver(AbstractWidget widget, double x, double y) { + return widget.visible && x >= widget.getX() && y >= widget.getY() && x < (widget.getX() + widget.getWidth()) && y < (widget.getY() + widget.getHeight()); + } } diff --git a/common/src/main/java/org/vivecraft/client/gui/screens/ErrorScreen.java b/common/src/main/java/org/vivecraft/client/gui/screens/ErrorScreen.java index ba482d2b9..9494a2316 100644 --- a/common/src/main/java/org/vivecraft/client/gui/screens/ErrorScreen.java +++ b/common/src/main/java/org/vivecraft/client/gui/screens/ErrorScreen.java @@ -25,16 +25,16 @@ protected void init() { text = this.addRenderableWidget(new TextScrollWidget(this.width / 2 - 155, 30, 310, this.height - 30 - 36, error)); - this.addRenderableWidget(new Button( - this.width / 2 + 5, this.height - 32, - 150, 20, - Component.translatable("gui.back"), - (p) -> Minecraft.getInstance().setScreen(this.lastScreen))); - this.addRenderableWidget(new Button( - this.width / 2 - 155, this.height - 32, - 150, 20, - Component.translatable("chat.copy"), - (p) -> Minecraft.getInstance().keyboardHandler.setClipboard(this.title.getString() + "\n" + error.getString()))); + this.addRenderableWidget(new Button.Builder(Component.translatable("gui.back"), (p) -> + Minecraft.getInstance().setScreen(this.lastScreen)) + .pos(this.width / 2 + 5, this.height - 32) + .size(150, 20) + .build()); + this.addRenderableWidget(new Button.Builder(Component.translatable("chat.copy.click"), (p) -> + Minecraft.getInstance().keyboardHandler.setClipboard(this.title.getString() + "\n" + error.getString())) + .pos(this.width / 2 - 155, this.height - 32) + .size(150, 20) + .build()); } @Override diff --git a/common/src/main/java/org/vivecraft/client/gui/screens/GarbageCollectorScreen.java b/common/src/main/java/org/vivecraft/client/gui/screens/GarbageCollectorScreen.java new file mode 100644 index 000000000..b6b04a1ed --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/gui/screens/GarbageCollectorScreen.java @@ -0,0 +1,79 @@ +package org.vivecraft.client.gui.screens; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.ConfirmLinkScreen; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import org.jetbrains.annotations.NotNull; +import org.vivecraft.client.gui.widgets.TextScrollWidget; +import org.vivecraft.client_vr.ClientDataHolderVR; + + +public class GarbageCollectorScreen extends Screen { + + private final Screen lastScreen; + private final String currentGarbageCollector; + private final static String guideURL = "https://github.com/Vivecraft/VivecraftMod/wiki/Memory-and-GC-Setup"; + + public GarbageCollectorScreen(String currentGarbageCollector) { + super(Component.translatable("vivecraft.messages.gctitle")); + this.lastScreen = Minecraft.getInstance().screen; + this.currentGarbageCollector = currentGarbageCollector; + } + + protected void init() { + Component message = Component.translatable("vivecraft.messages.gcinfo", + Component.literal(currentGarbageCollector).withStyle(s -> s.withColor(ChatFormatting.RED)), + Component.literal("ZGC"), + Component.literal(Integer.toString(6)), + Component.literal("-XX:+UseZGC").withStyle(s -> s + .withColor(ChatFormatting.GOLD) + .withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, "-XX:+UseZGC")) + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.copy.click")))), + Component.translatable("vivecraft.gui.openguide").withStyle(style -> style + .withUnderlined(true) + .withColor(ChatFormatting.GREEN) + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.link.open"))) + .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, guideURL)))); + this.addRenderableWidget(new TextScrollWidget(this.width / 2 - 155, 30, 310, this.height - 30 - 60, message)); + + this.addRenderableWidget(new Button.Builder(Component.translatable("vivecraft.gui.dontshowagain"), (p) -> { + ClientDataHolderVR.getInstance().vrSettings.disableGarbageCollectorMessage = true; + ClientDataHolderVR.getInstance().vrSettings.saveOptions(); + Minecraft.getInstance().setScreen(this.lastScreen); + }) + .pos(this.width / 2 - 155, this.height - 56) + .size(150, 20) + .build()); + + this.addRenderableWidget(new Button.Builder(Component.translatable("vivecraft.gui.ok"), (p) -> + onClose()) + .pos(this.width / 2 + 5, this.height - 56) + .size(150, 20) + .build()); + + this.addRenderableWidget(new Button.Builder(Component.translatable("vivecraft.gui.openguide"), + ConfirmLinkScreen.confirmLink(guideURL, this, true)) + .pos(this.width / 2 - 75, this.height - 32) + .size(150, 20) + .build()); + } + + @Override + public void render(@NotNull PoseStack poseStack, int i, int j, float f) { + this.renderBackground(poseStack); + drawCenteredString(poseStack, this.font, this.title, this.width / 2, 15, 16777215); + super.render(poseStack, i, j, f); + } + + @Override + public void onClose() { + ClientDataHolderVR.getInstance().incorrectGarbageCollector = ""; + this.minecraft.setScreen(lastScreen); + } +} diff --git a/common/src/main/java/org/vivecraft/client/gui/screens/UpdateScreen.java b/common/src/main/java/org/vivecraft/client/gui/screens/UpdateScreen.java index e54e58980..6644b0e82 100644 --- a/common/src/main/java/org/vivecraft/client/gui/screens/UpdateScreen.java +++ b/common/src/main/java/org/vivecraft/client/gui/screens/UpdateScreen.java @@ -19,7 +19,7 @@ public class UpdateScreen extends Screen { private TextScrollWidget text; public UpdateScreen() { - super(Component.literal("New Update Available")); + super(Component.translatable("vivecraft.messages.updateTitle")); lastScreen = Minecraft.getInstance().screen; } @@ -27,29 +27,17 @@ protected void init() { text = this.addRenderableWidget(new TextScrollWidget(this.width / 2 - 155, 30, 310, this.height - 30 - 60, UpdateChecker.changelog)); - this.addRenderableWidget(new Button( - this.width / 2 - 155, this.height - 56, 150, 20, - Component.literal("Download from Modrinth"), - button -> - this.minecraft.setScreen(new ConfirmLinkScreen(bl -> { - if (bl) { - Util.getPlatform().openUri("https://modrinth.com/mod/vivecraft"); - } - this.minecraft.setScreen(this); - }, "https://modrinth.com/mod/vivecraft", true)) - )); + this.addRenderableWidget(new Button.Builder(Component.translatable("vivecraft.gui.downloadfrom", Component.literal("Modrinth")), + ConfirmLinkScreen.confirmLink("https://modrinth.com/mod/vivecraft", this, true)) + .pos(this.width / 2 - 155, this.height - 56) + .size(150, 20) + .build()); - this.addRenderableWidget(new Button( - this.width / 2 + 5, this.height - 56, 150, 20, - Component.literal("Download from Curseforge"), - button -> - this.minecraft.setScreen(new ConfirmLinkScreen(bl -> { - if (bl) { - Util.getPlatform().openUri("https://www.curseforge.com/minecraft/mc-mods/vivecraft"); - } - this.minecraft.setScreen(this); - }, "https://www.curseforge.com/minecraft/mc-mods/vivecraft", true)) - )); + this.addRenderableWidget(new Button.Builder(Component.translatable("vivecraft.gui.downloadfrom", Component.literal("CurseForge")), + ConfirmLinkScreen.confirmLink("https://www.curseforge.com/minecraft/mc-mods/vivecraft", this, true)) + .pos(this.width / 2 + 5, this.height - 56) + .size(150, 20) + .build()); this.addRenderableWidget(new Button( this.width / 2 - 75, this.height - 32, diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiKeyboardSettings.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiKeyboardSettings.java index 542e9dbee..a4f2b7740 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/GuiKeyboardSettings.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiKeyboardSettings.java @@ -14,9 +14,10 @@ public class GuiKeyboardSettings extends GuiVROptionsBase { KeyboardHandler.setOverlayShowing(false); return false; }), + new VROptionEntry(VRSettings.VrOptions.KEYBOARD_PRESS_BINDS), new VROptionEntry(VRSettings.VrOptions.AUTO_OPEN_KEYBOARD), + new VROptionEntry(VRSettings.VrOptions.AUTO_CLOSE_KEYBOARD), new VROptionEntry(VRSettings.VrOptions.PHYSICAL_KEYBOARD_SCALE), - new VROptionEntry(VRSettings.VrOptions.KEYBOARD_PRESS_BINDS), new VROptionEntry(VRSettings.VrOptions.PHYSICAL_KEYBOARD_THEME) }; diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiQuickCommandsList.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiQuickCommandsList.java index e417fc2e7..b8fc3dfdf 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/GuiQuickCommandsList.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiQuickCommandsList.java @@ -47,6 +47,7 @@ public class CommandEntry extends Entry { private CommandEntry(String command, GuiQuickCommandsList parent) { this.txt = new EditBox(GuiQuickCommandsList.this.minecraft.font, parent.width / 2 - 100, 60, 200, 20, Component.literal("")); + this.txt.setMaxLength(256); this.txt.setValue(command); this.btnDelete = new Button(0, 0, 18, 18, Component.literal("X"), (p) -> { @@ -85,11 +86,11 @@ public boolean mouseReleased(double pMouseX, double p_94754_, int pMouseY) { } } - public boolean mouseScrolled(double pMouseX, double p_94735_, double pMouseY) { - if (this.btnDelete.mouseScrolled(pMouseX, p_94735_, pMouseY)) { + public boolean mouseScrolled(double x, double y, double scrollAmountY) { + if (this.btnDelete.mouseScrolled(x, y, scrollAmountY)) { return true; } else { - return this.txt.mouseScrolled(pMouseX, p_94735_, pMouseY) || super.mouseScrolled(pMouseX, p_94735_, pMouseY); + return this.txt.mouseScrolled(x, y, scrollAmountY) || super.mouseScrolled(x, y, scrollAmountY); } } diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiRenderOpticsSettings.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiRenderOpticsSettings.java index 899d6e7fd..70bc9551b 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/GuiRenderOpticsSettings.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiRenderOpticsSettings.java @@ -44,6 +44,9 @@ public class GuiRenderOpticsSettings extends GuiVROptionsBase { VRSettings.VrOptions.MIXED_REALITY_FOV, VRSettings.VrOptions.MIXED_REALITY_RENDER_CAMERA_MODEL }; + static VRSettings.VrOptions[] CROPOptions = new VRSettings.VrOptions[]{ + VRSettings.VrOptions.MIRROR_CROP + }; private float prevRenderScaleFactor = this.settings.renderScaleFactor; private float prevHandCameraResScale = this.settings.handCameraResScale; @@ -104,6 +107,8 @@ public void init() { super.init(UDOptions, false); } else if (this.dataholder.vrSettings.displayMirrorMode == VRSettings.MirrorMode.THIRD_PERSON) { super.init(TUDOptions, false); + } else if (this.dataholder.vrSettings.displayMirrorMode == VRSettings.MirrorMode.CROPPED) { + super.init(CROPOptions, false); } super.addDefaultButtons(); @@ -136,11 +141,13 @@ protected void loadDefaults() { protected void actionPerformed(AbstractWidget widget) { if (widget instanceof GuiVROption guivroption) { - if (VRState.vrRunning && (guivroption.getId() == VRSettings.VrOptions.MIRROR_DISPLAY.ordinal() || guivroption.getId() == VRSettings.VrOptions.FSAA.ordinal() || guivroption.getId() == VRSettings.VrOptions.STENCIL_ON.ordinal())) { - if (guivroption.getId() == VRSettings.VrOptions.STENCIL_ON.ordinal() || (guivroption.getId() == VRSettings.VrOptions.MIRROR_DISPLAY.ordinal() && ShadersHelper.isShaderActive())) { - this.dataholder.vrRenderer.resizeFrameBuffers("Render Setting Changed"); - } else { - this.dataholder.vrRenderer.reinitFrameBuffers("Render Setting Changed"); + if (guivroption.getId() == VRSettings.VrOptions.MIRROR_DISPLAY.ordinal() || VRState.vrRunning && (guivroption.getId() == VRSettings.VrOptions.FSAA.ordinal() || guivroption.getId() == VRSettings.VrOptions.STENCIL_ON.ordinal())) { + if (VRState.vrRunning) { + if (guivroption.getId() == VRSettings.VrOptions.STENCIL_ON.ordinal() || (guivroption.getId() == VRSettings.VrOptions.MIRROR_DISPLAY.ordinal() && ShadersHelper.isShaderActive())) { + this.dataholder.vrRenderer.resizeFrameBuffers("Render Setting Changed"); + } else { + this.dataholder.vrRenderer.reinitFrameBuffers("Render Setting Changed"); + } } this.reinit = true; } diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiRoomscaleSettings.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiRoomscaleSettings.java index 0e4fb8e14..b9642327e 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/GuiRoomscaleSettings.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiRoomscaleSettings.java @@ -14,7 +14,8 @@ public class GuiRoomscaleSettings extends GuiVROptionsBase { VRSettings.VrOptions.REALISTIC_SWIM, VRSettings.VrOptions.BOW_MODE, VRSettings.VrOptions.BACKPACK_SWITCH, - VRSettings.VrOptions.ALLOW_CRAWLING + VRSettings.VrOptions.ALLOW_CRAWLING, + VRSettings.VrOptions.REALISTIC_DISMOUNT }; public GuiRoomscaleSettings(Screen guiScreen) { diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiServerSettings.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiServerSettings.java index 209a37852..e87ec37f5 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/GuiServerSettings.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiServerSettings.java @@ -20,7 +20,6 @@ protected List getEntries() { List entries = new LinkedList<>(); String lastCategory = null; for (ConfigBuilder.ConfigValue cv : ServerConfig.getConfigValues()) { - int i; String path = cv.getPath(); String category = path.substring(0, path.lastIndexOf(".")); String name = path.substring(path.lastIndexOf(".") + 1); diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/VivecraftMainSettings.java b/common/src/main/java/org/vivecraft/client/gui/settings/VivecraftMainSettings.java index ecf72b098..a64fd19a6 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/VivecraftMainSettings.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/VivecraftMainSettings.java @@ -1,15 +1,11 @@ package org.vivecraft.client.gui.settings; -import com.google.common.collect.ImmutableList; -import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Button; -import net.minecraft.client.gui.components.CycleButton; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import org.vivecraft.client.gui.widgets.SettingsList; import org.vivecraft.client.network.ClientNetworking; -import org.vivecraft.client_vr.ClientDataHolderVR; -import org.vivecraft.client_vr.VRState; +import org.vivecraft.client_vr.settings.VRSettings; import java.util.LinkedList; import java.util.List; @@ -23,55 +19,32 @@ public VivecraftMainSettings(Screen lastScreen) { protected List getEntries() { List entries = new LinkedList<>(); - AbstractWidget vrButton = CycleButton.onOffBuilder(VRState.vrEnabled) - .displayOnlyValue() - .withTooltip(value -> font.split(Component.translatable("vivecraft.options.VR_MODE.tooltip"), 200)) - .create(0, 0, SettingsList.WidgetEntry.valueButtonWidth, 20, Component.empty(), (cycleButton, object) -> { - VRState.vrEnabled = !VRState.vrEnabled; - ClientDataHolderVR.getInstance().vrSettings.vrEnabled = VRState.vrEnabled; - ClientDataHolderVR.getInstance().vrSettings.saveOptions(); - }); - vrButton.active = ClientNetworking.serverAllowsVrSwitching || minecraft.player == null; + SettingsList.BaseEntry vrButton = SettingsList.vrOptionToEntry(VRSettings.VrOptions.VR_ENABLED); + vrButton.setActive(vrButton.isActive() && (ClientNetworking.serverAllowsVrSwitching || minecraft.player == null)); + entries.add(vrButton); - entries.add(new SettingsList.WidgetEntry( - Component.translatable("vivecraft.gui.vr", Component.empty()), - vrButton - )); + entries.add(SettingsList.vrOptionToEntry(VRSettings.VrOptions.VR_REMEMBER_ENABLED)); + entries.add(SettingsList.vrOptionToEntry(VRSettings.VrOptions.VR_PLUGIN)); entries.add(new SettingsList.WidgetEntry( Component.translatable("vivecraft.options.screen.main"), - new Button( - 0, 0, SettingsList.WidgetEntry.valueButtonWidth, 20, - Component.translatable("vivecraft.options.screen.main"), - button -> this.minecraft.setScreen(new GuiMainVRSettings(this))))); + Button.builder(Component.translatable("vivecraft.options.screen.main"), button -> this.minecraft.setScreen(new GuiMainVRSettings(this))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build() + )); entries.add(new SettingsList.WidgetEntry( Component.translatable("vivecraft.options.screen.server"), - new Button( - 0, 0, SettingsList.WidgetEntry.valueButtonWidth, 20, - Component.translatable("vivecraft.options.screen.server"), - button -> this.minecraft.setScreen(new GuiServerSettings(this))))); + Button.builder(Component.translatable("vivecraft.options.screen.server"), button -> this.minecraft.setScreen(new GuiServerSettings(this))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build() + )); entries.add(new SettingsList.CategoryEntry(Component.literal("Vivecraft Buttons"))); + entries.add(SettingsList.vrOptionToEntry(VRSettings.VrOptions.VR_TOGGLE_BUTTON_VISIBLE)); + entries.add(SettingsList.vrOptionToEntry(VRSettings.VrOptions.VR_SETTINGS_BUTTON_VISIBLE)); + entries.add(SettingsList.vrOptionToEntry(VRSettings.VrOptions.VR_SETTINGS_BUTTON_POSITION)); - entries.add(new SettingsList.WidgetEntry( - Component.translatable("vivecraft.options.VR_TOGGLE_BUTTON_VISIBLE"), - CycleButton.onOffBuilder(ClientDataHolderVR.getInstance().vrSettings.vrToggleButtonEnabled).displayOnlyValue().create(0, 0, SettingsList.WidgetEntry.valueButtonWidth, 20, Component.empty(), (cycleButton, object) -> { - ClientDataHolderVR.getInstance().vrSettings.vrToggleButtonEnabled = !ClientDataHolderVR.getInstance().vrSettings.vrToggleButtonEnabled; - ClientDataHolderVR.getInstance().vrSettings.saveOptions(); - }))); - entries.add(new SettingsList.WidgetEntry( - Component.translatable("vivecraft.options.VR_SETTINGS_BUTTON_VISIBLE"), - CycleButton.onOffBuilder(ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonEnabled).displayOnlyValue().create(0, 0, SettingsList.WidgetEntry.valueButtonWidth, 20, Component.empty(), (cycleButton, object) -> { - ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonEnabled = !ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonEnabled; - ClientDataHolderVR.getInstance().vrSettings.saveOptions(); - }))); - entries.add(new SettingsList.WidgetEntry( - Component.translatable("vivecraft.options.VR_SETTINGS_BUTTON_POSITION"), - new CycleButton.Builder(bool -> bool ? Component.translatable("vivecraft.options.left") : Component.translatable("vivecraft.options.right")).withValues(ImmutableList.of(Boolean.TRUE, Boolean.FALSE)).withInitialValue(ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonPositionLeft).displayOnlyValue().create(0, 0, SettingsList.WidgetEntry.valueButtonWidth, 20, Component.empty(), (cycleButton, object) -> { - ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonPositionLeft = !ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonPositionLeft; - ClientDataHolderVR.getInstance().vrSettings.saveOptions(); - }))); return entries; } } diff --git a/common/src/main/java/org/vivecraft/client/gui/widgets/SettingsList.java b/common/src/main/java/org/vivecraft/client/gui/widgets/SettingsList.java index a15abf0bb..7254b71ad 100644 --- a/common/src/main/java/org/vivecraft/client/gui/widgets/SettingsList.java +++ b/common/src/main/java/org/vivecraft/client/gui/widgets/SettingsList.java @@ -11,7 +11,11 @@ import net.minecraft.client.gui.narration.NarratedElementType; import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; +import org.vivecraft.client.gui.framework.GuiVROptionSlider; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.server.config.ConfigBuilder; import java.util.Collections; @@ -49,6 +53,56 @@ public static BaseEntry ConfigToEntry(ConfigBuilder.ConfigValue configValue, return new ResettableEntry(name, widget, configValue); } + public static BaseEntry vrOptionToEntry(VRSettings.VrOptions option) { + ClientDataHolderVR dh = ClientDataHolderVR.getInstance(); + String optionString = "vivecraft.options." + option.name(); + String tooltipString = optionString + ".tooltip"; + Tooltip tooltip; + // check if it has a tooltip + if (I18n.exists(tooltipString)) { + String tooltipPrefix = ""; + if (dh.vrSettings.overrides.hasSetting(option)) { + // add override prefix + VRSettings.ServerOverrides.Setting setting = dh.vrSettings.overrides.getSetting(option); + if (setting.isValueOverridden()) { + tooltipPrefix = I18n.get("vivecraft.message.overriddenbyserver"); + } else if (setting.isFloat() && (setting.isValueMinOverridden() || setting.isValueMaxOverridden())) { + tooltipPrefix = I18n.get("vivecraft.message.limitedbyserver", setting.getValueMin(), setting.getValueMax()); + } + } + tooltip = Tooltip.create(Component.literal(tooltipPrefix + I18n.get(tooltipString, (Object) null))); + } else { + tooltip = null; + } + + AbstractWidget widget; + + if (option.getEnumFloat()) { + // slider button + widget = new GuiVROptionSlider(option.returnEnumOrdinal(), + 0, 0, + WidgetEntry.valueButtonWidth, 20, + option, true); + widget.setTooltip(tooltip); + } else { + // regular button + widget = Button.builder(Component.literal(dh.vrSettings.getButtonDisplayString(option, true)) + , button -> { + dh.vrSettings.setOptionValue(option); + button.setMessage(Component.literal(dh.vrSettings.getButtonDisplayString(option, true))); + }) + .size(WidgetEntry.valueButtonWidth, 20) + .tooltip(tooltip) + .build(); + } + + BaseEntry entry = new WidgetEntry(Component.translatable(optionString), widget); + if (dh.vrSettings.overrides.hasSetting(option) && dh.vrSettings.overrides.getSetting(option).isValueOverridden()) { + entry.setActive(false); + } + return entry; + } + public static class CategoryEntry extends BaseEntry { private final int width; @@ -117,6 +171,12 @@ public List children() { public List narratables() { return ImmutableList.of(this.valueWidget, this.resetButton); } + + @Override + public void setActive(boolean active) { + super.setActive(active); + this.resetButton.active = active; + } } public static class WidgetEntry extends BaseEntry { @@ -146,15 +206,31 @@ public List children() { public List narratables() { return ImmutableList.of(this.valueWidget); } + + @Override + public void setActive(boolean active) { + super.setActive(active); + this.valueWidget.active = active; + } } public static abstract class BaseEntry extends Entry { protected final Component name; + private boolean active = true; public BaseEntry(Component name) { this.name = name; } + + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } } } diff --git a/common/src/main/java/org/vivecraft/client/gui/widgets/TextScrollWidget.java b/common/src/main/java/org/vivecraft/client/gui/widgets/TextScrollWidget.java index 1d9e52e2f..68ae82afa 100644 --- a/common/src/main/java/org/vivecraft/client/gui/widgets/TextScrollWidget.java +++ b/common/src/main/java/org/vivecraft/client/gui/widgets/TextScrollWidget.java @@ -3,7 +3,6 @@ import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.AbstractWidget; -import net.minecraft.client.gui.components.ComponentRenderUtils; import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Style; @@ -30,7 +29,7 @@ public class TextScrollWidget extends AbstractWidget { public TextScrollWidget(int x, int y, int width, int height, String text) { super(x, y, width, height, Component.literal("")); - formattedChars = ComponentRenderUtils.wrapComponents(Component.literal(text), width - scrollBarWidth * 2, Minecraft.getInstance().font); + formattedChars = Minecraft.getInstance().font.split(Component.literal(text), width - scrollBarWidth * 2); initScroll(); } @@ -38,7 +37,7 @@ public TextScrollWidget(int x, int y, int width, int height, String text) { public TextScrollWidget(int x, int y, int width, int height, Component text) { super(x, y, width, height, Component.literal("")); - formattedChars = ComponentRenderUtils.wrapComponents(text, width - scrollBarWidth * 2, Minecraft.getInstance().font); + formattedChars = Minecraft.getInstance().font.split(text, width - scrollBarWidth * 2); initScroll(); } @@ -140,10 +139,10 @@ private void setCurrentLineFromYPos(double y) { } @Override - public boolean mouseScrolled(double x, double y, double scrollAmount) { - if (scrollAmount < 0.0 && currentLine < scrollSteps) { + public boolean mouseScrolled(double x, double y, double scrollAmountY) { + if (scrollAmountY < 0.0 && currentLine < scrollSteps) { currentLine++; - } else if (scrollAmount > 0.0 && currentLine > 0) { + } else if (scrollAmountY > 0.0 && currentLine > 0) { currentLine--; } else { // scroll bar on limit, didn't consume the input diff --git a/common/src/main/java/org/vivecraft/client/network/ClientNetworking.java b/common/src/main/java/org/vivecraft/client/network/ClientNetworking.java index 3e0b036e9..bfbe92b35 100644 --- a/common/src/main/java/org/vivecraft/client/network/ClientNetworking.java +++ b/common/src/main/java/org/vivecraft/client/network/ClientNetworking.java @@ -25,6 +25,7 @@ import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.common.CommonDataHolder; import org.vivecraft.common.VRServerPerms; +import org.vivecraft.common.network.BufferSerializable; import org.vivecraft.common.network.CommonNetworkHelper; import org.vivecraft.common.network.VrPlayerState; @@ -51,14 +52,14 @@ public class ClientNetworking { public static boolean needsReset = true; public static ServerboundCustomPayloadPacket getVivecraftClientPacket(CommonNetworkHelper.PacketDiscriminators command, byte[] payload) { - FriendlyByteBuf friendlybytebuf = new FriendlyByteBuf(Unpooled.buffer()); - friendlybytebuf.writeByte(command.ordinal()); - friendlybytebuf.writeBytes(payload); - return new ServerboundCustomPayloadPacket(CommonNetworkHelper.CHANNEL, friendlybytebuf); + FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); + buffer.writeByte(command.ordinal()); + buffer.writeBytes(payload); + return new ServerboundCustomPayloadPacket(CommonNetworkHelper.CHANNEL, buffer); } public static ServerboundCustomPayloadPacket createVRActivePacket(boolean vrActive) { - var buffer = new FriendlyByteBuf(Unpooled.buffer()); + FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); buffer.writeByte(CommonNetworkHelper.PacketDiscriminators.IS_VR_ACTIVE.ordinal()); buffer.writeBoolean(vrActive); return new ServerboundCustomPayloadPacket(CommonNetworkHelper.CHANNEL, buffer); @@ -73,7 +74,16 @@ public static void resetServerSettings() { serverAllowsCrawling = false; serverAllowsVrSwitching = false; usedNetworkVersion = -1; - //DataHolder.getInstance().vrSettings.overrides.resetAll(); move to mixin + + // clear VR player data + VRPlayersClient.clear(); + // clear teleport + VRServerPerms.INSTANCE.setTeleportSupported(false); + if (VRState.vrInitialized) { + ClientDataHolderVR.getInstance().vrPlayer.setTeleportOverride(false); + } + // clear server overrides + ClientDataHolderVR.getInstance().vrSettings.overrides.resetAll(); } public static void sendVersionInfo() { @@ -129,8 +139,20 @@ public static void sendVRPlayerPositions(VRPlayer vrPlayer) { VRPlayersClient.getInstance().Update(Minecraft.getInstance().player.getGameProfile().getId(), vrPlayerState, worldScale, f1 / 1.52F, true); } + private static byte[] serializeToArray(BufferSerializable object, byte[] additionalData) { + FriendlyByteBuf tempBuffer = new FriendlyByteBuf(Unpooled.buffer()); + if (additionalData != null) { + tempBuffer.writeBytes(additionalData); + } + object.serialize(tempBuffer); + byte[] buffer = new byte[tempBuffer.readableBytes()]; + tempBuffer.readBytes(buffer); + tempBuffer.release(); + return buffer; + } + public static ServerboundCustomPayloadPacket createVrPlayerStatePacket(VrPlayerState vrPlayerState) { - var buffer = new FriendlyByteBuf(Unpooled.buffer()); + FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); buffer.writeByte(CommonNetworkHelper.PacketDiscriminators.VR_PLAYER_STATE.ordinal()); vrPlayerState.serialize(buffer); return new ServerboundCustomPayloadPacket(CommonNetworkHelper.CHANNEL, buffer); @@ -159,6 +181,10 @@ public static void sendLegacyPackets(ClientPacketListener connection, VrPlayerSt connection.send(new ServerboundCustomPayloadPacket(CommonNetworkHelper.CHANNEL, headBuffer)); } + public static boolean isThirdPersonItems() { + return ClientDataHolderVR.getInstance().vrSettings.overrides.getSetting(VRSettings.VrOptions.THIRDPERSON_ITEMTRANSFORMS).getBoolean(); + } + public static boolean isLimitedSurvivalTeleport() { return ClientDataHolderVR.getInstance().vrSettings.overrides.getSetting(VRSettings.VrOptions.LIMIT_TELEPORT).getBoolean(); } diff --git a/common/src/main/java/org/vivecraft/client/network/PatreonReceiver.java b/common/src/main/java/org/vivecraft/client/network/SupporterReceiver.java similarity index 62% rename from common/src/main/java/org/vivecraft/client/network/PatreonReceiver.java rename to common/src/main/java/org/vivecraft/client/network/SupporterReceiver.java index fdb4dc384..86d1ccc46 100644 --- a/common/src/main/java/org/vivecraft/client/network/PatreonReceiver.java +++ b/common/src/main/java/org/vivecraft/client/network/SupporterReceiver.java @@ -12,28 +12,35 @@ import java.util.List; import java.util.Map; -public class PatreonReceiver { +public class SupporterReceiver { private static final Object lock = new Object(); private static final List queuedPlayers = new LinkedList<>(); private static Map cache; private static boolean downloadStarted; private static boolean downloadFailed; - private static void fileDownloadFinished(String url, String data) { + private static void fileDownloadFinished(String url, String data, boolean addData) { synchronized (lock) { if (data != null) { try { - HashMap hashmap = new HashMap<>(); - String[] astring = data.split("\\r?\\n"); + Map userMap = new HashMap<>(); + if (addData) { + userMap = cache; + } + + String[] lines = data.split("\\r?\\n"); - for (String s1 : astring) { + for (String user : lines) { + if (user.isEmpty()) { + continue; + } try { - String[] astring1 = s1.split(":"); - int i = Integer.parseInt(astring1[1]); - hashmap.put(astring1[0], i); + String[] bits = user.split(":"); + int i = Integer.parseInt(bits[1]); + userMap.put(bits[0].toLowerCase(), i); for (Player player : queuedPlayers) { - if (astring1[0].equalsIgnoreCase(player.getGameProfile().getName())) { + if (bits[0].equalsIgnoreCase(player.getGameProfile().getName())) { VRPlayersClient.getInstance().setHMD(player.getUUID(), i); } } @@ -42,7 +49,7 @@ private static void fileDownloadFinished(String url, String data) { } } - cache = hashmap; + cache = userMap; } catch (Exception exception1) { System.out.println("Error parsing data: " + url + ", " + exception1.getClass().getName() + ": " + exception1.getMessage()); downloadFailed = true; @@ -64,18 +71,21 @@ public static void addPlayerInfo(Player p) { if (!downloadStarted) { downloadStarted = true; - String s = "http://www.vivecraft.org/patreon/current.txt"; + String url1 = "https://www.vivecraft.org/patreon/current.txt"; + String url2 = "https://raw.githubusercontent.com/Vivecraft/VivecraftSupporters/supporters/supporters.txt"; new Thread(() -> { try { - String value = IOUtils.toString(new URL(s), StandardCharsets.UTF_8); - fileDownloadFinished(s, value); + String value1 = IOUtils.toString(new URL(url1), StandardCharsets.UTF_8); + String value2 = IOUtils.toString(new URL(url2), StandardCharsets.UTF_8); + fileDownloadFinished(url1, value1, false); + fileDownloadFinished(url2, value2, true); } catch (IOException e) { throw new RuntimeException(e); } }).start(); } } else { - VRPlayersClient.getInstance().setHMD(p.getUUID(), cache.getOrDefault(p.getGameProfile().getName(), 0)); + VRPlayersClient.getInstance().setHMD(p.getUUID(), cache.getOrDefault(p.getGameProfile().getName().toLowerCase(), 0)); } } } diff --git a/common/src/main/java/org/vivecraft/client/utils/UpdateChecker.java b/common/src/main/java/org/vivecraft/client/utils/UpdateChecker.java index 3189980f1..dd59bd9c8 100644 --- a/common/src/main/java/org/vivecraft/client/utils/UpdateChecker.java +++ b/common/src/main/java/org/vivecraft/client/utils/UpdateChecker.java @@ -121,19 +121,20 @@ public Version(String version, String version_number, String changelog) { this.fullVersion = version; this.changelog = changelog; String[] parts = version_number.split("-"); - if (parts.length > 3) { + int viveVersionIndex = parts.length - 2; + // parts should be [mc version]-(pre/rc)-[vive version]-(vive a/b/test)-[mod loader] + if (!parts[viveVersionIndex].contains(".")) { + viveVersionIndex = parts.length - 3; // prerelease - if (parts[2].matches("a\\d+")) { - alpha = Integer.parseInt(parts[2].replaceAll("\\D+", "")); - } else if (parts[2].matches("b\\d+")) { - beta = Integer.parseInt(parts[2].replaceAll("\\D+", "")); + if (parts[parts.length - 1].matches("a\\d+")) { + alpha = Integer.parseInt(parts[parts.length - 1].replaceAll("\\D+", "")); + } else if (parts[parts.length - 1].matches("b\\d+")) { + beta = Integer.parseInt(parts[parts.length - 1].replaceAll("\\D+", "")); } else { featureTest = true; } } - // account for old version, without MC version prefix - int index = parts.length > 1 ? 1 : 0; - String[] ints = parts[index].split("\\."); + String[] ints = parts[viveVersionIndex].split("\\."); // remove all letters, since stupid me put a letter in one version major = Integer.parseInt(ints[0].replaceAll("\\D+", "")); minor = Integer.parseInt(ints[1].replaceAll("\\D+", "")); diff --git a/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java b/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java index 114d9ece3..3679e9657 100644 --- a/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java @@ -44,6 +44,7 @@ public class ClientDataHolderVR { public VRSettings vrSettings; public boolean integratedServerLaunchInProgress = false; public boolean grabScreenShot = false; + public String incorrectGarbageCollector = ""; public long frameIndex = 0L; public RenderPass currentPass; public int tickCounter; diff --git a/common/src/main/java/org/vivecraft/client_vr/ItemTags.java b/common/src/main/java/org/vivecraft/client_vr/ItemTags.java index 9a7e456d4..66c84a213 100644 --- a/common/src/main/java/org/vivecraft/client_vr/ItemTags.java +++ b/common/src/main/java/org/vivecraft/client_vr/ItemTags.java @@ -36,6 +36,8 @@ public class ItemTags { public final static TagKey VIVECRAFT_TOOLS = tag("tools"); + public final static TagKey VIVECRAFT_BOW_EXCLUSION = tag("bow_exclusion"); + private static TagKey tag(String name) { return TagKey.create(Registry.ITEM_REGISTRY, new ResourceLocation("vivecraft", name)); } diff --git a/common/src/main/java/org/vivecraft/client_vr/VRState.java b/common/src/main/java/org/vivecraft/client_vr/VRState.java index 5a9f031ab..1886d1b15 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRState.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRState.java @@ -3,8 +3,10 @@ import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import org.apache.commons.lang3.StringUtils; import org.lwjgl.glfw.GLFW; import org.vivecraft.client.gui.screens.ErrorScreen; +import org.vivecraft.client.gui.screens.GarbageCollectorScreen; import org.vivecraft.client_vr.gameplay.VRPlayer; import org.vivecraft.client_vr.menuworlds.MenuWorldRenderer; import org.vivecraft.client_vr.provider.nullvr.NullVR; @@ -14,6 +16,9 @@ import org.vivecraft.client_xr.render_pass.RenderPassManager; import org.vivecraft.mod_compat_vr.optifine.OptifineHelper; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryManagerMXBean; + public class VRState { public static boolean vrRunning = false; @@ -69,6 +74,32 @@ public static void initializeVR() { dh.menuWorldRenderer = new MenuWorldRenderer(); dh.menuWorldRenderer.init(); + + try { + String garbageCollector = StringUtils.getCommonPrefix(ManagementFactory.getGarbageCollectorMXBeans().stream().map(MemoryManagerMXBean::getName).toArray(String[]::new)).trim(); + if (garbageCollector.isEmpty()) { + garbageCollector = ManagementFactory.getGarbageCollectorMXBeans().get(0).getName(); + } + VRSettings.logger.info("Garbage collector: {}", garbageCollector); + + // Fully qualified name here to avoid any ambiguity + com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + // Might as well log this stuff since we have it, could be useful for technical support + VRSettings.logger.info("Available CPU threads: {}", Runtime.getRuntime().availableProcessors()); + VRSettings.logger.info("Total physical memory: {} GiB", String.format("%.01f", os.getTotalMemorySize() / 1073741824.0F)); + VRSettings.logger.info("Free physical memory: {} GiB", String.format("%.01f", os.getFreeMemorySize() / 1073741824.0F)); + + if (!garbageCollector.equals("ZGC") && !ClientDataHolderVR.getInstance().vrSettings.disableGarbageCollectorMessage) { + // At least 12 GiB RAM (minus 256 MiB for possible reserved) and 8 CPU threads + if (os.getTotalMemorySize() >= 1073741824L * 12L - 1048576L * 256L && Runtime.getRuntime().availableProcessors() >= 6) { + // store the garbage collector, as indicator, that the GarbageCollectorScreen should be shown, if it would be discarded + dh.incorrectGarbageCollector = garbageCollector; + Minecraft.getInstance().setScreen(new GarbageCollectorScreen(garbageCollector)); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } } catch (RenderConfigException renderConfigException) { vrEnabled = false; destroyVR(true); diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java index 9ce88ee83..f2e50b96c 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java @@ -317,7 +317,7 @@ public void doPlayerMoveInRoom(LocalPlayer player) { VRData tempVrdata = new VRData(this.roomOrigin, dataholder.vrSettings.walkMultiplier, this.worldScale, this.vrdata_world_pre.rotation_radians); - if (dataholder.vehicleTracker.canRoomscaleDismount(minecraft.player)) { + if (dataholder.vrSettings.realisticDismountEnabled && dataholder.vehicleTracker.canRoomscaleDismount(minecraft.player)) { Vec3 mountpos = minecraft.player.getVehicle().position(); Vec3 head = tempVrdata.getHeadPivot(); double distance = Math.sqrt((head.x - mountpos.x) * (head.x - mountpos.x) + (head.z - mountpos.z) * (head.z - mountpos.z)); diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/screenhandlers/GuiHandler.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/screenhandlers/GuiHandler.java index bc5eed53b..4e6b0762c 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/screenhandlers/GuiHandler.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/screenhandlers/GuiHandler.java @@ -328,7 +328,7 @@ public static void onScreenChanged(Screen previousGuiScreen, Screen newScreen, b guiRotation_room = null; guiScale = 1.0F; - if (KeyboardHandler.keyboardForGui) { + if (KeyboardHandler.keyboardForGui && dh.vrSettings.autoCloseKeyboard) { KeyboardHandler.setOverlayShowing(false); } } else { diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java index 0a87abeb6..d61693de4 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java @@ -69,7 +69,7 @@ public static boolean isBow(ItemStack itemStack) { } else if (ClientDataHolderVR.getInstance().vrSettings.bowMode == VRSettings.BowMode.VANILLA) { return itemStack.getItem() == Items.BOW; } else { - return itemStack.getItem().getUseAnimation(itemStack) == UseAnim.BOW; + return itemStack.getItem().getUseAnimation(itemStack) == UseAnim.BOW && !itemStack.is(org.vivecraft.client_vr.ItemTags.VIVECRAFT_BOW_EXCLUSION); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/ClimbTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/ClimbTracker.java index a811bed0a..8ca566bdb 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/ClimbTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/ClimbTracker.java @@ -2,6 +2,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; +import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.contents.TranslatableContents; import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket; @@ -28,6 +29,7 @@ import java.util.*; public class ClimbTracker extends Tracker { + public static final ModelResourceLocation clawsModel = new ModelResourceLocation("vivecraft", "climb_claws", "inventory"); private final boolean[] latched = new boolean[2]; private final boolean[] wasinblock = new boolean[2]; private final boolean[] wasbutton = new boolean[2]; diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/JumpTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/JumpTracker.java index 651005a8f..1a09d43e7 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/JumpTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/JumpTracker.java @@ -13,6 +13,7 @@ import org.vivecraft.client_vr.extensions.PlayerExtension; import org.vivecraft.client_vr.gameplay.VRPlayer; import org.vivecraft.client_vr.settings.AutoCalibration; +import org.vivecraft.client_vr.settings.VRSettings; public class JumpTracker extends Tracker { public Vec3[] latchStart = new Vec3[]{new Vec3(0.0D, 0.0D, 0.0D), new Vec3(0.0D, 0.0D, 0.0D)}; @@ -38,7 +39,7 @@ public boolean isActive(LocalPlayer p) { return false; } else if (!ClientDataHolderVR.getInstance().vrPlayer.getFreeMove() && !ClientDataHolderVR.getInstance().vrSettings.simulateFalling) { return false; - } else if (!ClientDataHolderVR.getInstance().vrSettings.realisticJumpEnabled) { + } else if (ClientDataHolderVR.getInstance().vrSettings.realisticJumpEnabled == VRSettings.RealisticJump.OFF) { return false; } else if (p != null && p.isAlive()) { if (this.mc.gameMode == null) { @@ -67,7 +68,8 @@ public void reset(LocalPlayer player) { } public void doProcess(LocalPlayer player) { - if (this.isClimbeyJumpEquipped()) { + boolean climbeyEquipped = this.isClimbeyJumpEquipped(); + if (climbeyEquipped) { VRPlayer vrplayer = this.dh.vrPlayer; boolean[] aboolean = new boolean[2]; @@ -155,7 +157,8 @@ public void doProcess(LocalPlayer player) { Vec3 vec36 = this.latchStartOrigin[0].subtract(this.latchStartPlayer[0]).add(this.mc.player.position()).subtract(vec33); this.dh.vrPlayer.setRoomOrigin(vec36.x, vec36.y, vec36.z, false); } - } else if (this.dh.vr.hmdPivotHistory.netMovement(0.25D).y > 0.1D && this.dh.vr.hmdPivotHistory.latest().y - (double) AutoCalibration.getPlayerHeight() > (double) this.dh.vrSettings.jumpThreshold) { + } + if ((!climbeyEquipped || ClientDataHolderVR.getInstance().vrSettings.realisticJumpEnabled == VRSettings.RealisticJump.ON) && this.dh.vr.hmdPivotHistory.netMovement(0.25D).y > 0.1D && this.dh.vr.hmdPivotHistory.latest().y - (double) AutoCalibration.getPlayerHeight() > (double) this.dh.vrSettings.jumpThreshold) { player.jumpFromGround(); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java index 97e8eacea..57b5b3ef1 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java @@ -5,6 +5,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.*; import net.minecraft.world.item.context.UseOnContext; @@ -16,12 +17,15 @@ import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import org.vivecraft.client.VivecraftVRMod; +import org.vivecraft.client.Xplat; import org.vivecraft.client_vr.BlockTags; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.ItemTags; import org.vivecraft.client_vr.Vec3History; import org.vivecraft.client_vr.provider.ControllerType; import org.vivecraft.client_vr.settings.VRSettings; +import org.vivecraft.mod_compat_vr.bettercombat.BetterCombatHelper; +import org.vivecraft.mod_compat_vr.epicfight.EpicFightHelper; import java.util.List; @@ -65,12 +69,10 @@ public boolean isActive(LocalPlayer p) { } else if (dataholder.vrSettings.seated) { return false; } else { - VRSettings vrsettings = dataholder.vrSettings; - if (dataholder.vrSettings.vrFreeMoveMode == VRSettings.FreeMove.RUN_IN_PLACE && p.zza > 0.0F) { - return false; + return false; // don't hit things while RIPing. } else if (p.isBlocking()) { - return false; + return false; //don't hit things while blocking. } else { return !dataholder.jumpTracker.isjumping(); } @@ -79,7 +81,21 @@ public boolean isActive(LocalPlayer p) { } public static boolean isTool(Item item) { - return item instanceof DiggerItem || item instanceof ArrowItem || item instanceof FishingRodItem || item instanceof FoodOnAStickItem || item instanceof ShearsItem || item == Items.BONE || item == Items.BLAZE_ROD || item == Items.BAMBOO || item == Items.TORCH || item == Items.REDSTONE_TORCH || item == Items.STICK || item == Items.DEBUG_STICK || item instanceof FlintAndSteelItem || item.getDefaultInstance().is(ItemTags.VIVECRAFT_TOOLS); + return item instanceof DiggerItem || + item instanceof ArrowItem || + item instanceof FishingRodItem || + item instanceof FoodOnAStickItem || + item instanceof ShearsItem || + item == Items.BONE || + item == Items.BLAZE_ROD || + item == Items.BAMBOO || + item == Items.TORCH || + item == Items.REDSTONE_TORCH || + item == Items.STICK || + item == Items.DEBUG_STICK || + item instanceof FlintAndSteelItem || + item instanceof BrushItem || + item.getDefaultInstance().is(ItemTags.VIVECRAFT_TOOLS); } public void doProcess(LocalPlayer player) { @@ -91,151 +107,210 @@ public void doProcess(LocalPlayer player) { this.mc.getProfiler().push("updateSwingAttack"); - for (int i = 0; i < 2; ++i) { - if (!this.dh.climbTracker.isGrabbingLadder(i)) { - Vec3 vec3 = this.dh.vrPlayer.vrdata_world_pre.getController(i).getPosition(); - Vec3 vec31 = this.dh.vrPlayer.vrdata_world_pre.getHand(i).getCustomVector(this.forward); - ItemStack itemstack = player.getItemInHand(i == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND); + for (int c = 0; c < 2; c++) { + if (!this.dh.climbTracker.isGrabbingLadder(c)) { + Vec3 handPos = this.dh.vrPlayer.vrdata_world_pre.getController(c).getPosition(); + Vec3 handDirection = this.dh.vrPlayer.vrdata_world_pre.getHand(c).getCustomVector(this.forward); + ItemStack itemstack = player.getItemInHand(c == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND); Item item = itemstack.getItem(); - boolean flag = false; - boolean flag1 = false; + boolean isTool = false; + boolean isSword = false; if (!(item instanceof SwordItem || itemstack.is(ItemTags.VIVECRAFT_SWORDS)) && !(item instanceof TridentItem || itemstack.is(ItemTags.VIVECRAFT_SPEARS))) { if (isTool(item)) { - flag = true; + isTool = true; } } else { - flag1 = true; - flag = true; + isSword = true; + isTool = true; + } + + float weaponLength; + float entityReachAdd; + + double playerEntityReach = Xplat.getItemEntityReach(3.0, itemstack, c == 0 ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); + if (Xplat.isModLoaded("bettercombat")) { + // better combat overrides the player reach + playerEntityReach = BetterCombatHelper.getItemRange(playerEntityReach, itemstack); } - float f; - float f1; - - if (flag1) { - f1 = 1.9F; - f = 0.6F; - flag = true; - } else if (flag) { - f1 = 1.2F; - f = 0.35F; - flag = true; + // subtract arm length and clamp it to 6 meters + playerEntityReach = Math.min(playerEntityReach, 6.0) - 0.5; + + if (isSword) { + weaponLength = 0.6F; + // in default situations a total reach of 2.5 + entityReachAdd = (float) playerEntityReach - weaponLength; + } else if (isTool) { + weaponLength = 0.35F; + // in default situations a total reach of 1.55 + entityReachAdd = (float) playerEntityReach * 0.62F - weaponLength; } else if (!itemstack.isEmpty()) { - f = 0.1F; - f1 = 0.3F; + weaponLength = 0.1F; + // in default situations a total reach of 0.4 + entityReachAdd = (float) playerEntityReach * 0.16F - weaponLength; } else { - f = 0.0F; - f1 = 0.3F; + weaponLength = 0.0F; + entityReachAdd = 0.3F; } - f = f * this.dh.vrPlayer.vrdata_world_pre.worldScale; - this.miningPoint[i] = vec3.add(vec31.scale(f)); - Vec3 vec32 = this.dh.vrPlayer.vrdata_room_pre.getController(i).getPosition().add(this.dh.vrPlayer.vrdata_room_pre.getHand(i).getCustomVector(this.forward).scale(0.3D)); - this.tipHistory[i].add(vec32); - float f2 = (float) this.tipHistory[i].averageSpeed(0.33D); - boolean flag2 = false; - this.canact[i] = (double) f2 > this.speedthresh && !this.lastWeaponSolid[i]; - boolean flag3 = this.canact[i]; + weaponLength *= this.dh.vrPlayer.vrdata_world_pre.worldScale; + + this.miningPoint[c] = handPos.add(handDirection.scale(weaponLength)); + + //do speed calc in actual room coords + Vec3 tip = this.dh.vrPlayer.vrdata_room_pre.getController(c).getPosition().add(this.dh.vrPlayer.vrdata_room_pre.getHand(c).getCustomVector(this.forward).scale(0.3D)); + this.tipHistory[c].add(tip); + + // at a 0.3m offset on index controllers a speed of 3m/s is an intended smack, 7 m/s is about as high as your arm can go. + float speed = (float) this.tipHistory[c].averageSpeed(0.33D); + boolean inAnEntity = false; + this.canact[c] = (double) speed > this.speedthresh && !this.lastWeaponSolid[c]; + + //Check EntityCollisions first + boolean entityAct = this.canact[c]; - if (flag3) { - BlockHitResult blockhitresult = this.mc.level.clip(new ClipContext(this.dh.vrPlayer.vrdata_world_pre.hmd.getPosition(), vec3, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.mc.player)); + // no hitting around corners, to not trigger anticheat + if (entityAct) { + BlockHitResult blockhitresult = this.mc.level.clip(new ClipContext(this.dh.vrPlayer.vrdata_world_pre.hmd.getPosition(), handPos, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.mc.player)); if (blockhitresult.getType() != HitResult.Type.MISS) { - flag3 = false; + entityAct = false; } } - this.attackingPoint[i] = this.constrain(vec3, this.miningPoint[i]); - Vec3 vec33 = vec3.add(vec31.scale(f + f1)); - vec33 = this.constrain(vec3, vec33); - AABB aabb = new AABB(vec3, this.attackingPoint[i]); - AABB aabb1 = new AABB(vec3, vec33); - List list = this.mc.level.getEntities(this.mc.player, aabb1); - list.removeIf((e) -> - { - return e instanceof Player; - }); - List list1 = this.mc.level.getEntities(this.mc.player, aabb); - list1.removeIf((e) -> - { - return !(e instanceof Player); - }); - list.addAll(list1); - - for (Entity entity : list) { + this.attackingPoint[c] = this.constrain(handPos, this.miningPoint[c]); + + Vec3 weaponTip = handPos.add(handDirection.scale(weaponLength + entityReachAdd)); + // no hitting through blocks + weaponTip = this.constrain(handPos, weaponTip); + + AABB weaponBB = new AABB(handPos, this.attackingPoint[c]); + AABB weaponTipBB = new AABB(handPos, weaponTip); + + List mobs = this.mc.level.getEntities(this.mc.player, weaponTipBB); + mobs.removeIf((e) -> e instanceof Player); + + // shorter range for players to try to prevent accidental hits + List players = this.mc.level.getEntities(this.mc.player, weaponBB); + players.removeIf((e) -> !(e instanceof Player)); + mobs.addAll(players); + + for (Entity entity : mobs) { if (entity.isPickable() && entity != this.mc.getCameraEntity().getVehicle()) { - if (flag3) { + if (entityAct) { //Minecraft.getInstance().physicalGuiManager.preClickAction(); - this.mc.gameMode.attack(player, entity); - this.dh.vr.triggerHapticPulse(i, 1000); - this.lastWeaponSolid[i] = true; - } - flag2 = true; + if (!EpicFightHelper.isLoaded() || !EpicFightHelper.attack()) { + // only attack if epic fight didn't trigger + this.mc.gameMode.attack(player, entity); + } else { + // only attack once with epic fight + entityAct = false; + } + this.dh.vr.triggerHapticPulse(c, 1000); + this.lastWeaponSolid[c] = true; + } + inAnEntity = true; } } - this.canact[i] = this.canact[i] && !flag1 && !flag2; - - if (!this.dh.climbTracker.isClimbeyClimb() || (i != 0 || !VivecraftVRMod.INSTANCE.keyClimbeyGrab.isDown(ControllerType.RIGHT)) && flag && (i != 1 || !VivecraftVRMod.INSTANCE.keyClimbeyGrab.isDown(ControllerType.LEFT)) && flag) { - BlockPos blockpos = new BlockPos(this.miningPoint[i]); - BlockState blockstate = this.mc.level.getBlockState(blockpos); - BlockHitResult blockhitresult1 = this.mc.level.clip(new ClipContext(this.lastWeaponEndAir[i], this.miningPoint[i], ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.mc.player)); - - if (!blockstate.isAir() && blockhitresult1.getType() == HitResult.Type.BLOCK && this.lastWeaponEndAir[i].length() != 0.0D) { - this.lastWeaponSolid[i] = true; - boolean flag4 = blockhitresult1.getBlockPos().equals(blockpos); - boolean flag5 = this.dh.vrSettings.realisticClimbEnabled && (blockstate.getBlock() instanceof LadderBlock || blockstate.getBlock() instanceof VineBlock || blockstate.is(BlockTags.VIVECRAFT_CLIMBABLE)); - - if (blockhitresult1.getType() == HitResult.Type.BLOCK && flag4 && this.canact[i] && !flag5) { - int j = 3; - - if ((item instanceof HoeItem || itemstack.is(ItemTags.VIVECRAFT_HOES) || itemstack.is(ItemTags.VIVECRAFT_SCYTHES)) && ( - blockstate.getBlock() instanceof CropBlock - || blockstate.getBlock() instanceof StemBlock - || blockstate.getBlock() instanceof AttachedStemBlock - || blockstate.is(BlockTags.VIVECRAFT_CROPS) - // check if the item can use the block - || item.useOn(new UseOnContext(player, i == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND, blockhitresult1)).shouldSwing())) { - // don't try to break crops with hoes - // actually use the item on the block - boolean useSuccessful = this.mc.gameMode.useItemOn(player, i == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND, blockhitresult1).shouldSwing(); - if (itemstack.is(ItemTags.VIVECRAFT_SCYTHES) && !useSuccessful) { - // some scythes just need to be used - this.mc.gameMode.useItem(player, i == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND); - } - } else if (blockstate.getBlock() instanceof NoteBlock || blockstate.is(BlockTags.VIVECRAFT_MUSIC_BLOCKS)) { - this.mc.gameMode.continueDestroyBlock(blockhitresult1.getBlockPos(), blockhitresult1.getDirection()); - } else { - j = (int) ((double) j + Math.min((double) f2 - this.speedthresh, 4.0D)); - //this.mc.physicalGuiManager.preClickAction(); - this.mc.gameMode.startDestroyBlock(blockhitresult1.getBlockPos(), blockhitresult1.getDirection()); + // block check + // don't hit blocks with swords or same time as hitting entity + this.canact[c] = this.canact[c] && !isSword && !inAnEntity; - if (this.getIsHittingBlock()) { - for (int k = 0; k < j; ++k) { - if (this.mc.gameMode.continueDestroyBlock(blockhitresult1.getBlockPos(), blockhitresult1.getDirection())) { - this.mc.particleEngine.crack(blockhitresult1.getBlockPos(), blockhitresult1.getDirection()); - } - - this.clearBlockHitDelay(); + // no hitting while climbey climbing + if (this.dh.climbTracker.isClimbeyClimb() && (!isTool || + (c == 0 && VivecraftVRMod.INSTANCE.keyClimbeyGrab.isDown(ControllerType.RIGHT)) || + (c == 1 && VivecraftVRMod.INSTANCE.keyClimbeyGrab.isDown(ControllerType.LEFT)))) { + continue; + } - if (!this.getIsHittingBlock()) { - break; - } + BlockPos blockpos = BlockPos.containing(this.miningPoint[c]); + BlockState blockstate = this.mc.level.getBlockState(blockpos); + + // every time end of weapon enters a solid for the first time, trace from our previous air position + // and damage the block it collides with... + BlockHitResult blockHit = this.mc.level.clip(new ClipContext(this.lastWeaponEndAir[c], this.miningPoint[c], ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.mc.player)); + + if (!blockstate.isAir() && blockHit.getType() == HitResult.Type.BLOCK && this.lastWeaponEndAir[c].length() != 0.0D) { + + this.lastWeaponSolid[c] = true; + + boolean sameBlock = blockHit.getBlockPos().equals(blockpos); //fix ladders? + // don't break climbable blocks + boolean protectedBlock = this.dh.vrSettings.realisticClimbEnabled && + (blockstate.getBlock() instanceof LadderBlock || + blockstate.getBlock() instanceof VineBlock || + blockstate.is(BlockTags.VIVECRAFT_CLIMBABLE)); + + if (blockHit.getType() == HitResult.Type.BLOCK && sameBlock && this.canact[c] && !protectedBlock) { + int totalHits = 3; + + // roomscale hoe interaction + if ((item instanceof HoeItem || itemstack.is(ItemTags.VIVECRAFT_HOES) || itemstack.is(ItemTags.VIVECRAFT_SCYTHES)) && ( + blockstate.getBlock() instanceof CropBlock + || blockstate.getBlock() instanceof StemBlock + || blockstate.getBlock() instanceof AttachedStemBlock + || blockstate.is(BlockTags.VIVECRAFT_CROPS) + // check if the item can use the block + || item.useOn(new UseOnContext(player, c == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND, blockHit)).shouldSwing())) { + // don't try to break crops with hoes + // actually use the item on the block + boolean useSuccessful = this.mc.gameMode.useItemOn(player, c == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND, blockHit).shouldSwing(); + if (itemstack.is(ItemTags.VIVECRAFT_SCYTHES) && !useSuccessful) { + // some scythes just need to be used + this.mc.gameMode.useItem(player, c == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND); + } + } + // roomscale brushes + else if ((item instanceof BrushItem /*|| itemstack.is(ItemTags.VIVECRAFT_BRUSHES*/)) { + ((BrushItem) item).spawnDustParticles(player.level, blockHit, blockstate, player.getViewVector(0.0F)); + player.level.playSound(player, blockHit.getBlockPos(), SoundEvents.BRUSH_BRUSHING, SoundSource.PLAYERS); + this.mc.gameMode.useItemOn(player, c == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND, blockHit); + } + // roomscale noteblocks + else if (blockstate.getBlock() instanceof NoteBlock || blockstate.is(BlockTags.VIVECRAFT_MUSIC_BLOCKS)) { + this.mc.gameMode.continueDestroyBlock(blockHit.getBlockPos(), blockHit.getDirection()); + } + // roomscale mining + else { + // faster swings do more damage + totalHits = (int) ((double) totalHits + Math.min((double) speed - this.speedthresh, 4.0D)); + //this.mc.physicalGuiManager.preClickAction(); + + // this will either destroy the block if in creative or set it as the current block. + // does nothing in survival if you are already hitting this block. + this.mc.gameMode.startDestroyBlock(blockHit.getBlockPos(), blockHit.getDirection()); + + //seems to be the only way to tell it didn't instabreak. + if (this.getIsHittingBlock()) { + for (int hit = 0; hit < totalHits; ++hit) { + //send multiple ticks worth of 'holding left click' to it. + if (this.mc.gameMode.continueDestroyBlock(blockHit.getBlockPos(), blockHit.getDirection())) { + this.mc.particleEngine.crack(blockHit.getBlockPos(), blockHit.getDirection()); } - Minecraft.getInstance().gameMode.destroyDelay = 0; + this.clearBlockHitDelay(); + + if (!this.getIsHittingBlock()) { + //seems to be the only way to tell if it broke. + break; + } } - this.dh.vrPlayer.blockDust(blockhitresult1.getLocation().x, blockhitresult1.getLocation().y, blockhitresult1.getLocation().z, 3 * j, blockpos, blockstate, 0.6F, 1.0F); + Minecraft.getInstance().gameMode.destroyDelay = 0; } - this.dh.vr.triggerHapticPulse(i, 250 * j); + this.dh.vrPlayer.blockDust(blockHit.getLocation().x, blockHit.getLocation().y, blockHit.getLocation().z, 3 * totalHits, blockpos, blockstate, 0.6F, 1.0F); } - } else { - this.lastWeaponEndAir[i] = this.miningPoint[i]; - this.lastWeaponSolid[i] = false; + + this.dh.vr.triggerHapticPulse(c, 250 * totalHits); } + } else { + // reset + this.lastWeaponEndAir[c] = this.miningPoint[c]; + this.lastWeaponSolid[c] = false; } } } @@ -248,6 +323,7 @@ private boolean getIsHittingBlock() { } private void clearBlockHitDelay() { + // TODO set destroyTicks to 1 to cancel multiple sound events per hit //MCReflection.PlayerController_blockHitDelay.set(Minecraft.getInstance().gameMode, 0); // Minecraft.getInstance().gameMode.blockBreakingCooldown = 1; } @@ -258,37 +334,37 @@ public Vec3 constrain(Vec3 start, Vec3 end) { } public static float getItemFade(LocalPlayer p, ItemStack is) { - float f = p.getAttackStrengthScale(0.0F) * 0.75F + 0.25F; + float fade = p.getAttackStrengthScale(0.0F) * 0.75F + 0.25F; if (p.isShiftKeyDown()) { - f = 0.75F; + fade = 0.75F; } boolean[] aboolean = ClientDataHolderVR.getInstance().swingTracker.lastWeaponSolid; Minecraft.getInstance().getItemRenderer(); if (aboolean[ClientDataHolderVR.ismainhand ? 0 : 1]) { - f -= 0.25F; + fade -= 0.25F; } if (is != ItemStack.EMPTY) { if (p.isBlocking() && p.getUseItem() != is) { - f -= 0.25F; + fade -= 0.25F; } if (is.getItem() == Items.SHIELD && !p.isBlocking()) { - f -= 0.25F; + fade -= 0.25F; } } - if ((double) f < 0.1D) { - f = 0.1F; + if ((double) fade < 0.1D) { + fade = 0.1F; } - if (f > 1.0F) { - f = 1.0F; + if (fade > 1.0F) { + fade = 1.0F; } - return f; + return fade; } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/InputSimulator.java b/common/src/main/java/org/vivecraft/client_vr/provider/InputSimulator.java index c46c7bfb8..b2f3d1be0 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/InputSimulator.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/InputSimulator.java @@ -17,8 +17,8 @@ public static boolean isKeyDown(int key) { } public static void pressKey(int key, int modifiers) { - Minecraft.getInstance().keyboardHandler.keyPress(Minecraft.getInstance().getWindow().getWindow(), key, 0, 1, modifiers); pressedKeys.add(key); + Minecraft.getInstance().keyboardHandler.keyPress(Minecraft.getInstance().getWindow().getWindow(), key, 0, 1, modifiers); } public static void pressKey(int key) { @@ -26,8 +26,8 @@ public static void pressKey(int key) { } public static void releaseKey(int key, int modifiers) { - Minecraft.getInstance().keyboardHandler.keyPress(Minecraft.getInstance().getWindow().getWindow(), key, 0, 0, modifiers); pressedKeys.remove(key); + Minecraft.getInstance().keyboardHandler.keyPress(Minecraft.getInstance().getWindow().getWindow(), key, 0, 0, modifiers); } public static void releaseKey(int key) { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java index f16da8756..5fe44f0b8 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java @@ -1172,4 +1172,8 @@ private void addActionParams(Map map, KeyMapping keyBindin public abstract VRRenderer createVRRenderer(); public abstract boolean isActive(); + + public boolean capFPS() { + return false; + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java index bf3fed253..645015d55 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java @@ -191,4 +191,9 @@ public boolean isActive() { } return vrActive; } + + @Override + public boolean capFPS() { + return true; + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java index 079a08401..08e9cb877 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java @@ -858,6 +858,26 @@ private void initOpenVRCompositor() { System.out.println("OpenVR Compositor initialized OK."); } + private void checkPathValid(String path, String knownError, boolean alwaysThrow) throws RenderConfigException { + String pathFormatted = ""; + boolean hasInvalidChars = false; + for (char c : path.toCharArray()) { + if (c > 127) { + hasInvalidChars = true; + pathFormatted += "§c" + c + "§r"; + } else { + pathFormatted += c; + } + } + + if (hasInvalidChars || alwaysThrow) { + String error = knownError + (hasInvalidChars ? "\nInvalid characters in path: \n" : "\n"); + System.out.println(error + path); + throw new RenderConfigException(knownError, Component.empty().append(error).append(pathFormatted)); + } + } + + private void installApplicationManifest(boolean force) throws RenderConfigException { File file1 = new File("openvr/vivecraft.vrmanifest"); Utils.loadAssetToFile("vivecraft.vrmanifest", file1, true); @@ -881,6 +901,9 @@ private void installApplicationManifest(boolean force) throws RenderConfigExcept System.out.println("Appkey: " + s); + // check if path is valid always, since if the application was already installed, it will not check it again + checkPathValid(file1.getAbsolutePath(), "Failed to install application manifest", false); + if (!force && VRApplications_IsApplicationInstalled(s)) { System.out.println("Application manifest already installed"); } else { @@ -888,21 +911,7 @@ private void installApplicationManifest(boolean force) throws RenderConfigExcept if (i != 0) { // application needs to be installed, so abort - String pathFormatted = ""; - boolean hasInvalidChars = false; - for (char c : file1.getAbsolutePath().toCharArray()) { - if (c > 127) { - hasInvalidChars = true; - pathFormatted += "§c" + c + "§r"; - } else { - pathFormatted += c; - } - } - - String error = VRApplications_GetApplicationsErrorNameFromEnum(i) + (hasInvalidChars ? "\nInvalid characters in path: \n" : "\n"); - System.out.println("Failed to install application manifest: " + error + file1.getAbsolutePath()); - - throw new RenderConfigException("Failed to install application manifest", Component.empty().append(error).append(pathFormatted)); + checkPathValid(file1.getAbsolutePath(), "Failed to install application manifest: " + VRApplications_GetApplicationsErrorNameFromEnum(i), true); } System.out.println("Application manifest installed successfully"); @@ -964,11 +973,14 @@ private void loadActionHandles() { } } - private void loadActionManifest() { - int i = VRInput_SetActionManifestPath((new File("openvr/input/action_manifest.json")).getAbsolutePath()); + private void loadActionManifest() throws RenderConfigException { + String actionsPath = (new File("openvr/input/action_manifest.json")).getAbsolutePath(); + // check if path is valid for steamvr, since it would just silently fail + checkPathValid(actionsPath, "Failed to install action manifest", false); + int i = VRInput_SetActionManifestPath(actionsPath); if (i != 0) { - throw new RuntimeException("Failed to load action manifest: " + getInputErrorName(i)); + throw new RenderConfigException("Failed to load action manifest", Component.literal(getInputErrorName(i))); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/render/VivecraftItemRendering.java b/common/src/main/java/org/vivecraft/client_vr/render/VivecraftItemRendering.java index af5a5338f..621626acb 100644 --- a/common/src/main/java/org/vivecraft/client_vr/render/VivecraftItemRendering.java +++ b/common/src/main/java/org/vivecraft/client_vr/render/VivecraftItemRendering.java @@ -15,12 +15,10 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.TorchBlock; import net.minecraft.world.phys.Vec3; -import org.vivecraft.client.VivecraftVRMod; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.ItemTags; import org.vivecraft.client_vr.gameplay.trackers.SwingTracker; import org.vivecraft.client_vr.gameplay.trackers.TelescopeTracker; -import org.vivecraft.client_vr.provider.ControllerType; public class VivecraftItemRendering { private static final ClientDataHolderVR dh = ClientDataHolderVR.getInstance(); @@ -47,7 +45,7 @@ public static VivecraftItemTransformType getTransformType(ItemStack pStack, Abst } } else if (item instanceof MapItem || pStack.is(ItemTags.VIVECRAFT_MAPS)) { rendertype = VivecraftItemTransformType.Map; - } else if (pStack.getUseAnimation() == UseAnim.BOW) { + } else if (pStack.getUseAnimation() == UseAnim.BOW && !pStack.is(ItemTags.VIVECRAFT_BOW_EXCLUSION)) { rendertype = VivecraftItemTransformType.Bow_Seated; if (dh.bowTracker.isActive((LocalPlayer) pPlayer)) { @@ -96,6 +94,10 @@ public static void applyThirdPersonItemTransforms(PoseStack pMatrixStack, Vivecr double translateZ = 0; boolean useLeftHandModelinLeftHand = false; + if (dh.climbTracker.isClaws(pStack)) { + scale = 0.4D; + } + // pMatrixStack.mulPose(preRotation); pMatrixStack.translate(translateX, translateY, translateZ); // pMatrixStack.mulPose(rotation); @@ -329,20 +331,6 @@ public static void applyFirstPersonItemTransforms(PoseStack pMatrixStack, Vivecr rotation.mul(Vector3f.XP.rotationDegrees(40.0F)); scale = 0.8F; } else if (rendertype == VivecraftItemTransformType.Tool) { - boolean isClaws = dh.climbTracker.isClaws(pStack) && dh.climbTracker.isClimbeyClimb(); - - if (isClaws) { - rotation.mul(Vector3f.XP.rotationDegrees((float) (-gunAngle))); - scale = 0.3F; - translateZ += 0.075F; - translateY += 0.02F; - translateX += 0.03F; - - if (VivecraftVRMod.INSTANCE.keyClimbeyGrab.isDown(ControllerType.RIGHT) && mainHand || VivecraftVRMod.INSTANCE.keyClimbeyGrab.isDown(ControllerType.LEFT) && !mainHand) { - translateZ += -0.2F; - } - } - if (pStack.getItem() instanceof ArrowItem || pStack.is(ItemTags.VIVECRAFT_ARROWS)) { preRotation = Vector3f.ZP.rotationDegrees(-180.0F); rotation.mul(Vector3f.XP.rotationDegrees((float) (-gunAngle))); diff --git a/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRArmHelper.java b/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRArmHelper.java index 932b8b7d6..afea7c661 100644 --- a/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRArmHelper.java +++ b/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRArmHelper.java @@ -12,7 +12,6 @@ import net.minecraft.util.Mth; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; import net.minecraft.world.phys.Vec3; import org.lwjgl.opengl.GL11C; import org.vivecraft.client.network.ClientNetworking; @@ -144,8 +143,8 @@ public static void renderVRHand_Main(PoseStack poseStack, float partialTicks) { item = override; } - if (dataHolder.climbTracker.isClimbeyClimb() && item.getItem() != Items.SHEARS) { - item = override == null ? mc.player.getOffhandItem() : override; + if (dataHolder.climbTracker.isClimbeyClimb() && !dataHolder.climbTracker.isClaws(item) && override == null) { + item = mc.player.getOffhandItem(); } if (BowTracker.isHoldingBow(mc.player, InteractionHand.MAIN_HAND)) { @@ -207,8 +206,7 @@ public static void renderVRHand_Offhand(float partialTicks, boolean renderTelepo item = override; } - if (dataHolder.climbTracker.isClimbeyClimb() - && (item == null || item.getItem() != Items.SHEARS)) { + if (dataHolder.climbTracker.isClimbeyClimb() && !dataHolder.climbTracker.isClaws(item) && override == null) { item = mc.player.getMainHandItem(); } diff --git a/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java b/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java index 37b9caed4..180cf1492 100644 --- a/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java +++ b/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java @@ -110,6 +110,12 @@ public enum FreeMove implements OptionEnum { AUTO // only for flying } + public enum RealisticJump implements OptionEnum { + OFF, + ON, + AUTO + } + public enum MenuWorld implements OptionEnum { BOTH, CUSTOM, @@ -156,7 +162,7 @@ public enum UpdateType implements OptionEnum { @SettingField public int version = UNKNOWN_VERSION; - @SettingField + @SettingField(VrOptions.VR_PLUGIN) public VRProvider stereoProviderPluginID = VRProvider.OPENVR; public boolean storeDebugAim = false; @SettingField @@ -251,7 +257,7 @@ public enum UpdateType implements OptionEnum { @SettingField public float crawlThreshold = 0.82f; @SettingField(VrOptions.REALISTIC_JUMP) - public boolean realisticJumpEnabled = true; + public RealisticJump realisticJumpEnabled = RealisticJump.AUTO; @SettingField(VrOptions.REALISTIC_SNEAK) public boolean realisticSneakEnabled = true; @SettingField(VrOptions.REALISTIC_CLIMB) @@ -260,6 +266,8 @@ public enum UpdateType implements OptionEnum { public boolean realisticSwimEnabled = true; @SettingField(VrOptions.REALISTIC_ROW) public boolean realisticRowEnabled = true; + @SettingField(VrOptions.REALISTIC_DISMOUNT) + public boolean realisticDismountEnabled = true; @SettingField(VrOptions.BACKPACK_SWITCH) public boolean backpackSwitching = true; @SettingField(VrOptions.PHYSICAL_GUI) @@ -307,6 +315,8 @@ public enum UpdateType implements OptionEnum { public float renderScaleFactor = 1.0f; @SettingField(VrOptions.MIRROR_DISPLAY) public MirrorMode displayMirrorMode = MirrorMode.CROPPED; + @SettingField(VrOptions.MIRROR_CROP) + public float mirrorCrop = 0.15F; @SettingField(VrOptions.MIRROR_EYE) public boolean displayMirrorLeftEye = false; @SettingField(VrOptions.MIRROR_CENTER_SMOOTH) @@ -396,6 +406,8 @@ public enum UpdateType implements OptionEnum { public boolean seatedHudAltMode = true; @SettingField(VrOptions.AUTO_OPEN_KEYBOARD) public boolean autoOpenKeyboard = false; + @SettingField(VrOptions.AUTO_CLOSE_KEYBOARD) + public boolean autoCloseKeyboard = true; @SettingField public int forceHardwareDetection = 0; // 0 = off, 1 = vive, 2 = oculus @SettingField(VrOptions.RADIAL_MODE_HOLD) @@ -436,16 +448,22 @@ public enum UpdateType implements OptionEnum { public boolean showServerPluginMissingMessageAlways = true; @SettingField(VrOptions.CHAT_MESSAGE_STENCIL) public boolean showChatMessageStencil = true; - @SettingField + @SettingField(value = VrOptions.VR_ENABLED, config = "vrEnabled") public boolean vrEnabled = false; + @SettingField(VrOptions.VR_REMEMBER_ENABLED) + public boolean rememberVr = true; @SettingField(VrOptions.VR_HOTSWITCH) public boolean vrHotswitchingEnabled = true; - @SettingField + @SettingField(value = VrOptions.VR_TOGGLE_BUTTON_VISIBLE, config = "vrToggleButtonEnabled") public boolean vrToggleButtonEnabled = true; - @SettingField + @SettingField(value = VrOptions.VR_SETTINGS_BUTTON_VISIBLE, config = "vrSettingsButtonEnabled") public boolean vrSettingsButtonEnabled = true; - @SettingField + @SettingField(value = VrOptions.VR_SETTINGS_BUTTON_POSITION, config = "vrSettingsButtonPositionLeft") public boolean vrSettingsButtonPositionLeft = true; + @SettingField + public boolean disableGarbageCollectorMessage = false; + @SettingField + public boolean selfButtSparklesInFirstPerson = false; /** * This isn't actually used, it's only a dummy field to save the value from vanilla Options. @@ -883,12 +901,20 @@ public void resetSettings() { } public String getButtonDisplayString(VrOptions par1EnumOptions) { + return getButtonDisplayString(par1EnumOptions, false); + } + + public String getButtonDisplayString(VrOptions par1EnumOptions, boolean valueOnly) { String var2 = I18n.get("vivecraft.options." + par1EnumOptions.name()); String var3 = var2 + ": "; String var4 = var3; String var5; + if (valueOnly) { + var4 = ""; + } + try { var mapping = fieldEnumMap.get(par1EnumOptions); if (mapping == null) { @@ -1030,6 +1056,15 @@ record ConfigEntry(Field field, VrOptions vrOptions, String configName, boolean public enum VrOptions { DUMMY(false, true), // Dummy + VR_PLUGIN(false, true), // vr plugin to use + VR_ENABLED(false, true) { // vr or nonvr + + @Override + void onOptionChange() { + VRState.vrEnabled = ClientDataHolderVR.getInstance().vrSettings.vrEnabled; + } + }, + VR_REMEMBER_ENABLED(false, true), // restore vr state on startup HUD_SCALE(true, false, 0.35f, 2.5f, 0.01f, -1), // Head HUD Size HUD_DISTANCE(true, false, 0.25f, 5.0f, 0.01f, 2) { // Head HUD Distance @@ -1159,6 +1194,7 @@ Object convertOption(String value) { SHOW_PLUGIN_MISSING(false, true, "vivecraft.options.always", "vivecraft.options.once"), CHAT_MESSAGE_STENCIL(false, true), // warning for other mod using stencil AUTO_OPEN_KEYBOARD(false, true), // Always Open Keyboard + AUTO_CLOSE_KEYBOARD(false, true), // Close Keyboard on Screenchange RADIAL_MODE_HOLD(false, true, "vivecraft.options.hold", "vivecraft.options.press"), // Radial Menu Mode PHYSICAL_KEYBOARD(false, true, "vivecraft.options.keyboard.physical", "vivecraft.options.keyboard.pointer"), // Keyboard Type PHYSICAL_KEYBOARD_SCALE(true, false, 0.75f, 1.5f, 0.01f, -1) { // Keyboard Size @@ -1196,6 +1232,9 @@ void onOptionChange() { } }, HUD_MAX_GUI_SCALE(false, true), // force HUD to render with max GUI scale + VR_TOGGLE_BUTTON_VISIBLE(false, true), // toggle in main menu + VR_SETTINGS_BUTTON_VISIBLE(false, true), // setting button in options + VR_SETTINGS_BUTTON_POSITION(false, true, "vivecraft.options.left", "vivecraft.options.right"), // setting button position //HMD/render FSAA(false, true), // Lanczos Scaler LOW_HEALTH_INDICATOR(false, true), // red low health pulse @@ -1225,6 +1264,7 @@ void onOptionChange() { } } }, + MIRROR_CROP(true, false, 0.0f, 0.25f, 0.01f, -1), // crop amount for mirror, MIRROR_EYE(false, true, "vivecraft.options.left", "vivecraft.options.right"), // Mirror Eye MIRROR_CENTER_SMOOTH(true, false, 0.0f, 1.0f, 0.1f, 1) { @Override @@ -1580,6 +1620,7 @@ Object loadOption(String value) { REALISTIC_CLIMB(false, true), // Roomscale Climbing REALISTIC_SWIM(false, true), // Roomscale Swimming REALISTIC_ROW(false, true), // Roomscale Rowing + REALISTIC_DISMOUNT(false, true), // Roomscale Dismounting WALK_MULTIPLIER(true, false, 1f, 10f, 0.1f, 1), // Walking Multiplier FREEMOVE_MODE(false, true) { // Free Move Type @@ -2104,6 +2145,7 @@ private ServerOverrides() { registerSetting(VrOptions.TELEPORT_DOWN_LIMIT, "teleportLimitDown", () -> vrTeleportDownLimit); registerSetting(VrOptions.TELEPORT_HORIZ_LIMIT, "teleportLimitHoriz", () -> vrTeleportHorizLimit); registerSetting(VrOptions.WORLD_SCALE, "worldScale", () -> worldScale); + registerSetting(VrOptions.THIRDPERSON_ITEMTRANSFORMS, "thirdPersonItems", () -> thirdPersonItems); } private void registerSetting(VrOptions option, String networkName, Supplier originalValue) { diff --git a/common/src/main/java/org/vivecraft/common/network/BufferSerializable.java b/common/src/main/java/org/vivecraft/common/network/BufferSerializable.java new file mode 100644 index 000000000..b852e043d --- /dev/null +++ b/common/src/main/java/org/vivecraft/common/network/BufferSerializable.java @@ -0,0 +1,7 @@ +package org.vivecraft.common.network; + +import net.minecraft.network.FriendlyByteBuf; + +public interface BufferSerializable { + void serialize(FriendlyByteBuf buf); +} diff --git a/common/src/main/java/org/vivecraft/common/network/Pose.java b/common/src/main/java/org/vivecraft/common/network/Pose.java index 5b652f71e..0d29d644c 100644 --- a/common/src/main/java/org/vivecraft/common/network/Pose.java +++ b/common/src/main/java/org/vivecraft/common/network/Pose.java @@ -4,7 +4,7 @@ import net.minecraft.world.phys.Vec3; import org.vivecraft.common.utils.math.Quaternion; -public record Pose(Vec3 position, Quaternion orientation) { +public record Pose(Vec3 position, Quaternion orientation) implements BufferSerializable { public static Pose deserialize(FriendlyByteBuf byteBuf) { return new Pose(CommonNetworkHelper.deserializeFVec3(byteBuf), CommonNetworkHelper.deserializeVivecraftQuaternion(byteBuf)); diff --git a/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java b/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java index a46cfbc8b..cc8c5bc30 100644 --- a/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java +++ b/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java @@ -13,7 +13,7 @@ import java.nio.FloatBuffer; public record VrPlayerState(boolean seated, Pose hmd, boolean reverseHands, Pose controller0, - boolean reverseHands1legacy, Pose controller1) { + boolean reverseHands1legacy, Pose controller1) implements BufferSerializable { public static VrPlayerState create(VRPlayer vrPlayer) { return new VrPlayerState( diff --git a/common/src/main/java/org/vivecraft/mixin/client/ResourceLoadStateTrackerMixin.java b/common/src/main/java/org/vivecraft/mixin/client/ResourceLoadStateTrackerMixin.java index b0f39ecde..0633ba068 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/ResourceLoadStateTrackerMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/ResourceLoadStateTrackerMixin.java @@ -1,14 +1,41 @@ package org.vivecraft.mixin.client; import net.minecraft.client.ResourceLoadStateTracker; +import org.jetbrains.annotations.Nullable; 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.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRState; -@Mixin(ResourceLoadStateTracker.class) +// we want to be late here, because some mods initialize keybinds after the first reload +@Mixin(value = ResourceLoadStateTracker.class, priority = 9999) public abstract class ResourceLoadStateTrackerMixin { + + @Shadow + @Nullable + private ResourceLoadStateTracker.ReloadState reloadState; + + @Inject(at = @At("TAIL"), method = "finishReload") + void vivecraft$initializeVR(CallbackInfo ci) { + if (reloadState != null && reloadState.reloadReason == ResourceLoadStateTracker.ReloadReason.INITIAL) { + // init vr after first resource loading + try { + if (ClientDataHolderVR.getInstance().vrSettings.vrEnabled && ClientDataHolderVR.getInstance().vrSettings.rememberVr) { + VRState.vrEnabled = true; + VRState.initializeVR(); + } else { + ClientDataHolderVR.getInstance().vrSettings.vrEnabled = false; + ClientDataHolderVR.getInstance().vrSettings.saveOptions(); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + } + @Inject(at = @At("HEAD"), method = "startReload") void vivecraft$startReloadMixin(CallbackInfo ci) { if (ClientDataHolderVR.getInstance().menuWorldRenderer != null) { diff --git a/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java b/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java index 0b4f058ed..5163a16be 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java @@ -9,14 +9,12 @@ import net.minecraft.client.renderer.ShaderInstance; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL30; -import org.spongepowered.asm.mixin.Debug; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.*; import org.vivecraft.client.extensions.RenderTargetExtension; -@Debug(export = true) @Mixin(RenderTarget.class) public abstract class RenderTargetMixin implements RenderTargetExtension { diff --git a/common/src/main/java/org/vivecraft/mixin/client/gui/screens/TitleScreenMixin.java b/common/src/main/java/org/vivecraft/mixin/client/gui/screens/TitleScreenMixin.java index 3615a4b15..2a159ad3c 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/gui/screens/TitleScreenMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/gui/screens/TitleScreenMixin.java @@ -73,7 +73,7 @@ protected TitleScreenMixin(Component component) { vivecraft$updateButton.visible = UpdateChecker.hasUpdate; if (vivecraft$vrModeButton.visible && vivecraft$vrModeButton.isMouseOver(i, j)) { - renderTooltip(poseStack, font.split(Component.translatable("vivecraft.options.VR_MODE.tooltip"), Math.max(width / 2 - 43, 170)), i, j); + renderTooltip(poseStack, font.split(Component.translatable("vivecraft.options.VR_ENABLED.tooltip"), Math.max(width / 2 - 43, 170)), i, j); } if (VRState.vrInitialized && !VRState.vrRunning) { Component hotswitchMessage = Component.translatable("vivecraft.messages.vrhotswitchinginfo"); diff --git a/common/src/main/java/org/vivecraft/mixin/client/main/MainMixin.java b/common/src/main/java/org/vivecraft/mixin/client/main/MainMixin.java index 3dc109558..dcccd58f0 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/main/MainMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/main/MainMixin.java @@ -6,25 +6,21 @@ 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.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.vivecraft.client_vr.ClientDataHolderVR; @Mixin(Main.class) public class MainMixin { - @Inject(at = @At(value = "INVOKE", target = "Ljoptsimple/OptionParser;allowsUnrecognizedOptions()V", remap = false), method = "run", locals = LocalCapture.CAPTURE_FAILHARD) - private static void vivecraft$options(String[] strings, boolean bl, CallbackInfo ci, OptionParser optionparser) { - optionparser.accepts("kiosk"); - optionparser.accepts("viewonly"); - optionparser.accepts("katvr"); - optionparser.accepts("infinadeck"); - } - - @Redirect(at = @At(value = "INVOKE", target = "Ljoptsimple/OptionParser;parse([Ljava/lang/String;)Ljoptsimple/OptionSet;", remap = false), method = "run") - private static OptionSet vivecraft$kiosk(OptionParser optionparser, String[] p_129642_) { - OptionSet optionset = optionparser.parse(p_129642_); + @Inject(at = @At("HEAD"), method = "main", remap = false) + private static void vivecraft$options(String[] strings, CallbackInfo ci) { + OptionParser vivecraftOptionParser = new OptionParser(); + vivecraftOptionParser.allowsUnrecognizedOptions(); + vivecraftOptionParser.accepts("kiosk"); + vivecraftOptionParser.accepts("viewonly"); + vivecraftOptionParser.accepts("katvr"); + vivecraftOptionParser.accepts("infinadeck"); + OptionSet optionset = vivecraftOptionParser.parse(strings); ClientDataHolderVR.kiosk = optionset.has("kiosk"); if (ClientDataHolderVR.kiosk) { @@ -41,6 +37,5 @@ public class MainMixin { ClientDataHolderVR.katvr = optionset.has("katvr"); ClientDataHolderVR.infinadeck = optionset.has("infinadeck"); - return optionset; } } diff --git a/common/src/main/java/org/vivecraft/mixin/client/particle/SparkParticleMixin.java b/common/src/main/java/org/vivecraft/mixin/client/particle/SparkParticleMixin.java new file mode 100644 index 000000000..287a65a91 --- /dev/null +++ b/common/src/main/java/org/vivecraft/mixin/client/particle/SparkParticleMixin.java @@ -0,0 +1,36 @@ +package org.vivecraft.mixin.client.particle; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.Camera; +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.vivecraft.client.extensions.SparkParticleExtension; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRState; +import org.vivecraft.client_vr.render.RenderPass; + +import java.util.UUID; +import java.util.stream.Stream; + +@Mixin(targets = "net.minecraft.client.particle.FireworkParticles$SparkParticle") +public class SparkParticleMixin implements SparkParticleExtension { + @Unique + private UUID vivecraft$playerUUID; + + @Inject(at = @At("HEAD"), method = "render", cancellable = true) + private void vivecraft$hideSelfButtSparkles(VertexConsumer vertexConsumer, Camera camera, float f, CallbackInfo ci) { + if (!ClientDataHolderVR.getInstance().vrSettings.selfButtSparklesInFirstPerson + && camera.getEntity().getUUID().equals(this.vivecraft$playerUUID) && ((!VRState.vrRunning && !camera.isDetached()) + || (VRState.vrRunning && Stream.of(RenderPass.LEFT, RenderPass.RIGHT, RenderPass.CENTER).anyMatch(pass -> ClientDataHolderVR.getInstance().currentPass == pass)))) { + ci.cancel(); + } + } + + @Override + public void vivecraft$setPlayerUUID(UUID playerUUID) { + this.vivecraft$playerUUID = playerUUID; + } +} diff --git a/common/src/main/java/org/vivecraft/mixin/client/player/AbstractClientPlayerMixin.java b/common/src/main/java/org/vivecraft/mixin/client/player/AbstractClientPlayerMixin.java index 969c238d7..458444c21 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/player/AbstractClientPlayerMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/player/AbstractClientPlayerMixin.java @@ -8,12 +8,12 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.vivecraft.client.network.PatreonReceiver; +import org.vivecraft.client.network.SupporterReceiver; @Mixin(AbstractClientPlayer.class) public class AbstractClientPlayerMixin { @Inject(method = "", at = @At("TAIL")) private void vivecraft$addPatreonInfo(ClientLevel clientLevel, GameProfile gameProfile, ProfilePublicKey profilePublicKey, CallbackInfo ci) { - PatreonReceiver.addPlayerInfo(((AbstractClientPlayer) (Object) this)); + SupporterReceiver.addPlayerInfo(((AbstractClientPlayer) (Object) this)); } } diff --git a/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/ItemRendererVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/ItemRendererVRMixin.java index 0cc41e0f9..dc3a9d0a8 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/ItemRendererVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/ItemRendererVRMixin.java @@ -10,6 +10,8 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.gameplay.trackers.ClimbTracker; import org.vivecraft.client_vr.gameplay.trackers.TelescopeTracker; @Mixin(ItemRenderer.class) @@ -20,8 +22,14 @@ public class ItemRendererVRMixin { private ItemModelShaper itemModelShaper; @ModifyVariable(at = @At(value = "STORE"), method = "getModel") - public BakedModel vivecraft$spyglassOverride(BakedModel bakedModel, ItemStack itemStack) { - return itemStack.is(Items.SPYGLASS) ? itemModelShaper.getModelManager().getModel(TelescopeTracker.scopeModel) : bakedModel; + public BakedModel vivecraft$modelOverride(BakedModel bakedModel, ItemStack itemStack) { + if (itemStack.is(Items.SPYGLASS)) { + return itemModelShaper.getModelManager().getModel(TelescopeTracker.scopeModel); + } + if (ClientDataHolderVR.getInstance().climbTracker.isClaws(itemStack)) { + return itemModelShaper.getModelManager().getModel(ClimbTracker.clawsModel); + } + return bakedModel; } // hand item fade diff --git a/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/PlayerRendererMixin.java b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/LivingEntityRendererMixin.java similarity index 91% rename from common/src/main/java/org/vivecraft/mixin/client/renderer/entity/PlayerRendererMixin.java rename to common/src/main/java/org/vivecraft/mixin/client/renderer/entity/LivingEntityRendererMixin.java index b9b019772..498785933 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/PlayerRendererMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/LivingEntityRendererMixin.java @@ -6,6 +6,7 @@ import net.minecraft.client.model.PlayerModel; import net.minecraft.client.model.geom.EntityModelSet; import net.minecraft.client.model.geom.ModelLayers; +import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.entity.LivingEntityRenderer; import net.minecraft.client.renderer.entity.RenderLayerParent; @@ -14,7 +15,11 @@ import net.minecraft.client.renderer.entity.player.PlayerRenderer; import net.minecraft.world.entity.LivingEntity; 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.CallbackInfoReturnable; import org.vivecraft.client.extensions.EntityRenderDispatcherExtension; import org.vivecraft.client.extensions.RenderLayerExtension; import org.vivecraft.client.utils.RenderLayerTypes; @@ -31,16 +36,18 @@ * so mods could add it manually, but some mods hardcode only the slim/default model, * and that would mean the VRPlayerRenderers would be missing those layers completely */ -@Mixin(PlayerRenderer.class) -public abstract class PlayerRendererMixin> extends LivingEntityRenderer { +@Mixin(LivingEntityRenderer.class) +public abstract class LivingEntityRendererMixin> extends EntityRenderer { - // dummy constructor - public PlayerRendererMixin(EntityRendererProvider.Context context, M entityModel, float f) { - super(context, entityModel, f); + @Shadow + protected M model; + + protected LivingEntityRendererMixin(EntityRendererProvider.Context context) { + super(context); } - @Override - public boolean addLayer(RenderLayer renderLayer) { + @Inject(at = @At("HEAD"), method = "addLayer") + public void vivecraft$copyLayer(RenderLayer renderLayer, CallbackInfoReturnable cir) { // check if the layer gets added from the PlayerRenderer, we don't want to copy, if we add it to the VRPlayerRenderer // also check that the VRPlayerRenderers were created, this method also gets called in the constructor, // those default Layers already are added to the VRPlayerRenderer there @@ -91,7 +98,6 @@ public boolean addLayer(RenderLayer renderLayer) { } } } - return super.addLayer(renderLayer); } /** diff --git a/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/layers/ItemInHandLayerMixin.java b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/layers/ItemInHandLayerMixin.java new file mode 100644 index 000000000..8304f2f18 --- /dev/null +++ b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/layers/ItemInHandLayerMixin.java @@ -0,0 +1,39 @@ +package org.vivecraft.mixin.client.renderer.entity.layers; + +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.client.player.RemotePlayer; +import net.minecraft.client.renderer.entity.layers.ItemInHandLayer; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.vivecraft.client.VRPlayersClient; +import org.vivecraft.client.network.ClientNetworking; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRState; +import org.vivecraft.client_vr.extensions.PlayerExtension; +import org.vivecraft.client_vr.gameplay.trackers.ClimbTracker; + +@Mixin(ItemInHandLayer.class) +public abstract class ItemInHandLayerMixin { + @ModifyVariable(at = @At("HEAD"), method = "renderArmWithItem", argsOnly = true) + private ItemStack vivecraft$climbClawsOverride(ItemStack itemStack, LivingEntity livingEntity, ItemStack itemStack2, ItemDisplayContext itemDisplayContext, HumanoidArm humanoidArm) { + ClimbTracker tracker = ClientDataHolderVR.getInstance().climbTracker; + if (ClientNetworking.serverAllowsClimbey && livingEntity instanceof Player && !tracker.isClaws(itemStack)) { + ItemStack otherStack = humanoidArm == livingEntity.getMainArm() ? livingEntity.getOffhandItem() : livingEntity.getMainHandItem(); + if (tracker.isClaws(otherStack)) { + if (livingEntity instanceof LocalPlayer player && VRState.vrRunning && tracker.isActive(player) && ((PlayerExtension) player).vivecraft$isClimbeyClimbEquipped()) { + return otherStack; + } else if (livingEntity instanceof RemotePlayer player && VRPlayersClient.getInstance().isVRPlayer(player) && !VRPlayersClient.getInstance().getRotationsForPlayer(player.getUUID()).seated) { + return otherStack; + } + } + } + + return itemStack; + } +} diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardHandlerVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardHandlerVRMixin.java index bbf4dad1e..2ecd736c4 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardHandlerVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardHandlerVRMixin.java @@ -35,7 +35,9 @@ public class KeyboardHandlerVRMixin { public void vivecraft$screenHandler(long l, int i, int j, int k, int m, CallbackInfo ci) { if (i == 256 && k == 1) { if (org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler.Showing) { - org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler.setOverlayShowing(false); + if (ClientDataHolderVR.getInstance().vrSettings.autoCloseKeyboard) { + org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler.setOverlayShowing(false); + } if (this.minecraft.screen instanceof ChatScreen) { minecraft.screen.onClose(); } diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java index 5ef45518d..15231622c 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java @@ -13,8 +13,7 @@ import net.minecraft.client.*; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.screens.Overlay; -import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.*; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.multiplayer.MultiPlayerGameMode; @@ -50,9 +49,11 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.vivecraft.client.VRPlayersClient; import org.vivecraft.client.VivecraftVRMod; +import org.vivecraft.client.Xplat; import org.vivecraft.client.extensions.RenderTargetExtension; import org.vivecraft.client.gui.VivecraftClickEvent; import org.vivecraft.client.gui.screens.ErrorScreen; +import org.vivecraft.client.gui.screens.GarbageCollectorScreen; import org.vivecraft.client.gui.screens.UpdateScreen; import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.client.utils.UpdateChecker; @@ -248,16 +249,6 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { "lambda$new$3"} // forge , remap = false) public void vivecraft$initVROnLaunch(CallbackInfo ci) { - // init vr after resource loading - try { - if (ClientDataHolderVR.getInstance().vrSettings.vrEnabled) { - VRState.vrEnabled = true; - VRState.initializeVR(); - } - } catch (Exception exception) { - exception.printStackTrace(); - } - // set initial resourcepacks vivecraft$resourcepacks = resourceManager.listPacks().map(PackResources::getName).toList(); @@ -272,6 +263,32 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { } } + @Inject(at = @At("TAIL"), method = "") + private void vivecraft$showGarbageCollectorScreenFabric(CallbackInfo ci) { + if ("fabric".equals(Xplat.getModloader())) { + vivecraft$showGarbageCollectorScreen(); + } + } + @Inject(at = @At("TAIL"), method = "lambda$new$2", remap = false, require = 0, expect = 0) + private void vivecraft$showGarbageCollectorScreenForge(CallbackInfo ci) { + if ("forge".equals(Xplat.getModloader())) { + vivecraft$showGarbageCollectorScreen(); + } + } + + @Unique + private void vivecraft$showGarbageCollectorScreen() { + // set the Garbage collector screen here, when it got reset after loading, but don't set it when using quickplay, because it would be removed after loading has finished + if (VRState.vrEnabled && !ClientDataHolderVR.getInstance().incorrectGarbageCollector.isEmpty() + && !(screen instanceof LevelLoadingScreen + || screen instanceof ReceivingLevelScreen + || screen instanceof ConnectScreen + || screen instanceof GarbageCollectorScreen)) { + Minecraft.getInstance().setScreen(new GarbageCollectorScreen(ClientDataHolderVR.getInstance().incorrectGarbageCollector)); + ClientDataHolderVR.getInstance().incorrectGarbageCollector = ""; + } + } + @Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/Minecraft;delayedCrash:Ljava/util/function/Supplier;", shift = Shift.BEFORE), method = "destroy()V") public void vivecraft$destroy(CallbackInfo info) { try { @@ -625,6 +642,13 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { // VR enabled only chat notifications if (VRState.vrInitialized && this.level != null && ClientDataHolderVR.getInstance().vrPlayer != null) { + if (!ClientDataHolderVR.getInstance().incorrectGarbageCollector.isEmpty()) { + if (!(screen instanceof GarbageCollectorScreen)) { + // set the Garbage collector screen here, quickplay is used, this shouldn't be triggered in other cases, since the GarbageCollectorScreen resets the string on closing + Minecraft.getInstance().setScreen(new GarbageCollectorScreen(ClientDataHolderVR.getInstance().incorrectGarbageCollector)); + } + ClientDataHolderVR.getInstance().incorrectGarbageCollector = ""; + } if (ClientDataHolderVR.getInstance().vrPlayer.chatWarningTimer >= 0 && --ClientDataHolderVR.getInstance().vrPlayer.chatWarningTimer == 0) { boolean showMessage = !ClientNetworking.displayedChatWarning || ClientDataHolderVR.getInstance().vrSettings.showServerPluginMissingMessageAlways; @@ -681,6 +705,15 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { VRPlayersClient.getInstance().tick(); + this.profiler.popPush("Vivecraft Keybindings"); + vivecraft$processAlwaysAvailableKeybindings(); + + this.profiler.pop(); + } + + @Unique + private void vivecraft$processAlwaysAvailableKeybindings() { + // menuworld export if (VivecraftVRMod.INSTANCE.keyExportWorld.consumeClick() && level != null && player != null) { Throwable error = null; try { @@ -735,7 +768,17 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { } } - this.profiler.pop(); + // quick commands + for (int i = 0; i < VivecraftVRMod.INSTANCE.keyQuickCommands.length; i++) { + if (VivecraftVRMod.INSTANCE.keyQuickCommands[i].consumeClick()) { + String command = ClientDataHolderVR.getInstance().vrSettings.vrQuickCommands[i]; + if (command.startsWith("/")) { + this.player.connection.sendCommand(command.substring(1)); + } else { + this.player.connection.sendChat(command); + } + } + } } @Redirect(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;pick(F)V"), method = "tick") @@ -910,6 +953,7 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { Minecraft.getInstance().getSoundManager().reload(); } resizeDisplay(); + window.updateVsync(options.enableVsync().get()); } @Unique @@ -977,8 +1021,8 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { source = ClientDataHolderVR.getInstance().vrRenderer.framebufferEye1; } - xcrop = 0.15F; - ycrop = 0.15F; + xcrop = ClientDataHolderVR.getInstance().vrSettings.mirrorCrop; + ycrop = ClientDataHolderVR.getInstance().vrSettings.mirrorCrop; ar = true; } // Debug diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/blaze3d/systems/RenderSystemVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/blaze3d/systems/RenderSystemVRMixin.java index 4f4b6385e..a0a5424f6 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/blaze3d/systems/RenderSystemVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/blaze3d/systems/RenderSystemVRMixin.java @@ -7,6 +7,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.vivecraft.client_vr.VRState; +import org.vivecraft.client_vr.provider.MCVR; import static com.mojang.blaze3d.systems.RenderSystem.blendFuncSeparate; @@ -22,7 +23,7 @@ public class RenderSystemVRMixin { @Inject(at = @At("HEAD"), method = "limitDisplayFPS", cancellable = true) private static void vivecraft$noFPSlimit(CallbackInfo ci) { - if (VRState.vrRunning) { + if (VRState.vrRunning && !MCVR.get().capFPS()) { ci.cancel(); } } diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/gui/GuiVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/gui/GuiVRMixin.java index 619652067..099ce041d 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/gui/GuiVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/gui/GuiVRMixin.java @@ -223,20 +223,22 @@ public abstract class GuiVRMixin extends GuiComponent implements GuiExtension { RenderSystem.setShaderTexture(0, Screen.GUI_ICONS_LOCATION); float f = 16.0F * ClientDataHolderVR.getInstance().vrSettings.menuCrosshairScale; RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.ONE_MINUS_DST_COLOR, GlStateManager.DestFactor.ZERO, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE); - this.vivecraft$drawCentredTexturedModalRect(mouseX, mouseY, f, f, 0, 0, 15, 15); + this.vivecraft$drawCentredTexturedModalRect(mouseX, mouseY, f, f, 0, 0, 15F / 256F, 15F / 256F); RenderSystem.disableBlend(); } @Unique - public void vivecraft$drawCentredTexturedModalRect(int centreX, int centreY, float width, float height, int u, int v, int texWidth, int texHeight) { - float f = 0.00390625F; - float f1 = 0.00390625F; + public void vivecraft$drawCentredTexturedModalRect(int centreX, int centreY, float width, float height, float uMin, float vMin, float uMax, float vMax) { BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); - bufferbuilder.vertex((float) centreX - width / 2.0F, (float) centreY + height / 2.0F, this.getBlitOffset()).uv((float) (u) * f, (float) (v + texHeight) * f1).endVertex(); - bufferbuilder.vertex((float) centreX + width / 2.0F, (float) centreY + height / 2.0F, this.getBlitOffset()).uv((float) (u + texWidth) * f, (float) (v + texHeight) * f1).endVertex(); - bufferbuilder.vertex((float) centreX + width / 2.0F, (float) centreY - height / 2.0F, this.getBlitOffset()).uv((float) (u + texWidth) * f, (float) (v) * f1).endVertex(); - bufferbuilder.vertex((float) centreX - width / 2.0F, (float) centreY - height / 2.0F, this.getBlitOffset()).uv((float) (u) * f, (float) (v) * f1).endVertex(); + bufferbuilder.vertex((float) centreX - width / 2.0F, (float) centreY + height / 2.0F, 0) + .uv(uMin, vMin).endVertex(); + bufferbuilder.vertex((float) centreX + width / 2.0F, (float) centreY + height / 2.0F, 0) + .uv(uMin, vMax).endVertex(); + bufferbuilder.vertex((float) centreX + width / 2.0F, (float) centreY - height / 2.0F, 0) + .uv(uMax, vMax).endVertex(); + bufferbuilder.vertex((float) centreX - width / 2.0F, (float) centreY - height / 2.0F, 0) + .uv(uMax, vMin).endVertex(); BufferUploader.drawWithShader(bufferbuilder.end()); } } diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/gui/screens/inventory/CreativeModeInventoryScreenVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/gui/screens/inventory/CreativeModeInventoryScreenVRMixin.java index 200ca1b15..128ae9ddb 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/gui/screens/inventory/CreativeModeInventoryScreenVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/gui/screens/inventory/CreativeModeInventoryScreenVRMixin.java @@ -33,7 +33,7 @@ public CreativeModeInventoryScreenVRMixin(CreativeModeInventoryScreen.ItemPicker vivecraft$addCreativeSearch(this.searchBox.getValue(), this.menu.items); } - @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/CreativeModeTab;fillItemList(Lnet/minecraft/core/NonNullList;)V"), method = "selectTab") + @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/core/NonNullList;addAll(Ljava/util/Collection;)Z", ordinal = 1, shift = At.Shift.AFTER), method = "selectTab") public void vivecraft$fill(CreativeModeTab creativeModeTab, CallbackInfo ci) { vivecraft$addCreativeItems(creativeModeTab, this.menu.items); } @@ -49,14 +49,19 @@ public CreativeModeInventoryScreenVRMixin(CreativeModeInventoryScreen.ItemPicker } if (tab == CreativeModeTab.TAB_TOOLS || tab == null) { - ItemStack itemstack3 = (new ItemStack(Items.LEATHER_BOOTS)).setHoverName(Component.translatable("vivecraft.item.jumpboots")); - itemstack3.getTag().putBoolean("Unbreakable", true); - itemstack3.getTag().putInt("HideFlags", 4); - ItemStack itemstack4 = (new ItemStack(Items.SHEARS)).setHoverName(Component.translatable("vivecraft.item.climbclaws")); - itemstack4.getTag().putBoolean("Unbreakable", true); - itemstack4.getTag().putInt("HideFlags", 4); - list.add(itemstack3); - list.add(itemstack4); + ItemStack boots = new ItemStack(Items.LEATHER_BOOTS); + boots.setHoverName(Component.translatableWithFallback("vivecraft.item.jumpboots", "Jump Boots")); + boots.getTag().putBoolean("Unbreakable", true); + boots.getTag().putInt("HideFlags", 4); + boots.getOrCreateTagElement(ItemStack.TAG_DISPLAY).putInt(ItemStack.TAG_COLOR, 9233775); + + ItemStack claws = new ItemStack(Items.SHEARS); + claws.setHoverName(Component.translatableWithFallback("vivecraft.item.climbclaws", "Climb Claws")); + claws.getTag().putBoolean("Unbreakable", true); + claws.getTag().putInt("HideFlags", 4); + + list.add(boots); + list.add(claws); } } diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/gui/screens/inventory/SignEditScreenVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/gui/screens/inventory/SignEditScreenVRMixin.java index c1c7e989e..eeafb8e2b 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/gui/screens/inventory/SignEditScreenVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/gui/screens/inventory/SignEditScreenVRMixin.java @@ -5,6 +5,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRState; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; @@ -20,7 +21,7 @@ public class SignEditScreenVRMixin { @Inject(at = @At("HEAD"), method = "removed") public void vivecraft$dontShowOverlay(CallbackInfo ci) { - if (VRState.vrRunning) { + if (VRState.vrRunning && ClientDataHolderVR.getInstance().vrSettings.autoCloseKeyboard) { KeyboardHandler.setOverlayShowing(false); } } diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/lwjgl/OpenVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/lwjgl/OpenVRMixin.java new file mode 100644 index 000000000..601e38119 --- /dev/null +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/lwjgl/OpenVRMixin.java @@ -0,0 +1,85 @@ +package org.vivecraft.mixin.client_vr.lwjgl; + +import org.lwjgl.openvr.OpenVR; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import javax.annotation.Nullable; +import java.util.function.LongFunction; + +import static org.lwjgl.openvr.VR.*; + +@Mixin(value = OpenVR.class, remap = false) +public abstract class OpenVRMixin { + + @Shadow + @Nullable + public static OpenVR.IVRSystem VRSystem; + @Shadow + @Nullable + public static OpenVR.IVRChaperone VRChaperone; + @Shadow + @Nullable + public static OpenVR.IVRChaperoneSetup VRChaperoneSetup; + @Shadow + @Nullable + public static OpenVR.IVRCompositor VRCompositor; + @Shadow + @Nullable + public static OpenVR.IVROverlay VROverlay; + @Shadow + @Nullable + public static OpenVR.IVRRenderModels VRRenderModels; + @Shadow + @Nullable + public static OpenVR.IVRExtendedDisplay VRExtendedDisplay; + @Shadow + @Nullable + public static OpenVR.IVRSettings VRSettings; + @Shadow + @Nullable + public static OpenVR.IVRApplications VRApplications; + @Shadow + @Nullable + public static OpenVR.IVRScreenshots VRScreenshots; + @Shadow + @Nullable + public static OpenVR.IVRInput VRInput; + @Shadow + private static int token; + + @Shadow + @Nullable + private static T getGenericInterface(String interfaceNameVersion, LongFunction supplier) { + return null; + } + + /** + * @author CADIndie + * @reason Open Composite doesn't implement all function tables, so trying to assign them will make it crash + */ + @Overwrite + public static void create(int tok) { + token = tok; + + VRSystem = getGenericInterface(IVRSystem_Version, OpenVR.IVRSystem::new); + VRChaperone = getGenericInterface(IVRChaperone_Version, OpenVR.IVRChaperone::new); + VRChaperoneSetup = getGenericInterface(IVRChaperoneSetup_Version, OpenVR.IVRChaperoneSetup::new); + VRCompositor = getGenericInterface(IVRCompositor_Version, OpenVR.IVRCompositor::new); + VROverlay = getGenericInterface(IVROverlay_Version, OpenVR.IVROverlay::new); + // VRResources = getGenericInterface(IVRResources_Version, OpenVR.IVRResources::new); + VRRenderModels = getGenericInterface(IVRRenderModels_Version, OpenVR.IVRRenderModels::new); + VRExtendedDisplay = getGenericInterface(IVRExtendedDisplay_Version, OpenVR.IVRExtendedDisplay::new); + VRSettings = getGenericInterface(IVRSettings_Version, OpenVR.IVRSettings::new); + VRApplications = getGenericInterface(IVRApplications_Version, OpenVR.IVRApplications::new); + // VRTrackedCamera = getGenericInterface(IVRTrackedCamera_Version, OpenVR.IVRTrackedCamera::new); + VRScreenshots = getGenericInterface(IVRScreenshots_Version, OpenVR.IVRScreenshots::new); + // VRDriverManager = getGenericInterface(IVRDriverManager_Version, OpenVR.IVRDriverManager::new); + VRInput = getGenericInterface(IVRInput_Version, OpenVR.IVRInput::new); + // VRIOBuffer = getGenericInterface(IVRIOBuffer_Version, OpenVR.IVRIOBuffer::new); + // VRSpatialAnchors = getGenericInterface(IVRSpatialAnchors_Version, OpenVR.IVRSpatialAnchors::new); + // VRDebug = getGenericInterface(IVRDebug_Version, OpenVR.IVRDebug::new); + // VRNotifications = getGenericInterface(IVRNotifications_Version, OpenVR.IVRNotifications::new); + } +} diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/multiplayer/ClientPacketListenerVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/multiplayer/ClientPacketListenerVRMixin.java index 3f8c1038e..8266aa7b6 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/multiplayer/ClientPacketListenerVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/multiplayer/ClientPacketListenerVRMixin.java @@ -8,7 +8,6 @@ import net.minecraft.core.Registry; import net.minecraft.network.Connection; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.*; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundSource; @@ -21,7 +20,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import org.vivecraft.client.VRPlayersClient; import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRState; @@ -29,11 +27,11 @@ import org.vivecraft.client_vr.gameplay.screenhandlers.GuiHandler; import org.vivecraft.client_vr.provider.ControllerType; import org.vivecraft.client_vr.settings.VRSettings; -import org.vivecraft.common.VRServerPerms; import org.vivecraft.common.network.CommonNetworkHelper; @Mixin(ClientPacketListener.class) public class ClientPacketListenerVRMixin { + @Final @Shadow private Minecraft minecraft; @@ -41,7 +39,6 @@ public class ClientPacketListenerVRMixin { @Inject(at = @At("TAIL"), method = "") public void vivecraft$init(Minecraft minecraft, Screen screen, Connection connection, GameProfile gameProfile, ClientTelemetryManager clientTelemetryManager, CallbackInfo ci) { if (ClientNetworking.needsReset) { - ClientDataHolderVR.getInstance().vrSettings.overrides.resetAll(); ClientNetworking.resetServerSettings(); ClientNetworking.displayedChatMessage = false; ClientNetworking.displayedChatWarning = false; @@ -49,9 +46,12 @@ public class ClientPacketListenerVRMixin { } } - @Inject(at = @At("TAIL"), method = "handleLogin(Lnet/minecraft/network/protocol/game/ClientboundLoginPacket;)V") - public void vivecraft$login(ClientboundLoginPacket p_105030_, CallbackInfo callback) { - VRPlayersClient.clear(); + @Inject(at = @At("TAIL"), method = "handleLogin") + public void vivecraft$resetOnLogin(ClientboundLoginPacket p_105030_, CallbackInfo callback) { + // clear old data + ClientNetworking.resetServerSettings(); + + // request server data ClientNetworking.sendVersionInfo(); if (VRState.vrInitialized) { @@ -62,17 +62,27 @@ public class ClientPacketListenerVRMixin { } } - @Inject(at = @At("TAIL"), method = "onDisconnect") - public void vivecraft$disconnect(Component component, CallbackInfo ci) { - VRServerPerms.INSTANCE.setTeleportSupported(false); + @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setLevel(Lnet/minecraft/client/multiplayer/ClientLevel;)V", shift = At.Shift.AFTER), method = "handleRespawn") + public void vivecraft$resetOnDimensionChange(ClientboundRespawnPacket clientboundRespawnPacket, CallbackInfo ci) { + // clear old data + ClientNetworking.resetServerSettings(); + + // request server data + ClientNetworking.sendVersionInfo(); + if (VRState.vrInitialized) { - ClientDataHolderVR.getInstance().vrPlayer.setTeleportOverride(false); + // set the timer, even if vr is currently not running + ClientDataHolderVR.getInstance().vrPlayer.chatWarningTimer = 200; + ClientDataHolderVR.getInstance().vrPlayer.teleportWarning = true; + ClientDataHolderVR.getInstance().vrPlayer.vrSwitchWarning = false; } - ClientDataHolderVR.getInstance().vrSettings.overrides.resetAll(); } @Inject(at = @At("TAIL"), method = "cleanup") public void vivecraft$cleanup(CallbackInfo ci) { + ClientNetworking.resetServerSettings(); + ClientNetworking.displayedChatMessage = false; + ClientNetworking.displayedChatWarning = false; ClientNetworking.needsReset = true; } @@ -109,28 +119,12 @@ public class ClientPacketListenerVRMixin { } } - @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/MultiPlayerGameMode;adjustPlayer(Lnet/minecraft/world/entity/player/Player;)V", shift = At.Shift.BEFORE), method = "handleRespawn") - public void vivecraft$readdInput2(ClientboundRespawnPacket clientboundRespawnPacket, CallbackInfo ci) { - ClientNetworking.resetServerSettings(); - ClientNetworking.sendVersionInfo(); - if (VRState.vrInitialized) { - // set the timer, even if vr is currently not running - ClientDataHolderVR.getInstance().vrPlayer.chatWarningTimer = 200; - ClientDataHolderVR.getInstance().vrPlayer.teleportWarning = true; - ClientDataHolderVR.getInstance().vrPlayer.vrSwitchWarning = false; - } - } - - @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V", ordinal = 0, shift = At.Shift.AFTER), method = "handleRespawn(Lnet/minecraft/network/protocol/game/ClientboundRespawnPacket;)V") - public void vivecraft$respawn(ClientboundRespawnPacket packet, CallbackInfo callback) { - ClientDataHolderVR.getInstance().vrSettings.overrides.resetAll(); - } - - @Inject(at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/network/protocol/game/ClientboundCustomPayloadPacket;getData()Lnet/minecraft/network/FriendlyByteBuf;"), method = "handleCustomPayload(Lnet/minecraft/network/protocol/game/ClientboundCustomPayloadPacket;)V", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) - public void vivecraft$handlepacket(ClientboundCustomPayloadPacket p_105004_, CallbackInfo info, ResourceLocation channelID, FriendlyByteBuf buffer) { - if (channelID.equals(CommonNetworkHelper.CHANNEL)) { - var packetID = CommonNetworkHelper.PacketDiscriminators.values()[buffer.readByte()]; - ClientNetworking.handlePacket(packetID, buffer); + @Inject(at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/network/protocol/game/ClientboundCustomPayloadPacket;getData()Lnet/minecraft/network/FriendlyByteBuf;"), method = "handleCustomPayload", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) + public void vivecraft$handlepacket(ClientboundCustomPayloadPacket payloadPacket, CallbackInfo info, ResourceLocation channelID, FriendlyByteBuf buffer) { + if (CommonNetworkHelper.CHANNEL.equals(channelID)) { + ClientNetworking.handlePacket( + CommonNetworkHelper.PacketDiscriminators.values()[buffer.readByte()], + buffer); buffer.release(); info.cancel(); } diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java index 669972556..5202d1a30 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java @@ -297,6 +297,7 @@ public abstract class GameRendererVRMixin } } + // do remap because of forge @Inject(at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;viewport(IIII)V", shift = Shift.AFTER), method = "Lnet/minecraft/client/renderer/GameRenderer;render(FJZ)V") public void vivecraft$matrix(float partialTicks, long nanoTime, boolean renderWorldIn, CallbackInfo info) { this.resetProjectionMatrix(this.getProjectionMatrix(minecraft.options.fov().get())); @@ -304,6 +305,20 @@ public abstract class GameRendererVRMixin RenderSystem.applyModelViewMatrix(); } + @Inject(at = @At("HEAD"), method = "shouldRenderBlockOutline", cancellable = true) + public void vivecraft$shouldDrawBlockOutline(CallbackInfoReturnable cir) { + if (VRState.vrRunning) { + if (vivecraft$DATA_HOLDER.teleportTracker.isAiming() || vivecraft$DATA_HOLDER.vrSettings.renderBlockOutlineMode == VRSettings.RenderPointerElement.NEVER) { + // don't render outline when aiming with tp, or the user disabled it + cir.setReturnValue(false); + } else if (vivecraft$DATA_HOLDER.vrSettings.renderBlockOutlineMode == VRSettings.RenderPointerElement.ALWAYS) { + // skip vanilla check and always render the outline + cir.setReturnValue(true); + } + // VRSettings.RenderPointerElement.WITH_HUD uses the vanilla behaviour + } + } + @ModifyArg(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(FJLcom/mojang/blaze3d/vertex/PoseStack;)V"), method = "render") public PoseStack vivecraft$newStack(PoseStack poseStack) { this.vivecraft$stack = poseStack; diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemInHandRendererVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemInHandRendererVRMixin.java index d308a57ee..aa454c861 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemInHandRendererVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemInHandRendererVRMixin.java @@ -23,6 +23,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRState; import org.vivecraft.client_vr.extensions.EntityRenderDispatcherVRExtension; @@ -114,8 +115,13 @@ public abstract class ItemInHandRendererVRMixin implements ItemInHandRendererExt boolean useLeftHandModelinLeftHand = false; - ItemTransforms.TransformType transformType; - if (dh.vrSettings.thirdPersonItems && !(BowTracker.isBow(pStack) && dh.bowTracker.isActive((LocalPlayer) pPlayer))) { + // swap hand for claws, since it's backwards else wise + if (dh.climbTracker.isClaws(pStack) && dh.vrSettings.reverseHands) { + mainHand = !mainHand; + } + + ItemDisplayContext itemDisplayContext; + if ((ClientNetworking.isThirdPersonItems() && !(BowTracker.isBow(pStack) && dh.bowTracker.isActive((LocalPlayer) pPlayer))) || dh.climbTracker.isClaws(pStack)) { useLeftHandModelinLeftHand = true; //test VivecraftItemRendering.applyThirdPersonItemTransforms(pMatrixStack, rendertype, mainHand, pPlayer, pEquippedProgress, pPartialTicks, pStack, pHand); transformType = mainHand ? ItemTransforms.TransformType.THIRD_PERSON_RIGHT_HAND : (useLeftHandModelinLeftHand ? ItemTransforms.TransformType.THIRD_PERSON_LEFT_HAND : ItemTransforms.TransformType.THIRD_PERSON_RIGHT_HAND); diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemPropertiesVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemPropertiesVRMixin.java index 88baf8766..29d662b44 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemPropertiesVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemPropertiesVRMixin.java @@ -7,7 +7,6 @@ import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Group; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.vivecraft.client_vr.VRState; @@ -15,21 +14,10 @@ @Mixin(ItemProperties.class) public class ItemPropertiesVRMixin { - @Group(name = "disableGoatHornAnimation", min = 1, max = 1) - @Inject(at = @At("HEAD"), method = "method_43611" // fabric - , remap = false, cancellable = true, expect = 0) + @Inject(at = @At("HEAD"), method = "method_43611", cancellable = true) private static void vivecraft$noHornUseAnimFabric(ItemStack itemStack, ClientLevel clientLevel, LivingEntity livingEntity, int i, CallbackInfoReturnable cir) { if (VRState.vrRunning && livingEntity == Minecraft.getInstance().player) { cir.setReturnValue(0.0F); } } - - @Group(name = "disableGoatHornAnimation", min = 1, max = 1) - @Inject(at = @At("HEAD"), method = "m_234977_" // forge - , remap = false, cancellable = true, expect = 0) - private static void vivecraft$noHornUseAnimForge(ItemStack itemStack, ClientLevel clientLevel, LivingEntity livingEntity, int i, CallbackInfoReturnable cir) { - if (VRState.vrRunning && livingEntity == Minecraft.getInstance().player) { - cir.setReturnValue(0.0F); - } - } } diff --git a/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java b/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java index 727cc313e..4227edfeb 100644 --- a/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java @@ -8,7 +8,6 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.server.network.ServerPlayerConnection; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -21,10 +20,8 @@ import org.vivecraft.server.ServerVRPlayers; import org.vivecraft.server.config.ServerConfig; -import static org.vivecraft.common.network.CommonNetworkHelper.PacketDiscriminators.CLIMBING; - @Mixin(ServerGamePacketListenerImpl.class) -public abstract class ServerGamePacketListenerImplMixin implements ServerPlayerConnection, ServerGamePacketListener { +public abstract class ServerGamePacketListenerImplMixin implements ServerGamePacketListener { @Shadow @Final @@ -40,7 +37,7 @@ public abstract class ServerGamePacketListenerImplMixin implements ServerPlayerC @Shadow private int aboveGroundTickCount; - @Inject(at = @At("TAIL"), method = "(Lnet/minecraft/server/MinecraftServer;Lnet/minecraft/network/Connection;Lnet/minecraft/server/level/ServerPlayer;)V") + @Inject(at = @At("TAIL"), method = "") public void vivecraft$init(MinecraftServer p_9770_, Connection p_9771_, ServerPlayer p_9772_, CallbackInfo info) { // Vivecraft if (this.connection.channel != null && this.connection.channel.pipeline().get("packet_handler") != null) { //fake player fix @@ -54,18 +51,22 @@ public abstract class ServerGamePacketListenerImplMixin implements ServerPlayerC ServerNetworking.sendVrPlayerStateToClients(this.player); } - @Inject(at = @At("TAIL"), method = "handleCustomPayload(Lnet/minecraft/network/protocol/game/ServerboundCustomPayloadPacket;)V") - public void vivecraft$handleVivecraftPackets(ServerboundCustomPayloadPacket pPacket, CallbackInfo info) { - var buffer = pPacket.getData(); - var channelID = pPacket.getIdentifier(); + /** + * handle server bound vivecraft packets + */ + @Inject(at = @At("HEAD"), method = "handleCustomPayload", cancellable = true) + public void vivecraft$handleVivecraftPackets(ServerboundCustomPayloadPacket payloadPacket, CallbackInfo ci) { + if (CommonNetworkHelper.CHANNEL.equals(payloadPacket.getIdentifier())) { + PacketUtils.ensureRunningOnSameThread(payloadPacket, this, this.player.getLevel()); + + CommonNetworkHelper.PacketDiscriminators packetId = CommonNetworkHelper.PacketDiscriminators.values()[payloadPacket.getData().readByte()]; + + ServerNetworking.handlePacket(packetId, payloadPacket.getData(), this.player, ((ServerGamePacketListenerImpl) (Object) this)::send); - if (channelID.equals(CommonNetworkHelper.CHANNEL)) { - PacketUtils.ensureRunningOnSameThread(pPacket, this, this.player.getLevel()); - CommonNetworkHelper.PacketDiscriminators packetDiscriminator = CommonNetworkHelper.PacketDiscriminators.values()[buffer.readByte()]; - ServerNetworking.handlePacket(packetDiscriminator, buffer, (ServerGamePacketListenerImpl) (Object) this); - if (packetDiscriminator == CLIMBING) { + if (packetId == CommonNetworkHelper.PacketDiscriminators.CLIMBING) { this.aboveGroundTickCount = 0; } + ci.cancel(); } } diff --git a/common/src/main/java/org/vivecraft/mixin/server/TrackedEntityAccessor.java b/common/src/main/java/org/vivecraft/mixin/server/TrackedEntityAccessor.java index 9e20b0b89..c98becc5c 100644 --- a/common/src/main/java/org/vivecraft/mixin/server/TrackedEntityAccessor.java +++ b/common/src/main/java/org/vivecraft/mixin/server/TrackedEntityAccessor.java @@ -6,7 +6,7 @@ import java.util.Set; -@Mixin(targets = "net/minecraft/server/level/ChunkMap$TrackedEntity") +@Mixin(targets = "net.minecraft.server.level.ChunkMap$TrackedEntity") public interface TrackedEntityAccessor { @Accessor("seenBy") diff --git a/common/src/main/java/org/vivecraft/mixin/world/item/crafting/ShapedRecipeMixin.java b/common/src/main/java/org/vivecraft/mixin/world/item/crafting/ShapedRecipeMixin.java index 49562a77a..acaa38707 100644 --- a/common/src/main/java/org/vivecraft/mixin/world/item/crafting/ShapedRecipeMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/world/item/crafting/ShapedRecipeMixin.java @@ -50,9 +50,18 @@ public class ShapedRecipeMixin { throw new JsonSyntaxException("Invalid output count: " + i); } else { ItemStack itemStack = new ItemStack(vanillaItem, i); - itemStack.setHoverName(Component.translatable(jsonObject.get("name").getAsString())); + if (jsonObject.has("fallbackname")) { + itemStack.setHoverName(Component.translatableWithFallback( + jsonObject.get("name").getAsString(), + jsonObject.get("fallbackname").getAsString())); + } else { + itemStack.setHoverName(Component.translatable(jsonObject.get("name").getAsString())); + } itemStack.getOrCreateTag().putBoolean("Unbreakable", GsonHelper.getAsBoolean(jsonObject, "unbreakable", false)); itemStack.getOrCreateTag().putInt("HideFlags", GsonHelper.getAsInt(jsonObject, "hideflags", 0)); + if (jsonObject.has("color")) { + itemStack.getOrCreateTagElement(ItemStack.TAG_DISPLAY).putInt(ItemStack.TAG_COLOR, GsonHelper.getAsInt(jsonObject, "color", 0)); + } return itemStack; } } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/bedrockify/mixin/BedrockBlockShadingMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/bedrockify/mixin/BedrockBlockShadingMixin.java new file mode 100644 index 000000000..dae4d57b5 --- /dev/null +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/bedrockify/mixin/BedrockBlockShadingMixin.java @@ -0,0 +1,26 @@ +package org.vivecraft.mod_compat_vr.bedrockify.mixin; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.Direction; +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.callback.CallbackInfoReturnable; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.menuworlds.MenuWorldRenderer; + +@Pseudo +@Mixin(targets = "me.juancarloscp52.bedrockify.client.features.bedrockShading.BedrockBlockShading") +public class BedrockBlockShadingMixin { + @Inject(at = @At("HEAD"), method = "getBlockShade", cancellable = true, remap = false) + private void vivecraft$MenuNetherBlockShade(Direction direction, CallbackInfoReturnable cir) { + if (Minecraft.getInstance().player == null && direction == Direction.DOWN) { + MenuWorldRenderer menuWorldRenderer = ClientDataHolderVR.getInstance().menuWorldRenderer; + if (menuWorldRenderer != null && menuWorldRenderer.getLevel() != null) { + // change brightness based on nether or not + cir.setReturnValue(menuWorldRenderer.getLevel().getDimensionReaderInfo().constantAmbientLight() ? 0.9f : 0.87f); + } + } + } +} diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/bettercombat/BetterCombatHelper.java b/common/src/main/java/org/vivecraft/mod_compat_vr/bettercombat/BetterCombatHelper.java new file mode 100644 index 000000000..031ca5a0a --- /dev/null +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/bettercombat/BetterCombatHelper.java @@ -0,0 +1,16 @@ +package org.vivecraft.mod_compat_vr.bettercombat; + +import net.bettercombat.api.WeaponAttributes; +import net.bettercombat.logic.WeaponRegistry; +import net.minecraft.world.item.ItemStack; + +public class BetterCombatHelper { + + public static double getItemRange(double rangeIn, ItemStack itemStack) { + WeaponAttributes attribute = WeaponRegistry.getAttributes(itemStack); + if (attribute != null) { + return attribute.attackRange(); + } + return rangeIn; + } +} diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/epicfight/EpicFightHelper.java b/common/src/main/java/org/vivecraft/mod_compat_vr/epicfight/EpicFightHelper.java new file mode 100644 index 000000000..e6100143d --- /dev/null +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/epicfight/EpicFightHelper.java @@ -0,0 +1,32 @@ +package org.vivecraft.mod_compat_vr.epicfight; + +import com.mojang.blaze3d.platform.InputConstants; +import org.vivecraft.client.Xplat; +import org.vivecraft.client_vr.provider.InputSimulator; +import yesman.epicfight.client.ClientEngine; +import yesman.epicfight.client.input.EpicFightKeyMappings; + +public class EpicFightHelper { + + public static boolean isLoaded() { + return Xplat.isModLoaded("epicfight"); + } + + public static boolean attack() { + if (ClientEngine.getInstance().controllEngine.getPlayerPatch().isBattleMode()) { + InputConstants.Key key = EpicFightKeyMappings.ATTACK.key; + switch (key.getType()) { + case MOUSE -> { + InputSimulator.pressMouse(key.getValue()); + InputSimulator.releaseMouse(key.getValue()); + } + case KEYSYM -> { + InputSimulator.pressKey(key.getValue()); + InputSimulator.releaseKey(key.getValue()); + } + } + return true; + } + return false; + } +} diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/IrisHelper.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/IrisHelper.java index 4f09c3801..2ca94706e 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/IrisHelper.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/IrisHelper.java @@ -1,34 +1,98 @@ package org.vivecraft.mod_compat_vr.iris; -import net.coderbot.iris.Iris; -import net.coderbot.iris.pipeline.WorldRenderingPipeline; import net.irisshaders.iris.api.v0.IrisApi; +import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.client_xr.render_pass.RenderPassManager; -import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Optional; public class IrisHelper { + private static boolean initialized = false; + private static boolean initFailed = false; + + private static Method Iris_reload; + private static Method Iris_getPipelineManager; + private static Method PipelineManager_getPipeline; + private static Method WorldRenderingPipeline_shouldRenderUnderwaterOverlay; public static void setShadersActive(boolean bl) { IrisApi.getInstance().getConfig().setShadersEnabledAndApply(bl); } public static void reload() { - try { - RenderPassManager.setVanillaRenderPass(); - Iris.reload(); - } catch (IOException e) { - System.err.println("Error reloading shaders on Frame Buffer reinit"); - e.printStackTrace(); + RenderPassManager.setVanillaRenderPass(); + if (init()) { + try { + // Iris.reload(); + Iris_reload.invoke(null); + } catch (Exception e) { + // catch Exception, because that call can throw an IOException + VRSettings.logger.error("Vivecraft: Error reloading Iris shaders on Frame Buffer reinit: {}", e.getMessage()); + } } } public static boolean hasWaterEffect() { - return Iris.getPipelineManager().getPipeline().map(WorldRenderingPipeline::shouldRenderUnderwaterOverlay).orElse(true); + if (init()) { + try { + // Iris.getPipelineManager().getPipeline().map(WorldRenderingPipeline::shouldRenderUnderwaterOverlay).orElse(true); + return (boolean) ((Optional) PipelineManager_getPipeline.invoke(Iris_getPipelineManager.invoke(null))).map(o -> { + try { + return WorldRenderingPipeline_shouldRenderUnderwaterOverlay.invoke(o); + } catch (IllegalAccessException | InvocationTargetException e) { + VRSettings.logger.error("Vivecraft: Iris water effect check failed: {}", e.getMessage()); + return true; + } + }).orElse(true); + } catch (InvocationTargetException | IllegalAccessException e) { + VRSettings.logger.error("Vivecraft: Iris water effect check failed: {}", e.getMessage()); + } + } + return true; } public static boolean isShaderActive() { return IrisApi.getInstance().isShaderPackInUse(); } + + private static boolean init() { + if (initialized) { + return !initFailed; + } + try { + Class iris = getClassWithAlternative( + "net.coderbot.iris.Iris", + "net.irisshaders.iris.Iris"); + Iris_reload = iris.getMethod("reload"); + Iris_getPipelineManager = iris.getMethod("getPipelineManager"); + + Class pipelineManager = getClassWithAlternative( + "net.coderbot.iris.pipeline.PipelineManager", + "net.irisshaders.iris.pipeline.PipelineManager"); + + PipelineManager_getPipeline = pipelineManager.getMethod("getPipeline"); + + Class worldRenderingPipeline = getClassWithAlternative( + "net.coderbot.iris.pipeline.WorldRenderingPipeline", + "net.irisshaders.iris.pipeline.WorldRenderingPipeline"); + + WorldRenderingPipeline_shouldRenderUnderwaterOverlay = worldRenderingPipeline.getMethod("shouldRenderUnderwaterOverlay"); + } catch (ClassNotFoundException | NoSuchMethodException e) { + initFailed = true; + } + + initialized = true; + return !initFailed; + } + + private static Class getClassWithAlternative(String class1, String class2) throws ClassNotFoundException { + try { + return Class.forName(class1); + } catch (ClassNotFoundException e) { + return Class.forName(class2); + } + } } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/extensions/IrisChunkProgramOverridesExtension.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/extensions/IrisChunkProgramOverridesExtension.java index e90dc3496..0da3cefd1 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/extensions/IrisChunkProgramOverridesExtension.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/extensions/IrisChunkProgramOverridesExtension.java @@ -1,11 +1,9 @@ package org.vivecraft.mod_compat_vr.iris.extensions; -import net.coderbot.iris.pipeline.SodiumTerrainPipeline; - import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public interface IrisChunkProgramOverridesExtension { - void vivecraft$createAllPipelinesShadersSodiumProcessing(SodiumTerrainPipeline sodiumTerrainPipeline, Object chunkVertexType, Method createShaders) throws InvocationTargetException, IllegalAccessException; + void vivecraft$createAllPipelinesShadersSodiumProcessing(Object sodiumTerrainPipeline, Object chunkVertexType, Method createShaders) throws InvocationTargetException, IllegalAccessException; } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/extensions/PipelineManagerExtension.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/extensions/PipelineManagerExtension.java index 360ab0deb..1c3929911 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/extensions/PipelineManagerExtension.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/extensions/PipelineManagerExtension.java @@ -1,17 +1,15 @@ package org.vivecraft.mod_compat_vr.iris.extensions; -import net.coderbot.iris.pipeline.WorldRenderingPipeline; -import net.coderbot.iris.shadows.ShadowRenderTargets; import org.vivecraft.client_vr.render.RenderPass; public interface PipelineManagerExtension { - ShadowRenderTargets vivecraft$getShadowRenderTargets(); + Object vivecraft$getShadowRenderTargets(); - void vivecraft$setShadowRenderTargets(ShadowRenderTargets targets); + void vivecraft$setShadowRenderTargets(Object targets); // needed for sodium terrain shaders, to get all pipelines, and not just the one from the current pass - WorldRenderingPipeline vivecraft$getVRPipeline(RenderPass pass); + Object vivecraft$getVRPipeline(RenderPass pass); - WorldRenderingPipeline vivecraft$getVanillaPipeline(); + Object vivecraft$getVanillaPipeline(); } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisBeginFrameHack.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisBeginFrameHack.java index 198e6e9f5..470197409 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisBeginFrameHack.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisBeginFrameHack.java @@ -11,7 +11,9 @@ @Pseudo @Mixin(targets = { "net.coderbot.iris.uniforms.SystemTimeUniforms$FrameCounter", - "net.coderbot.iris.uniforms.SystemTimeUniforms$Timer" + "net.coderbot.iris.uniforms.SystemTimeUniforms$Timer", + "net.irisshaders.iris.uniforms.SystemTimeUniforms$FrameCounter", + "net.irisshaders.iris.uniforms.SystemTimeUniforms$Timer" }) public class IrisBeginFrameHack { // only count frames from the first RenderPass, so that all RenderPasses have the same frame counter diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisBlockRenderingSettingsMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisBlockRenderingSettingsMixin.java index cf19cd864..01fcfb494 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisBlockRenderingSettingsMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisBlockRenderingSettingsMixin.java @@ -1,13 +1,17 @@ package org.vivecraft.mod_compat_vr.iris.mixin; -import net.coderbot.iris.block_rendering.BlockRenderingSettings; 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.callback.CallbackInfoReturnable; import org.vivecraft.client_vr.ClientDataHolderVR; -@Mixin(BlockRenderingSettings.class) +@Pseudo +@Mixin(targets = { + "net.coderbot.iris.block_rendering.BlockRenderingSettings", + "net.irisshaders.iris.block_rendering.BlockRenderingSettings" +}) public class IrisBlockRenderingSettingsMixin { @Inject(at = @At("HEAD"), method = "getAmbientOcclusionLevel", remap = false, cancellable = true) private void vivecrat$defaultAOforMenuWorld(CallbackInfoReturnable cir) { diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisHandRendererVRMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisHandRendererVRMixin.java index 420df5779..6fde1761f 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisHandRendererVRMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisHandRendererVRMixin.java @@ -1,10 +1,5 @@ package org.vivecraft.mod_compat_vr.iris.mixin; -import com.mojang.blaze3d.vertex.PoseStack; -import net.coderbot.iris.pipeline.HandRenderer; -import net.coderbot.iris.pipeline.WorldRenderingPipeline; -import net.minecraft.client.Camera; -import net.minecraft.client.renderer.GameRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.At; @@ -14,25 +9,28 @@ //TODO Move rendering to here @Pseudo -@Mixin(HandRenderer.class) +@Mixin(targets = { + "net.coderbot.iris.pipeline.HandRenderer", + "net.irisshaders.iris.pipeline.HandRenderer" +}) public class IrisHandRendererVRMixin { - @Inject(at = @At("HEAD"), method = "setupGlState", cancellable = true) - public void vivecraft$glState(GameRenderer par1, Camera par2, PoseStack par3, float par4, CallbackInfo ci) { + @Inject(at = @At("HEAD"), method = "setupGlState", cancellable = true, remap = false) + public void vivecraft$glState(CallbackInfo ci) { if (!RenderPassType.isVanilla()) { ci.cancel(); } } - @Inject(at = @At("HEAD"), method = "renderSolid", cancellable = true) - public void vivecraft$rendersolid(PoseStack par1, float par2, Camera par3, GameRenderer par4, WorldRenderingPipeline par5, CallbackInfo ci) { + @Inject(at = @At("HEAD"), method = "renderSolid", cancellable = true, remap = false) + public void vivecraft$rendersolid(CallbackInfo ci) { if (!RenderPassType.isVanilla()) { ci.cancel(); } } - @Inject(at = @At("HEAD"), method = "renderTranslucent", cancellable = true) - public void vivecraft$rendertranslucent(PoseStack par1, float par2, Camera par3, GameRenderer par4, WorldRenderingPipeline par5, CallbackInfo ci) { + @Inject(at = @At("HEAD"), method = "renderTranslucent", cancellable = true, remap = false) + public void vivecraft$rendertranslucent(CallbackInfo ci) { if (!RenderPassType.isVanilla()) { ci.cancel(); } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisProgramUniformsMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisProgramUniformsMixin.java index ee009f28e..db10df3e1 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisProgramUniformsMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisProgramUniformsMixin.java @@ -1,6 +1,5 @@ package org.vivecraft.mod_compat_vr.iris.mixin; -import net.coderbot.iris.gl.program.ProgramUniforms; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.Shadow; @@ -12,7 +11,10 @@ import org.vivecraft.client_xr.render_pass.RenderPassType; @Pseudo -@Mixin(ProgramUniforms.class) +@Mixin(targets = { + "net.coderbot.iris.gl.program.ProgramUniforms", + "net.irisshaders.iris.gl.program.ProgramUniforms" +}) public class IrisProgramUniformsMixin { @Shadow(remap = false) diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisRenderSystemVRMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisRenderSystemVRMixin.java index 1f9a4200f..8dd7e857c 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisRenderSystemVRMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisRenderSystemVRMixin.java @@ -1,6 +1,5 @@ package org.vivecraft.mod_compat_vr.iris.mixin; -import net.coderbot.iris.gl.IrisRenderSystem; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.At; @@ -9,7 +8,10 @@ import org.vivecraft.client_xr.render_pass.RenderPassType; @Pseudo -@Mixin(IrisRenderSystem.class) +@Mixin(targets = { + "net.coderbot.iris.gl.IrisRenderSystem", + "net.irisshaders.iris.gl.IrisRenderSystem" +}) public class IrisRenderSystemVRMixin { // expect 0 since this is only for iris 1.6+ // disable SSBOS since I didn't get to find a good way to share them between passes yet diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisShadowMatricesMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisShadowMatricesMixin.java index ccd07f4c7..74739423c 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisShadowMatricesMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisShadowMatricesMixin.java @@ -14,7 +14,12 @@ import org.vivecraft.client_xr.render_pass.RenderPassType; @Pseudo -@Mixin(targets = {"net.coderbot.iris.shadow.ShadowMatrices", "net.coderbot.iris.shadows.ShadowMatrices"}) +@Mixin(targets = { + "net.coderbot.iris.shadow.ShadowMatrices", + "net.coderbot.iris.shadows.ShadowMatrices", + "net.irisshaders.iris.shadow.ShadowMatrices", + "net.irisshaders.iris.shadows.ShadowMatrices" +}) public class IrisShadowMatricesMixin { @Unique diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisShadowRendererMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisShadowRendererMixin.java index a83ccd29a..fcdc63c50 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisShadowRendererMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisShadowRendererMixin.java @@ -1,66 +1,24 @@ package org.vivecraft.mod_compat_vr.iris.mixin; -import com.mojang.blaze3d.vertex.PoseStack; -import net.coderbot.iris.mixin.LevelRendererAccessor; -import net.coderbot.iris.pipeline.ShadowRenderer; -import net.minecraft.client.Camera; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.culling.Frustum; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; 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.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.vivecraft.client_vr.ClientDataHolderVR; -import org.vivecraft.client_vr.extensions.GameRendererExtension; import org.vivecraft.client_xr.render_pass.RenderPassType; @Pseudo -@Mixin(ShadowRenderer.class) +@Mixin(targets = { + "net.coderbot.iris.pipeline.ShadowRenderer", + "net.irisshaders.iris.pipeline.ShadowRenderer" +}) public class IrisShadowRendererMixin { - @Inject(method = "renderPlayerEntity", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/mixin/LevelRendererAccessor;invokeRenderEntity(Lnet/minecraft/world/entity/Entity;DDDFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;)V", ordinal = 2)) - private void vivecraft$setRVE(LevelRendererAccessor par1, EntityRenderDispatcher par2, MultiBufferSource.BufferSource par3, PoseStack par4, float par5, Frustum par6, double par7, double par8, double par9, CallbackInfoReturnable cir) { - if (!RenderPassType.isVanilla()) { - ((GameRendererExtension) Minecraft.getInstance().gameRenderer).vivecraft$restoreRVEPos(Minecraft.getInstance().player); - } - } - - @Inject(method = "renderPlayerEntity", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/mixin/LevelRendererAccessor;invokeRenderEntity(Lnet/minecraft/world/entity/Entity;DDDFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;)V", ordinal = 2, shift = At.Shift.AFTER)) - private void vivecraft$resetRVE(LevelRendererAccessor par1, EntityRenderDispatcher par2, MultiBufferSource.BufferSource par3, PoseStack par4, float par5, Frustum par6, double par7, double par8, double par9, CallbackInfoReturnable cir) { - if (!RenderPassType.isVanilla()) { - ((GameRendererExtension) Minecraft.getInstance().gameRenderer).vivecraft$cacheRVEPos(Minecraft.getInstance().player); - ((GameRendererExtension) Minecraft.getInstance().gameRenderer).vivecraft$setupRVE(); - } - } - - @Redirect(method = "renderEntities", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/mixin/LevelRendererAccessor;invokeRenderEntity(Lnet/minecraft/world/entity/Entity;DDDFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;)V")) - private void vivecraft$setRVE2(LevelRendererAccessor instance, Entity entity, double x, double y, double z, float f, PoseStack poseStack, MultiBufferSource multiBufferSource) { - if (!RenderPassType.isVanilla()) { - if (entity == Minecraft.getInstance().getCameraEntity()) { - ((GameRendererExtension) Minecraft.getInstance().gameRenderer).vivecraft$restoreRVEPos((LivingEntity) entity); - } - - instance.invokeRenderEntity(entity, x, y, z, f, poseStack, multiBufferSource); - - if (entity == Minecraft.getInstance().getCameraEntity()) { - ((GameRendererExtension) Minecraft.getInstance().gameRenderer).vivecraft$cacheRVEPos((LivingEntity) entity); - ((GameRendererExtension) Minecraft.getInstance().gameRenderer).vivecraft$setupRVE(); - } - } else { - instance.invokeRenderEntity(entity, x, y, z, f, poseStack, multiBufferSource); - } - } // only render shadows on the first RenderPass // cancel them here, or we would also cancel prepare shaders - @Inject(method = "renderShadows", at = @At("HEAD"), cancellable = true) - private void vivecraft$onlyOneShadow(LevelRendererAccessor par1, Camera par2, CallbackInfo ci) { + @Inject(method = "renderShadows", at = @At("HEAD"), cancellable = true, remap = false) + private void vivecraft$onlyOneShadow(CallbackInfo ci) { if (!RenderPassType.isVanilla() && !ClientDataHolderVR.getInstance().isFirstPass) { ci.cancel(); } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisChunkProgramOverridesMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisChunkProgramOverridesMixin.java similarity index 88% rename from common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisChunkProgramOverridesMixin.java rename to common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisChunkProgramOverridesMixin.java index 94799c566..5dd9e9ea5 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisChunkProgramOverridesMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisChunkProgramOverridesMixin.java @@ -1,4 +1,4 @@ -package org.vivecraft.mod_compat_vr.iris.mixin; +package org.vivecraft.mod_compat_vr.iris.mixin.coderbot; import me.jellysquid.mods.sodium.client.gl.shader.GlProgram; import net.coderbot.iris.Iris; @@ -38,7 +38,7 @@ public class IrisChunkProgramOverridesMixin implements IrisChunkProgramOverrides @Override @Unique - public void vivecraft$createAllPipelinesShadersSodiumProcessing(SodiumTerrainPipeline sodiumTerrainPipeline, Object chunkVertexType, Method createShadersMethod) throws InvocationTargetException, IllegalAccessException { + public void vivecraft$createAllPipelinesShadersSodiumProcessing(Object sodiumTerrainPipeline, Object chunkVertexType, Method createShadersMethod) throws InvocationTargetException, IllegalAccessException { if (VRState.vrInitialized) { WorldRenderPass current = RenderPassManager.wrp; RenderPass currentPass = ClientDataHolderVR.getInstance().currentPass; @@ -47,7 +47,7 @@ public class IrisChunkProgramOverridesMixin implements IrisChunkProgramOverrides for (RenderPass renderPass : RenderPass.values()) { Iris.logger.info("Creating VR sodium shaders for RenderPass {}", renderPass); - WorldRenderingPipeline worldPipeline = ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getVRPipeline(renderPass); + WorldRenderingPipeline worldPipeline = (WorldRenderingPipeline) ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getVRPipeline(renderPass); // GUI and unused renderPasses don't have a pipeline if (worldPipeline != null) { SodiumTerrainPipeline sodiumPipeline = worldPipeline.getSodiumTerrainPipeline(); @@ -63,7 +63,7 @@ public class IrisChunkProgramOverridesMixin implements IrisChunkProgramOverrides RenderPassManager.setVanillaRenderPass(); Iris.logger.info("Creating sodium shaders for vanilla RenderPass"); - createShadersMethod.invoke(this, ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getVanillaPipeline().getSodiumTerrainPipeline(), chunkVertexType); + createShadersMethod.invoke(this, ((WorldRenderingPipeline) ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getVanillaPipeline()).getSodiumTerrainPipeline(), chunkVertexType); if (current != null) { RenderPassManager.setWorldRenderPass(current); ClientDataHolderVR.getInstance().currentPass = currentPass; diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisChunkProgramOverridesMixinSodium_0_4_11.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisChunkProgramOverridesMixinSodium_0_4_11.java similarity index 97% rename from common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisChunkProgramOverridesMixinSodium_0_4_11.java rename to common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisChunkProgramOverridesMixinSodium_0_4_11.java index d4c7c63ce..6159dd7ce 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisChunkProgramOverridesMixinSodium_0_4_11.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisChunkProgramOverridesMixinSodium_0_4_11.java @@ -1,4 +1,4 @@ -package org.vivecraft.mod_compat_vr.iris.mixin; +package org.vivecraft.mod_compat_vr.iris.mixin.coderbot; import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType; import net.coderbot.iris.compat.sodium.impl.shader_overrides.IrisChunkProgramOverrides; diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisChunkProgramOverridesMixinSodium_0_4_9.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisChunkProgramOverridesMixinSodium_0_4_9.java similarity index 96% rename from common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisChunkProgramOverridesMixinSodium_0_4_9.java rename to common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisChunkProgramOverridesMixinSodium_0_4_9.java index ca99e5128..598399bd6 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisChunkProgramOverridesMixinSodium_0_4_9.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisChunkProgramOverridesMixinSodium_0_4_9.java @@ -1,4 +1,4 @@ -package org.vivecraft.mod_compat_vr.iris.mixin; +package org.vivecraft.mod_compat_vr.iris.mixin.coderbot; import me.jellysquid.mods.sodium.client.render.vertex.type.ChunkVertexType; import net.coderbot.iris.compat.sodium.impl.shader_overrides.IrisChunkProgramOverrides; diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisNewWorldRenderingPipelineVRMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisNewWorldRenderingPipelineVRMixin.java similarity index 85% rename from common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisNewWorldRenderingPipelineVRMixin.java rename to common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisNewWorldRenderingPipelineVRMixin.java index 1310c2252..65a847c64 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisNewWorldRenderingPipelineVRMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisNewWorldRenderingPipelineVRMixin.java @@ -1,4 +1,4 @@ -package org.vivecraft.mod_compat_vr.iris.mixin; +package org.vivecraft.mod_compat_vr.iris.mixin.coderbot; import net.coderbot.iris.Iris; import net.coderbot.iris.pipeline.ShadowRenderer; @@ -41,7 +41,7 @@ public class IrisNewWorldRenderingPipelineVRMixin { @Inject(target = @Desc(value = "lambda$new$1", owner = NewWorldRenderingPipeline.class, ret = ShadowRenderTargets.class, args = PackShadowDirectives.class), at = @At("HEAD"), cancellable = true, remap = false, expect = 0) private void vivecraft$onlyOneShadowTargetSupplier131(CallbackInfoReturnable cir) { if (!RenderPassType.isVanilla() && ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets() != null) { - cir.setReturnValue(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets()); + cir.setReturnValue((ShadowRenderTargets) ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets()); } } @@ -49,7 +49,7 @@ public class IrisNewWorldRenderingPipelineVRMixin { @Inject(target = @Desc(value = "lambda$new$0", owner = NewWorldRenderingPipeline.class, ret = ShadowRenderTargets.class, args = PackShadowDirectives.class), at = @At("HEAD"), cancellable = true, remap = false, expect = 0) private void vivecraft$onlyOneShadowTargetSupplier140(CallbackInfoReturnable cir) { if (!RenderPassType.isVanilla() && ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets() != null) { - cir.setReturnValue(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets()); + cir.setReturnValue((ShadowRenderTargets) ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets()); } } @@ -57,7 +57,7 @@ public class IrisNewWorldRenderingPipelineVRMixin { @Inject(target = @Desc(value = "lambda$new$3", owner = NewWorldRenderingPipeline.class, ret = ShadowRenderTargets.class, args = PackShadowDirectives.class), at = @At("HEAD"), cancellable = true, remap = false, expect = 0) private void vivecraft$onlyOneShadowTargetSupplier150(CallbackInfoReturnable cir) { if (!RenderPassType.isVanilla() && ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets() != null) { - cir.setReturnValue(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets()); + cir.setReturnValue((ShadowRenderTargets) ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets()); } } @@ -65,7 +65,7 @@ public class IrisNewWorldRenderingPipelineVRMixin { @Inject(target = @Desc(value = "lambda$new$4", owner = NewWorldRenderingPipeline.class, ret = ShadowRenderTargets.class, args = PackShadowDirectives.class), at = @At("HEAD"), cancellable = true, remap = false, expect = 0) private void vivecraft$onlyOneShadowTargetSupplier160(CallbackInfoReturnable cir) { if (!RenderPassType.isVanilla() && ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets() != null) { - cir.setReturnValue(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets()); + cir.setReturnValue((ShadowRenderTargets) ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets()); } } @@ -74,7 +74,7 @@ public class IrisNewWorldRenderingPipelineVRMixin { @Inject(target = @Desc(value = "lambda$new$1", owner = NewWorldRenderingPipeline.class, ret = ShadowRenderTargets.class, args = {}), at = @At("HEAD"), cancellable = true, remap = false, expect = 0) private void vivecraft$onlyOneShadowTargetSupplierOculus(CallbackInfoReturnable cir) { if (!RenderPassType.isVanilla() && ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets() != null) { - cir.setReturnValue(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets()); + cir.setReturnValue((ShadowRenderTargets) ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets()); } } @@ -93,8 +93,7 @@ public class IrisNewWorldRenderingPipelineVRMixin { @Redirect(method = "addGbufferOrShadowSamplers", at = @At(value = "INVOKE", target = "Ljava/util/Objects;requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false, expect = 0, slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/coderbot/iris/samplers/IrisSamplers;hasShadowSamplers(Lnet/coderbot/iris/gl/sampler/SamplerHolder;)Z"))) private Object vivecraft$rerouteShadowTarget(Object obj) { if (!RenderPassType.isVanilla()) { - ShadowRenderTargets targets = ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(); - return Objects.requireNonNull(targets != null ? targets : obj); + return Objects.requireNonNull(Objects.requireNonNullElse(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(), obj)); } else { return Objects.requireNonNull(obj); } @@ -110,8 +109,7 @@ public class IrisNewWorldRenderingPipelineVRMixin { }, at = @At(value = "INVOKE", target = "Ljava/util/Objects;requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false, expect = 0) private Object vivecraft$rerouteShadowTarget131(Object obj) { if (!RenderPassType.isVanilla()) { - ShadowRenderTargets targets = ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(); - return Objects.requireNonNull(targets != null ? targets : obj); + return Objects.requireNonNull(Objects.requireNonNullElse(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(), obj)); } else { return Objects.requireNonNull(obj); } @@ -127,8 +125,7 @@ public class IrisNewWorldRenderingPipelineVRMixin { }, at = @At(value = "INVOKE", target = "Ljava/util/Objects;requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false, expect = 0) private Object vivecraft$rerouteShadowTarget140(Object obj) { if (!RenderPassType.isVanilla()) { - ShadowRenderTargets targets = ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(); - return Objects.requireNonNull(targets != null ? targets : obj); + return Objects.requireNonNull(Objects.requireNonNullElse(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(), obj)); } else { return Objects.requireNonNull(obj); } @@ -144,8 +141,7 @@ public class IrisNewWorldRenderingPipelineVRMixin { }, at = @At(value = "INVOKE", target = "Ljava/util/Objects;requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false, expect = 0) private Object rvivecraft$erouteShadowTarget150(Object obj) { if (!RenderPassType.isVanilla()) { - ShadowRenderTargets targets = ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(); - return Objects.requireNonNull(targets != null ? targets : obj); + return Objects.requireNonNull(Objects.requireNonNullElse(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(), obj)); } else { return Objects.requireNonNull(obj); } @@ -161,8 +157,7 @@ public class IrisNewWorldRenderingPipelineVRMixin { }, at = @At(value = "INVOKE", target = "Ljava/util/Objects;requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false, expect = 0) private Object vivecraft$rerouteShadowTarget160(Object obj) { if (!RenderPassType.isVanilla()) { - ShadowRenderTargets targets = ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(); - return Objects.requireNonNull(targets != null ? targets : obj); + return Objects.requireNonNull(Objects.requireNonNullElse(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(), obj)); } else { return Objects.requireNonNull(obj); } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisPipelineManagerVRMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisPipelineManagerVRMixin.java similarity index 96% rename from common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisPipelineManagerVRMixin.java rename to common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisPipelineManagerVRMixin.java index 1b7e26b25..2fd77f7f3 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/IrisPipelineManagerVRMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/coderbot/IrisPipelineManagerVRMixin.java @@ -1,4 +1,4 @@ -package org.vivecraft.mod_compat_vr.iris.mixin; +package org.vivecraft.mod_compat_vr.iris.mixin.coderbot; import net.coderbot.iris.Iris; import net.coderbot.iris.pipeline.PipelineManager; @@ -50,8 +50,8 @@ private void resetTextureState() { @Override @Unique - public void vivecraft$setShadowRenderTargets(ShadowRenderTargets targets) { - vivecraft$shadowRenderTargets = targets; + public void vivecraft$setShadowRenderTargets(Object targets) { + vivecraft$shadowRenderTargets = (ShadowRenderTargets) targets; } @Unique @@ -185,13 +185,13 @@ private void resetTextureState() { @Override @Unique - public WorldRenderingPipeline vivecraft$getVRPipeline(RenderPass pass) { + public Object vivecraft$getVRPipeline(RenderPass pass) { return vivecraft$vrPipelinesCurrentDimension.get(pass); } @Override @Unique - public WorldRenderingPipeline vivecraft$getVanillaPipeline() { + public Object vivecraft$getVanillaPipeline() { return vivecraft$vanillaPipeline; } } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisChunkProgramOverridesMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisChunkProgramOverridesMixin.java new file mode 100644 index 000000000..0f0ff4fd4 --- /dev/null +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisChunkProgramOverridesMixin.java @@ -0,0 +1,97 @@ +package org.vivecraft.mod_compat_vr.iris.mixin.irisshaders; + +import net.caffeinemc.mods.sodium.client.gl.shader.GlProgram; +import net.irisshaders.iris.Iris; +import net.irisshaders.iris.compat.sodium.impl.shader_overrides.IrisChunkProgramOverrides; +import net.irisshaders.iris.compat.sodium.impl.shader_overrides.IrisChunkShaderInterface; +import net.irisshaders.iris.compat.sodium.impl.shader_overrides.IrisTerrainPass; +import net.irisshaders.iris.pipeline.SodiumTerrainPipeline; +import net.irisshaders.iris.pipeline.WorldRenderingPipeline; +import org.spongepowered.asm.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.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRState; +import org.vivecraft.client_vr.render.RenderPass; +import org.vivecraft.client_vr.settings.VRSettings; +import org.vivecraft.client_xr.render_pass.RenderPassManager; +import org.vivecraft.client_xr.render_pass.RenderPassType; +import org.vivecraft.client_xr.render_pass.WorldRenderPass; +import org.vivecraft.mod_compat_vr.iris.extensions.IrisChunkProgramOverridesExtension; +import org.vivecraft.mod_compat_vr.iris.extensions.PipelineManagerExtension; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.EnumMap; + +@Pseudo +@Mixin(IrisChunkProgramOverrides.class) +public class IrisChunkProgramOverridesMixin implements IrisChunkProgramOverridesExtension { + + @Shadow(remap = false) + @Final + private EnumMap> programs; + + @Unique + private final EnumMap>> vivecraft$pipelinePrograms = new EnumMap<>(RenderPass.class); + + @Override + @Unique + public void vivecraft$createAllPipelinesShadersSodiumProcessing(Object sodiumTerrainPipeline, Object chunkVertexType, Method createShadersMethod) throws InvocationTargetException, IllegalAccessException { + if (VRState.vrInitialized) { + WorldRenderPass current = RenderPassManager.wrp; + RenderPass currentPass = ClientDataHolderVR.getInstance().currentPass; + + RenderPassManager.renderPassType = RenderPassType.WORLD_ONLY; + for (RenderPass renderPass : RenderPass.values()) { + VRSettings.logger.info("Creating VR sodium shaders for RenderPass {}", renderPass); + + WorldRenderingPipeline worldPipeline = (WorldRenderingPipeline) ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getVRPipeline(renderPass); + // GUI and unused renderPasses don't have a pipeline + if (worldPipeline != null) { + SodiumTerrainPipeline sodiumPipeline = worldPipeline.getSodiumTerrainPipeline(); + EnumMap> renderPassShaders = new EnumMap<>(IrisTerrainPass.class); + vivecraft$pipelinePrograms.put(renderPass, renderPassShaders); + createShadersMethod.invoke(this, sodiumPipeline, chunkVertexType); + // programs should have the shaders for this pass now + renderPassShaders.putAll(programs); + // clear it now, since programs is for the vanilla pass + programs.clear(); + } + } + + RenderPassManager.setVanillaRenderPass(); + VRSettings.logger.info("Creating sodium shaders for vanilla RenderPass"); + createShadersMethod.invoke(this, ((WorldRenderingPipeline) ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getVanillaPipeline()).getSodiumTerrainPipeline(), chunkVertexType); + if (current != null) { + RenderPassManager.setWorldRenderPass(current); + ClientDataHolderVR.getInstance().currentPass = currentPass; + } + } else { + createShadersMethod.invoke(this, sodiumTerrainPipeline, chunkVertexType); + } + } + + @Redirect(method = "getProgramOverride", at = @At(value = "INVOKE", target = "Ljava/util/EnumMap;get(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false) + public Object vivecraft$getVRPipelineShaders(EnumMap> instance, Object key) { + // return shader of the current RenderPass + return !RenderPassType.isVanilla() ? vivecraft$pipelinePrograms.get(ClientDataHolderVR.getInstance().currentPass).get((IrisTerrainPass) key) : instance.get((IrisTerrainPass) key); + } + + @Inject(method = "deleteShaders", at = @At("HEAD"), remap = false) + public void vivecraft$deleteVRPipelineShaders(CallbackInfo ci) { + if (VRState.vrInitialized) { + for (EnumMap> map : vivecraft$pipelinePrograms.values()) { + for (GlProgram program : map.values()) { + if (program != null) { + program.delete(); + } + } + map.clear(); + } + vivecraft$pipelinePrograms.clear(); + } + } +} diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisChunkProgramOverridesMixinSodium_0_6.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisChunkProgramOverridesMixinSodium_0_6.java new file mode 100644 index 000000000..ef17f3721 --- /dev/null +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisChunkProgramOverridesMixinSodium_0_6.java @@ -0,0 +1,33 @@ +package org.vivecraft.mod_compat_vr.iris.mixin.irisshaders; + +import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType; +import net.irisshaders.iris.compat.sodium.impl.shader_overrides.IrisChunkProgramOverrides; +import net.irisshaders.iris.pipeline.SodiumTerrainPipeline; +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.Group; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.vivecraft.mod_compat_vr.iris.extensions.IrisChunkProgramOverridesExtension; + +import java.lang.reflect.InvocationTargetException; + +@Pseudo +@Mixin(IrisChunkProgramOverrides.class) +public class IrisChunkProgramOverridesMixinSodium_0_6 { + + @Group(name = "create sodium shaders", min = 1, max = 1) + @Redirect(at = @At(value = "INVOKE", target = "Lnet/irisshaders/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides;createShaders(Lnet/irisshaders/iris/pipeline/SodiumTerrainPipeline;Lnet/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType;)V"), method = "getProgramOverride", remap = false, expect = 0) + public void vivecraft$createAllPipelinesShadersSodium_0_6(IrisChunkProgramOverrides instance, SodiumTerrainPipeline sodiumTerrainPipeline, ChunkVertexType chunkVertexType) { + try { + ((IrisChunkProgramOverridesExtension) this).vivecraft$createAllPipelinesShadersSodiumProcessing( + sodiumTerrainPipeline, + chunkVertexType, + instance.getClass().getMethod("createShaders", SodiumTerrainPipeline.class, ChunkVertexType.class) + ); + } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { + // this shouldn't happen if everything went well + throw new RuntimeException(e); + } + } +} diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisNewWorldRenderingPipelineVRMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisNewWorldRenderingPipelineVRMixin.java new file mode 100644 index 000000000..c66e0297f --- /dev/null +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisNewWorldRenderingPipelineVRMixin.java @@ -0,0 +1,86 @@ +package org.vivecraft.mod_compat_vr.iris.mixin.irisshaders; + +import net.irisshaders.iris.Iris; +import net.irisshaders.iris.gl.program.ProgramImages; +import net.irisshaders.iris.gl.program.ProgramSamplers; +import net.irisshaders.iris.pipeline.ShadowRenderer; +import net.irisshaders.iris.pipeline.newshader.NewWorldRenderingPipeline; +import net.irisshaders.iris.shaderpack.PackShadowDirectives; +import net.irisshaders.iris.shaderpack.ProgramSet; +import net.irisshaders.iris.shadows.ShadowRenderTargets; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.vivecraft.client_xr.render_pass.RenderPassType; +import org.vivecraft.mod_compat_vr.iris.extensions.PipelineManagerExtension; + +import java.util.Objects; + +@Pseudo +@Mixin(NewWorldRenderingPipeline.class) +public class IrisNewWorldRenderingPipelineVRMixin { + @Shadow(remap = false) + private ShadowRenderTargets shadowRenderTargets; + + @Final + @Shadow(remap = false) + private ShadowRenderer shadowRenderer; + + // store shadowTargets of the first pipeline + @Inject(method = "", at = @At("TAIL"), remap = false) + private void vivecraft$storeShadowTargets(ProgramSet par1, CallbackInfo ci) { + if (((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets() == null) { + ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$setShadowRenderTargets(shadowRenderTargets); + } + } + + // return main shadowRenderTargets, instead of own + @Group(name = "one shadowRenderTargets", min = 1, max = 1) + @Inject(target = @Desc(value = "lambda$new$4", owner = NewWorldRenderingPipeline.class, ret = ShadowRenderTargets.class, args = PackShadowDirectives.class), at = @At("HEAD"), cancellable = true, remap = false, expect = 0) + private void vivecraft$onlyOneShadowTargetSupplier160(CallbackInfoReturnable cir) { + if (!RenderPassType.isVanilla() && ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets() != null) { + cir.setReturnValue((ShadowRenderTargets) ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets()); + } + } + + @Inject(method = "shouldDisableVanillaEntityShadows()Z", at = @At("HEAD"), cancellable = true, remap = false) + private void vivecraft$shouldDisableEntityShadows(CallbackInfoReturnable cir) { + if (!RenderPassType.isVanilla() && (shadowRenderer != null || ((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets() != null)) { + cir.setReturnValue(true); + } + } + + // needed because shadowRenderTargets never gets set for sub pipelines + // this should give the own shadow targets, for the main pipeline and renderpass.LEFT, + // and for all other piplines the one from renderpass.LEFT + + @Group(name = "reroute shadowRenderTargets", min = 6, max = 6) + @Redirect(method = "addGbufferOrShadowSamplers", at = @At(value = "INVOKE", target = "Ljava/util/Objects;requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false, expect = 0, slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/irisshaders/iris/samplers/IrisSamplers;hasShadowSamplers(Lnet/irisshaders/iris/gl/sampler/SamplerHolder;)Z"))) + private Object vivecraft$rerouteShadowTarget(Object obj) { + if (!RenderPassType.isVanilla()) { + return Objects.requireNonNull(Objects.requireNonNullElse(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(), obj)); + } else { + return Objects.requireNonNull(obj); + } + } + + // iris 1.6.0+ + @Group(name = "reroute shadowRenderTargets", min = 6, max = 6) + @Redirect(target = { + @Desc(value = "lambda$new$6", owner = NewWorldRenderingPipeline.class, ret = ProgramSamplers.class, args = {java.util.function.Supplier.class, int.class}), + @Desc(value = "lambda$new$7", owner = NewWorldRenderingPipeline.class, ret = ProgramImages.class, args = {java.util.function.Supplier.class, int.class}), + @Desc(value = "lambda$new$9", owner = NewWorldRenderingPipeline.class, ret = ProgramSamplers.class, args = int.class), + @Desc(value = "lambda$new$11", owner = NewWorldRenderingPipeline.class, ret = ProgramImages.class, args = int.class) + }, at = @At(value = "INVOKE", target = "Ljava/util/Objects;requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false, expect = 0) + private Object vivecraft$rerouteShadowTarget160(Object obj) { + if (!RenderPassType.isVanilla()) { + return Objects.requireNonNull(Objects.requireNonNullElse(((PipelineManagerExtension) Iris.getPipelineManager()).vivecraft$getShadowRenderTargets(), obj)); + } else { + return Objects.requireNonNull(obj); + } + } +} diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisPipelineManagerVRMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisPipelineManagerVRMixin.java new file mode 100644 index 000000000..ee9928866 --- /dev/null +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/iris/mixin/irisshaders/IrisPipelineManagerVRMixin.java @@ -0,0 +1,180 @@ +package org.vivecraft.mod_compat_vr.iris.mixin.irisshaders; + +import net.irisshaders.iris.pipeline.PipelineManager; +import net.irisshaders.iris.pipeline.WorldRenderingPipeline; +import net.irisshaders.iris.shaderpack.materialmap.NamespacedId; +import net.irisshaders.iris.shadows.ShadowRenderTargets; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Group; +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.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRState; +import org.vivecraft.client_vr.render.RenderPass; +import org.vivecraft.client_vr.settings.VRSettings; +import org.vivecraft.client_xr.render_pass.RenderPassManager; +import org.vivecraft.client_xr.render_pass.RenderPassType; +import org.vivecraft.client_xr.render_pass.WorldRenderPass; +import org.vivecraft.mod_compat_vr.iris.extensions.PipelineManagerExtension; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +@Pseudo +@Mixin(PipelineManager.class) +public class IrisPipelineManagerVRMixin implements PipelineManagerExtension { + + @Shadow(remap = false) + private void resetTextureState() { + } + + @Shadow(remap = false) + private WorldRenderingPipeline pipeline; + @Shadow(remap = false) + @Final + private Function pipelineFactory; + + @Unique + private ShadowRenderTargets vivecraft$shadowRenderTargets; + + @Override + @Unique + public Object vivecraft$getShadowRenderTargets() { + return vivecraft$shadowRenderTargets; + } + + @Override + @Unique + public void vivecraft$setShadowRenderTargets(Object targets) { + vivecraft$shadowRenderTargets = (ShadowRenderTargets) targets; + } + + @Unique + private final Map> vivecraft$vrPipelinesPerDimension = new HashMap<>(); + @Unique + private WorldRenderingPipeline vivecraft$vanillaPipeline; + @Unique + private Map vivecraft$vrPipelinesCurrentDimension; + + @Unique + private WorldRenderPass vivecraft$currentWorldRenderPass = null; + + @Inject(method = "preparePipeline", at = @At(value = "INVOKE", target = "Ljava/util/function/Function;apply(Ljava/lang/Object;)Ljava/lang/Object;", shift = At.Shift.BEFORE), remap = false) + private void vivecraft$generateVanillaPipeline(CallbackInfoReturnable cir) { + // this also runs on game startup, when the renderpassManager isn't initialized yet + if (VRState.vrInitialized && RenderPassManager.INSTANCE != null) { + vivecraft$currentWorldRenderPass = RenderPassManager.wrp; + RenderPass currentRenderPass = ClientDataHolderVR.getInstance().currentPass; + RenderPassManager.setVanillaRenderPass(); + ClientDataHolderVR.getInstance().currentPass = currentRenderPass; + } + } + + @Group(name = "generateVRPipelines", min = 1, max = 1) + @Inject(method = "preparePipeline", at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", shift = At.Shift.AFTER), remap = false, expect = 0) + private void vivecraft$generateVRPipelines165(NamespacedId newDimension, CallbackInfoReturnable cir) { + vivecraft$generateVRPipelines(newDimension); + } + + @Unique + private void vivecraft$generateVRPipelines(Object newDimension) { + if (VRState.vrInitialized) { + vivecraft$vanillaPipeline = pipeline; + if (!this.vivecraft$vrPipelinesPerDimension.containsKey(newDimension)) { + vivecraft$vrPipelinesPerDimension.put(newDimension, new HashMap<>()); + vivecraft$vrPipelinesCurrentDimension = vivecraft$vrPipelinesPerDimension.get(newDimension); + // main pipeline also sets this, but we don't want that, since it is unused + vivecraft$shadowRenderTargets = null; + + for (RenderPass renderPass : RenderPass.values()) { + VRSettings.logger.info("Creating VR pipeline for dimension {}, RenderPass {}", newDimension, renderPass); + WorldRenderPass worldRenderPass = null; + switch (renderPass) { + case LEFT, RIGHT -> worldRenderPass = WorldRenderPass.stereoXR; + case CENTER -> worldRenderPass = WorldRenderPass.center; + case THIRD -> worldRenderPass = WorldRenderPass.mixedReality; + case SCOPEL -> worldRenderPass = WorldRenderPass.leftTelescope; + case SCOPER -> worldRenderPass = WorldRenderPass.rightTelescope; + case CAMERA -> worldRenderPass = WorldRenderPass.camera; + default -> { + VRSettings.logger.info("skipped VR pipeline for dimension {}, RenderPass {}, not used", newDimension, renderPass); + continue; + } + } + + if (worldRenderPass != null) { + RenderPassManager.setWorldRenderPass(worldRenderPass); + } else { + continue; + } + + WorldRenderingPipeline pipe = pipelineFactory.apply(newDimension); + vivecraft$vrPipelinesPerDimension.get(newDimension).put(renderPass, pipe); + } + // set to currently needed renderpass again + if (vivecraft$currentWorldRenderPass != null) { + RenderPassManager.setWorldRenderPass(vivecraft$currentWorldRenderPass); + } else if (ClientDataHolderVR.getInstance().currentPass == RenderPass.GUI) { + RenderPassManager.setGUIRenderPass(); + } else { + RenderPassManager.setVanillaRenderPass(); + } + } + vivecraft$vrPipelinesCurrentDimension = vivecraft$vrPipelinesPerDimension.get(newDimension); + + if (!RenderPassType.isVanilla()) { + if (ClientDataHolderVR.getInstance().currentPass != null) { + pipeline = vivecraft$vrPipelinesCurrentDimension.get(ClientDataHolderVR.getInstance().currentPass); + } else { + pipeline = vivecraft$vrPipelinesCurrentDimension.get(RenderPass.LEFT); + } + } + } + } + + @Group(name = "returnCurrentVRPipeline", min = 1, max = 1) + @Inject(method = "preparePipeline", at = @At(value = "INVOKE", target = "Ljava/util/Map;get(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false, cancellable = true, expect = 0) + private void vivecraft$returnCurrentVRPipeline165(NamespacedId newDimension, CallbackInfoReturnable cir) { + if (!RenderPassType.isVanilla()) { + pipeline = vivecraft$getCurrentVRPipeline(newDimension); + cir.setReturnValue(pipeline); + } + } + + @Unique + private WorldRenderingPipeline vivecraft$getCurrentVRPipeline(Object key) { + return vivecraft$vrPipelinesPerDimension.get(key).get(ClientDataHolderVR.getInstance().currentPass); + } + + @Inject(method = "destroyPipeline", at = @At(value = "INVOKE", target = "Ljava/util/Map;clear()V"), remap = false) + private void vivecraft$destroyVRPipelines(CallbackInfo ci) { + if (VRState.vrInitialized) { + vivecraft$vrPipelinesPerDimension.forEach((dimID, map) -> { + map.forEach((renderPass, pipeline) -> { + VRSettings.logger.info("Destroying VR pipeline {}", renderPass); + resetTextureState(); + pipeline.destroy(); + }); + map.clear(); + }); + vivecraft$shadowRenderTargets = null; + vivecraft$vrPipelinesPerDimension.clear(); + vivecraft$vanillaPipeline = null; + } + } + + @Override + @Unique + public WorldRenderingPipeline vivecraft$getVRPipeline(RenderPass pass) { + return vivecraft$vrPipelinesCurrentDimension.get(pass); + } + + @Override + @Unique + public WorldRenderingPipeline vivecraft$getVanillaPipeline() { + return vivecraft$vanillaPipeline; + } +} diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/optifine/mixin/OptifineLiquidBlockRendererMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/optifine/mixin/OptifineLiquidBlockRendererMixin.java index 8439ebe8e..67f81a152 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/optifine/mixin/OptifineLiquidBlockRendererMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/optifine/mixin/OptifineLiquidBlockRendererMixin.java @@ -10,7 +10,7 @@ @Mixin(LiquidBlockRenderer.class) public class OptifineLiquidBlockRendererMixin { // needed for menuworlds water rendering - @Redirect(method = "tesselate", at = @At(value = "INVOKE", target = "Lnet/optifine/Config;isRenderRegions()Z")) + @Redirect(method = "tesselate", at = @At(value = "INVOKE", target = "Lnet/optifine/Config;isRenderRegions()Z", remap = false), remap = true) private boolean vivecraft$optifineChunkClipping() { return OptifineHelper.isRenderRegions() && (ClientDataHolderVR.getInstance().menuWorldRenderer == null || !ClientDataHolderVR.getInstance().menuWorldRenderer.isOnBuilderThread()); } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/optifine/mixin/ShadersRenderVRMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/optifine/mixin/ShadersRenderVRMixin.java index 2aca5869d..2dad84b33 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/optifine/mixin/ShadersRenderVRMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/optifine/mixin/ShadersRenderVRMixin.java @@ -26,7 +26,7 @@ @Mixin(targets = "net.optifine.shaders.ShadersRender") public class ShadersRenderVRMixin { - @Shadow + @Shadow(remap = false) public static void updateActiveRenderInfo(Camera activeRenderInfo, Minecraft mc, float partialTicks) { } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/rei/mixin/reiTextFieldWidgetMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/rei/mixin/reiTextFieldWidgetMixin.java index 87e563ce4..2ddb07def 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/rei/mixin/reiTextFieldWidgetMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/rei/mixin/reiTextFieldWidgetMixin.java @@ -1,5 +1,6 @@ package org.vivecraft.mod_compat_vr.rei.mixin; +import net.minecraft.client.gui.components.events.ContainerEventHandler; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.At; @@ -11,11 +12,11 @@ @Pseudo @Mixin(targets = {"me.shedaniel.rei.impl.client.gui.widget.basewidgets.TextFieldWidget"}) -public class reiTextFieldWidgetMixin { +public abstract class reiTextFieldWidgetMixin implements ContainerEventHandler { @Inject(method = "setFocused(Z)V", at = @At("HEAD")) private void vivecraft$openKeyboard(boolean focused, CallbackInfo ci) { - if (VRState.vrRunning && !ClientDataHolderVR.getInstance().vrSettings.seated) { + if (VRState.vrRunning && !ClientDataHolderVR.getInstance().vrSettings.seated && (focused || ClientDataHolderVR.getInstance().vrSettings.autoCloseKeyboard)) { KeyboardHandler.setOverlayShowing(focused); } } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/sereneseasons/mixin/SeasonColorHandlersMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/sereneseasons/mixin/SeasonColorHandlersMixin.java index 7bdf741ce..9bfdf3eb1 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/sereneseasons/mixin/SeasonColorHandlersMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/sereneseasons/mixin/SeasonColorHandlersMixin.java @@ -18,26 +18,26 @@ @Mixin(targets = "sereneseasons.handler.season.SeasonColorHandlers") public class SeasonColorHandlersMixin { - @Shadow + @Shadow(remap = false) private static ColorResolver originalGrassColorResolver; - @Shadow + @Shadow(remap = false) private static ColorResolver originalFoliageColorResolver; - @Inject(at = @At("HEAD"), method = "lambda$registerGrassAndFoliageColorHandlers$1", cancellable = true) + @Inject(at = @At("HEAD"), method = "lambda$registerGrassAndFoliageColorHandlers$1", remap = false, cancellable = true) private static void vivecraft$grassColor(Biome biome, double x, double y, CallbackInfoReturnable cir) { if (Minecraft.getInstance().level == null) { cir.setReturnValue(originalGrassColorResolver.getColor(biome, x, y)); } } - @Inject(at = @At("HEAD"), method = "lambda$registerGrassAndFoliageColorHandlers$3", cancellable = true) + @Inject(at = @At("HEAD"), method = "lambda$registerGrassAndFoliageColorHandlers$3", remap = false, cancellable = true) private static void vivecraft$foliageColor(Biome biome, double x, double y, CallbackInfoReturnable cir) { if (Minecraft.getInstance().level == null) { cir.setReturnValue(originalFoliageColorResolver.getColor(biome, x, y)); } } - @Inject(at = @At("HEAD"), method = "lambda$registerBirchColorHandler$4", cancellable = true) + @Inject(at = @At("HEAD"), method = "lambda$registerBirchColorHandler$4", remap = false, cancellable = true) private static void vivecraft$birchColor(BlockState blockState, BlockAndTintGetter blockAndTintGetter, BlockPos blockPos, int tintIndex, CallbackInfoReturnable cir) { if (Minecraft.getInstance().level == null) { cir.setReturnValue(FoliageColor.getBirchColor()); diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/SodiumHelper.java b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/SodiumHelper.java index 0fc305528..7740f66be 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/SodiumHelper.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/SodiumHelper.java @@ -1,18 +1,44 @@ package org.vivecraft.mod_compat_vr.sodium; -import me.jellysquid.mods.sodium.client.render.immediate.model.ModelCuboid; -import me.jellysquid.mods.sodium.client.render.texture.SpriteUtil; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import org.joml.Vector2f; import org.vivecraft.client.Xplat; import org.vivecraft.client_vr.settings.VRSettings; +import org.vivecraft.mod_compat_vr.sodium.extensions.ModelCuboidExtension; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; public class SodiumHelper { + // use reflection, because sodium changed package in 0.6 + private static Method SpriteUtil_MarkSpriteActive; + + private static boolean hasModelCuboidQuads; + private static boolean hasModelCuboidFloats; + private static Field ModelCuboid_Sodium$cuboids; + private static Field ModelCuboid_Quads; + + // quad uvs + private static Field ModelCuboid_u0; + private static Field ModelCuboid_u1; + private static Field ModelCuboid_u2; + private static Field ModelCuboid_u3; + private static Field ModelCuboid_u4; + private static Field ModelCuboid_u5; + private static Field ModelCuboid_v0; + private static Field ModelCuboid_v1; + private static Field ModelCuboid_v2; + + private static Field ModelCuboid$Quad_Textures; + + private static boolean initialized = false; + private static boolean initFailed = false; + public static boolean isLoaded() { - return Xplat.isModLoaded("sodium") || Xplat.isModLoaded("rubidium"); + return Xplat.isModLoaded("sodium") || Xplat.isModLoaded("rubidium") || Xplat.isModLoaded("embeddium"); } public static boolean hasIssuesWithParallelBlockBuilding() { @@ -25,7 +51,14 @@ public static boolean hasIssuesWithParallelBlockBuilding() { } public static void markTextureAsActive(TextureAtlasSprite sprite) { - SpriteUtil.markSpriteActive(sprite); + if (init()) { + try { + // SpriteUtil.markSpriteActive(sprite); + SpriteUtil_MarkSpriteActive.invoke(null, sprite); + } catch (InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } } // NotFixed @@ -33,39 +66,123 @@ public static void markTextureAsActive(TextureAtlasSprite sprite) { // SodiumClientMod.options().quality.enableVignette = b; // } + public static void copyModelCuboidUV(ModelPart source, ModelPart dest, int sourcePoly, int destPoly) { + if (init()) { + if (hasModelCuboidQuads) { + try { + Object sourceQuad = ((Object[]) ModelCuboid_Quads.get(((Object[]) ModelCuboid_Sodium$cuboids.get(source))[0]))[sourcePoly]; + Object destQuad = ((Object[]) ModelCuboid_Quads.get(((Object[]) ModelCuboid_Sodium$cuboids.get(dest))[0]))[destPoly]; - private static boolean hasModelCuboid; - private static boolean checkedForModelCuboid; - private static Field sodium$cuboids; + Vector2f[] sourceTextures = (Vector2f[]) ModelCuboid$Quad_Textures.get(sourceQuad); + Vector2f[] destTextures = (Vector2f[]) ModelCuboid$Quad_Textures.get(destQuad); - public static void copyModelCuboidUV(ModelPart source, ModelPart dest, int sourcePoly, int destPoly) { - if (!checkedForModelCuboid) { - checkedForModelCuboid = true; - try { - Class.forName("me.jellysquid.mods.sodium.client.render.immediate.model.ModelCuboid"); - sodium$cuboids = ModelPart.class.getDeclaredField("sodium$cuboids"); - sodium$cuboids.setAccessible(true); - hasModelCuboid = true; - } catch (ClassNotFoundException ignored) { - return; - } catch (NoSuchFieldException e) { - VRSettings.logger.error("sodium version has ModelCuboids, but field was not found. VR hands will probably look wrong"); - return; + for (int i = 0; i < sourceTextures.length; i++) { + destTextures[i].x = sourceTextures[i].x; + destTextures[i].y = sourceTextures[i].y; + } + } catch (IllegalAccessException | ClassCastException ignored) { + VRSettings.logger.error("Vivecraft: sodium version has ModelCuboids, but field has wrong type. VR hands will probably look wrong"); + hasModelCuboidQuads = false; + } + } else if (hasModelCuboidFloats) { + try { + Object sourceQuad = ((Object[]) ModelCuboid_Sodium$cuboids.get(source))[0]; + float[][] UVs = new float[][]{{ + (float) ModelCuboid_u0.get(sourceQuad), + (float) ModelCuboid_u1.get(sourceQuad), + (float) ModelCuboid_u2.get(sourceQuad), + (float) ModelCuboid_u3.get(sourceQuad), + (float) ModelCuboid_u4.get(sourceQuad), + (float) ModelCuboid_u5.get(sourceQuad) + }, { + (float) ModelCuboid_v0.get(sourceQuad), + (float) ModelCuboid_v1.get(sourceQuad), + (float) ModelCuboid_v2.get(sourceQuad) + }}; + + ((ModelCuboidExtension) ((Object[]) ModelCuboid_Sodium$cuboids.get(dest))[0]).vivecraft$addOverrides( + mapDirection(destPoly), + mapDirection(sourcePoly), + UVs + ); + } catch (IllegalAccessException | ClassCastException ignored) { + VRSettings.logger.error("Vivecraft: sodium version has ModelCuboids, but field has wrong type. VR hands will probably look wrong"); + hasModelCuboidFloats = false; + } } } - if (hasModelCuboid) { + } + + private static int mapDirection(int old) { + return switch (old) { + default -> 4; + case 1 -> 2; + case 2 -> 0; + case 3 -> 1; + case 4 -> 3; + case 5 -> 5; + }; + } + + private static boolean init() { + if (initialized) { + // try to softly fail when something went wrong + return !initFailed; + } + try { + Class spriteUtil = getClassWithAlternative( + "me.jellysquid.mods.sodium.client.render.texture.SpriteUtil", + "net.caffeinemc.mods.sodium.client.render.texture.SpriteUtil" + ); + + SpriteUtil_MarkSpriteActive = spriteUtil.getMethod("markSpriteActive", TextureAtlasSprite.class); + try { - ModelCuboid.Quad sourceQuad = ((ModelCuboid[]) sodium$cuboids.get(source))[0].quads[sourcePoly]; - ModelCuboid.Quad destQuad = ((ModelCuboid[]) sodium$cuboids.get(dest))[0].quads[destPoly]; + // model + Class ModelCuboid = getClassWithAlternative( + "me.jellysquid.mods.sodium.client.render.immediate.model.ModelCuboid", + "net.caffeinemc.mods.sodium.client.render.immediate.model.ModelCuboid" + ); - for (int i = 0; i < sourceQuad.textures.length; i++) { - destQuad.textures[i].x = sourceQuad.textures[i].x; - destQuad.textures[i].y = sourceQuad.textures[i].y; + ModelCuboid_Sodium$cuboids = ModelPart.class.getDeclaredField("sodium$cuboids"); + ModelCuboid_Sodium$cuboids.setAccessible(true); + try { + Class cuboidQuad = getClassWithAlternative( + "me.jellysquid.mods.sodium.client.render.immediate.model.ModelCuboid$Quad", + "net.caffeinemc.mods.sodium.client.render.immediate.model.ModelCuboid$Quad" + ); + ModelCuboid_Quads = ModelCuboid.getDeclaredField("quads"); + ModelCuboid$Quad_Textures = cuboidQuad.getDeclaredField("textures"); + hasModelCuboidQuads = true; + } catch (ClassNotFoundException noQuads) { + ModelCuboid_u0 = ModelCuboid.getDeclaredField("u0"); + ModelCuboid_u1 = ModelCuboid.getDeclaredField("u1"); + ModelCuboid_u2 = ModelCuboid.getDeclaredField("u2"); + ModelCuboid_u3 = ModelCuboid.getDeclaredField("u3"); + ModelCuboid_u4 = ModelCuboid.getDeclaredField("u4"); + ModelCuboid_u5 = ModelCuboid.getDeclaredField("u5"); + ModelCuboid_v0 = ModelCuboid.getDeclaredField("v0"); + ModelCuboid_v1 = ModelCuboid.getDeclaredField("v1"); + ModelCuboid_v2 = ModelCuboid.getDeclaredField("v2"); + hasModelCuboidFloats = true; } - } catch (IllegalAccessException | ClassCastException ignored) { - VRSettings.logger.error("sodium version has ModelCuboids, but field has wrong type. VR hands will probably look wrong"); - hasModelCuboid = false; + } catch (ClassNotFoundException ignored) { + } catch (NoSuchFieldException e) { + VRSettings.logger.error("Vivecraft: sodium version has ModelCuboids, but field was not found. VR hands will probably look wrong"); } + } catch (ClassNotFoundException | NoSuchMethodException e) { + initFailed = true; + VRSettings.logger.error("Vivecraft: Failed to initialize Sodium compat: {}", e.getMessage()); + } + initialized = true; + return !initFailed; + } + + private static Class getClassWithAlternative(String class1, String class2) throws ClassNotFoundException { + try { + return Class.forName(class1); + } catch (ClassNotFoundException e) { + return Class.forName(class2); } } } diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/extensions/ModelCuboidExtension.java b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/extensions/ModelCuboidExtension.java new file mode 100644 index 000000000..79fb4ece3 --- /dev/null +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/extensions/ModelCuboidExtension.java @@ -0,0 +1,8 @@ +package org.vivecraft.mod_compat_vr.sodium.extensions; + +public interface ModelCuboidExtension { + + float[][] vivecraft$getOverrides(); + + void vivecraft$addOverrides(int overrideFaceIndex, int sourceFaceIndex, float[][] source); +} diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/FabricSodiumGameOptionPagesVRMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/FabricSodiumGameOptionPagesVRMixin.java index feb0ca876..9a1780f3f 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/FabricSodiumGameOptionPagesVRMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/FabricSodiumGameOptionPagesVRMixin.java @@ -1,6 +1,5 @@ package org.vivecraft.mod_compat_vr.sodium.mixin; -import me.jellysquid.mods.sodium.client.gui.SodiumGameOptionPages; import net.minecraft.client.GraphicsStatus; import net.minecraft.client.Options; import org.spongepowered.asm.mixin.Mixin; @@ -12,7 +11,10 @@ import org.vivecraft.client_vr.VRState; @Pseudo -@Mixin(SodiumGameOptionPages.class) +@Mixin(targets = { + "me.jellysquid.mods.sodium.client.gui.SodiumGameOptionPages", + "net.caffeinemc.mods.sodium.client.gui.SodiumGameOptionPages" +}) public class FabricSodiumGameOptionPagesVRMixin { @Inject(at = @At("HEAD"), method = "lambda$quality$23", remap = false) diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/ForgeSodiumGameOptionPagesVRMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/ForgeSodiumGameOptionPagesVRMixin.java index b6ec0e043..69e600c56 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/ForgeSodiumGameOptionPagesVRMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/ForgeSodiumGameOptionPagesVRMixin.java @@ -1,6 +1,5 @@ package org.vivecraft.mod_compat_vr.sodium.mixin; -import me.jellysquid.mods.sodium.client.gui.SodiumGameOptionPages; import net.minecraft.client.GraphicsStatus; import net.minecraft.client.Options; import org.spongepowered.asm.mixin.Mixin; @@ -12,7 +11,10 @@ import org.vivecraft.client_vr.VRState; @Pseudo -@Mixin(SodiumGameOptionPages.class) +@Mixin(targets = { + "me.jellysquid.mods.sodium.client.gui.SodiumGameOptionPages", + "net.caffeinemc.mods.sodium.client.gui.SodiumGameOptionPages" +}) public class ForgeSodiumGameOptionPagesVRMixin { @Inject(at = @At("HEAD"), method = "lambda$quality$23", remap = false) diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/ModelCuboidMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/ModelCuboidMixin.java new file mode 100644 index 000000000..38a7eede3 --- /dev/null +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/ModelCuboidMixin.java @@ -0,0 +1,67 @@ +package org.vivecraft.mod_compat_vr.sodium.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.Unique; +import org.vivecraft.mod_compat_vr.sodium.extensions.ModelCuboidExtension; + +@Pseudo +@Mixin(targets = { + "me.jellysquid.mods.sodium.client.render.immediate.model.ModelCuboid", + "net.caffeinemc.mods.sodium.client.render.immediate.model.ModelCuboid"}) +public class ModelCuboidMixin implements ModelCuboidExtension { + @Unique + private float[][] vivecraft$overrides = null; + + @Override + public float[][] vivecraft$getOverrides() { + return vivecraft$overrides; + } + + @Override + public void vivecraft$addOverrides(int overrideFaceIndex, int sourceFaceIndex, float[][] source) { + if (vivecraft$overrides == null) { + vivecraft$overrides = new float[6][5]; + } + vivecraft$overrides[overrideFaceIndex][0] = 1F; + // order taken from me.jellysquid.mods.sodium.client.render.immediate.model.EntityRenderer.prepareVertices + switch (sourceFaceIndex) { + default -> { + vivecraft$overrides[overrideFaceIndex][1] = source[0][1]; + vivecraft$overrides[overrideFaceIndex][2] = source[1][0]; + vivecraft$overrides[overrideFaceIndex][3] = source[0][2]; + vivecraft$overrides[overrideFaceIndex][4] = source[1][1]; + } + case 1 -> { + vivecraft$overrides[overrideFaceIndex][1] = source[0][2]; + vivecraft$overrides[overrideFaceIndex][2] = source[1][1]; + vivecraft$overrides[overrideFaceIndex][3] = source[0][3]; + vivecraft$overrides[overrideFaceIndex][4] = source[1][0]; + } + case 2 -> { + vivecraft$overrides[overrideFaceIndex][1] = source[0][1]; + vivecraft$overrides[overrideFaceIndex][2] = source[1][1]; + vivecraft$overrides[overrideFaceIndex][3] = source[0][2]; + vivecraft$overrides[overrideFaceIndex][4] = source[1][2]; + } + case 3 -> { + vivecraft$overrides[overrideFaceIndex][1] = source[0][4]; + vivecraft$overrides[overrideFaceIndex][2] = source[1][1]; + vivecraft$overrides[overrideFaceIndex][3] = source[0][5]; + vivecraft$overrides[overrideFaceIndex][4] = source[1][2]; + } + case 4 -> { + vivecraft$overrides[overrideFaceIndex][1] = source[0][2]; + vivecraft$overrides[overrideFaceIndex][2] = source[1][1]; + vivecraft$overrides[overrideFaceIndex][3] = source[0][4]; + vivecraft$overrides[overrideFaceIndex][4] = source[1][2]; + } + case 5 -> { + vivecraft$overrides[overrideFaceIndex][1] = source[0][0]; + vivecraft$overrides[overrideFaceIndex][2] = source[1][1]; + vivecraft$overrides[overrideFaceIndex][3] = source[0][1]; + vivecraft$overrides[overrideFaceIndex][4] = source[1][2]; + } + } + } +} diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/RenderSectionManagerVRMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/RenderSectionManagerVRMixin.java deleted file mode 100644 index 9dec3af8a..000000000 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/RenderSectionManagerVRMixin.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.vivecraft.mod_compat_vr.sodium.mixin; - -import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager; -import me.jellysquid.mods.sodium.client.render.chunk.lists.ChunkRenderList; -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; - -@Mixin(RenderSectionManager.class) -public class RenderSectionManagerVRMixin { - - @Shadow(remap = false) - private ChunkRenderList chunkRenderList; - - @Inject(at = @At("HEAD"), method = "getVisibleChunkCount", cancellable = true, remap = false) - private void vivecraft$preventNullpointerException(CallbackInfoReturnable cir) { - if (chunkRenderList == null) { - cir.setReturnValue(-1); - } - } -} diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/SodiumWorldRendererVRMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/SodiumWorldRendererVRMixin.java index 467772bc5..115c81666 100644 --- a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/SodiumWorldRendererVRMixin.java +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/SodiumWorldRendererVRMixin.java @@ -1,6 +1,5 @@ package org.vivecraft.mod_compat_vr.sodium.mixin; -import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.At; @@ -10,18 +9,21 @@ @Pseudo -@Mixin(SodiumWorldRenderer.class) +@Mixin(targets = { + "me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer", + "net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer" +}) public class SodiumWorldRendererVRMixin { @Group(name = "forceChunkUpdate", min = 1, max = 1) - @ModifyVariable(at = @At("STORE"), ordinal = 1, method = "updateChunks", expect = 0) + @ModifyVariable(at = @At("STORE"), ordinal = 1, method = "updateChunks", remap = false, expect = 0) public boolean vivecraft$RenderUpdate(boolean b) { // always update chunk graph in VR to prevent missing chunks return !RenderPassType.isVanilla() || b; } @Group(name = "forceChunkUpdate", min = 1, max = 1) - @ModifyVariable(at = @At("STORE"), ordinal = 2, method = "setupTerrain", expect = 0) + @ModifyVariable(at = @At("STORE"), ordinal = 2, method = "setupTerrain", remap = false, expect = 0) public boolean vivecraft$RenderUpdateSodium5(boolean b) { // always update chunk graph in VR to prevent missing chunks return !RenderPassType.isVanilla() || b; diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/caffeinemc/EntityRendererMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/caffeinemc/EntityRendererMixin.java new file mode 100644 index 000000000..e9c09ed0d --- /dev/null +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/caffeinemc/EntityRendererMixin.java @@ -0,0 +1,37 @@ +package org.vivecraft.mod_compat_vr.sodium.mixin.caffeinemc; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.caffeinemc.mods.sodium.client.render.immediate.model.ModelCuboid; +import org.joml.Vector2f; +import org.spongepowered.asm.mixin.Final; +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.callback.CallbackInfo; +import org.vivecraft.mod_compat_vr.sodium.extensions.ModelCuboidExtension; + +@Pseudo +@Mixin(targets = "net.caffeinemc.mods.sodium.client.render.immediate.model.EntityRenderer") +public class EntityRendererMixin { + @Shadow(remap = false) + private static void buildVertexTexCoord(Vector2f[] uvs, float u1, float v1, float u2, float v2) { + } + + @Shadow(remap = false) + @Final + private static Vector2f[][] VERTEX_TEXTURES; + + @Inject(at = @At("TAIL"), method = "prepareVertices", remap = false) + private static void vivecraft$overrideVrHands(PoseStack.Pose matrices, ModelCuboid cuboid, CallbackInfo ci) { + float[][] overrides = ((ModelCuboidExtension) cuboid).vivecraft$getOverrides(); + if (overrides != null) { + for (int i = 0; i < overrides.length; i++) { + if (overrides[i][0] > 0F) { + buildVertexTexCoord(VERTEX_TEXTURES[i], overrides[i][1], overrides[i][2], overrides[i][3], overrides[i][4]); + } + } + } + } +} diff --git a/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/jellysquid/EntityRendererMixin.java b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/jellysquid/EntityRendererMixin.java new file mode 100644 index 000000000..867a7f71c --- /dev/null +++ b/common/src/main/java/org/vivecraft/mod_compat_vr/sodium/mixin/jellysquid/EntityRendererMixin.java @@ -0,0 +1,37 @@ +package org.vivecraft.mod_compat_vr.sodium.mixin.jellysquid; + +import com.mojang.blaze3d.vertex.PoseStack; +import me.jellysquid.mods.sodium.client.render.immediate.model.ModelCuboid; +import org.joml.Vector2f; +import org.spongepowered.asm.mixin.Final; +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.callback.CallbackInfo; +import org.vivecraft.mod_compat_vr.sodium.extensions.ModelCuboidExtension; + +@Pseudo +@Mixin(targets = "me.jellysquid.mods.sodium.client.render.immediate.model.EntityRenderer") +public class EntityRendererMixin { + @Shadow(remap = false) + private static void buildVertexTexCoord(Vector2f[] uvs, float u1, float v1, float u2, float v2) { + } + + @Shadow(remap = false) + @Final + private static Vector2f[][] VERTEX_TEXTURES; + + @Inject(at = @At("TAIL"), method = "prepareVertices", remap = false) + private static void vivecraft$overrideVrHands(PoseStack.Pose matrices, ModelCuboid cuboid, CallbackInfo ci) { + float[][] overrides = ((ModelCuboidExtension) cuboid).vivecraft$getOverrides(); + if (overrides != null) { + for (int i = 0; i < overrides.length; i++) { + if (overrides[i][0] > 0F) { + buildVertexTexCoord(VERTEX_TEXTURES[i], overrides[i][1], overrides[i][2], overrides[i][3], overrides[i][4]); + } + } + } + } +} diff --git a/common/src/main/java/org/vivecraft/server/ServerNetworking.java b/common/src/main/java/org/vivecraft/server/ServerNetworking.java index 0eb7596a0..eefab1ef5 100644 --- a/common/src/main/java/org/vivecraft/server/ServerNetworking.java +++ b/common/src/main/java/org/vivecraft/server/ServerNetworking.java @@ -6,7 +6,6 @@ import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.server.network.ServerPlayerConnection; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Pose; @@ -20,6 +19,7 @@ import org.vivecraft.server.config.ServerConfig; import java.util.*; +import java.util.function.Consumer; public class ServerNetworking { @@ -28,9 +28,8 @@ public class ServerNetworking { private static final Logger LOGGER = LoggerFactory.getLogger("VivecraftServer"); - public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetID, FriendlyByteBuf buffer, ServerGamePacketListenerImpl listener) { - var playerEntity = listener.player; - ServerVivePlayer vivePlayer = ServerVRPlayers.getVivePlayer(playerEntity); + public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetID, FriendlyByteBuf buffer, ServerPlayer player, Consumer packetConsumer) { + ServerVivePlayer vivePlayer = ServerVRPlayers.getVivePlayer(player); if (vivePlayer == null && packetID != CommonNetworkHelper.PacketDiscriminators.VERSION) { return; @@ -40,7 +39,7 @@ public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetI case VERSION: // Vivecraft client connected, send server settings - vivePlayer = new ServerVivePlayer(playerEntity); + vivePlayer = new ServerVivePlayer(player); // read initial VR State byte[] stringBytes = new byte[buffer.readableBytes()]; @@ -49,7 +48,7 @@ public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetI String clientVivecraftVersion = parts[0]; if (ServerConfig.debug.get()) { - LOGGER.info("Vivecraft: player '{}' joined with {}", listener.player.getName().getString(), clientVivecraftVersion); + LOGGER.info("Vivecraft: player '{}' joined with {}", player.getName().getString(), clientVivecraftVersion); } if (parts.length >= 3) { @@ -61,14 +60,14 @@ public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetI && clientMinVersion <= CommonNetworkHelper.MAX_SUPPORTED_NETWORK_VERSION) { vivePlayer.networkVersion = Math.min(clientMaxVersion, CommonNetworkHelper.MAX_SUPPORTED_NETWORK_VERSION); if (ServerConfig.debug.get()) { - LOGGER.info("{} networking supported, using version {}", listener.player.getName().getString(), vivePlayer.networkVersion); + LOGGER.info("{} networking supported, using version {}", player.getName().getString(), vivePlayer.networkVersion); } } else { // unsupported version, send notification, and disregard - listener.player.sendSystemMessage(Component.literal("Unsupported vivecraft version, VR features will not work")); + player.sendSystemMessage(Component.literal("Unsupported vivecraft version, VR features will not work")); if (ServerConfig.debug.get()) { LOGGER.info("{} networking not supported. client range [{},{}], server range [{},{}]", - listener.player.getName().getString(), + player.getName().getString(), clientMinVersion, clientMaxVersion, CommonNetworkHelper.MIN_SUPPORTED_NETWORK_VERSION, @@ -80,23 +79,23 @@ public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetI // client didn't send a version, so it's a legacy client vivePlayer.networkVersion = -1; if (ServerConfig.debug.get()) { - LOGGER.info("{} using legacy networking", listener.player.getName().getString()); + LOGGER.info("{} using legacy networking", player.getName().getString()); } } vivePlayer.setVR(!clientVivecraftVersion.contains("NONVR")); - ServerVRPlayers.getPlayersWithVivecraft(listener.player.server).put(playerEntity.getUUID(), vivePlayer); + ServerVRPlayers.getPlayersWithVivecraft(player.server).put(player.getUUID(), vivePlayer); - listener.send(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.VERSION, CommonDataHolder.getInstance().versionIdentifier)); - listener.send(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.REQUESTDATA, new byte[0])); + packetConsumer.accept(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.VERSION, CommonDataHolder.getInstance().versionIdentifier)); + packetConsumer.accept(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.REQUESTDATA, new byte[0])); if (ServerConfig.climbeyEnabled.get()) { - listener.send(getClimbeyServerPacket()); + packetConsumer.accept(getClimbeyServerPacket()); } if (ServerConfig.teleportEnabled.get()) { - listener.send(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.TELEPORT, new byte[0])); + packetConsumer.accept(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.TELEPORT, new byte[0])); } if (ServerConfig.teleportLimitedSurvival.get()) { FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer()); @@ -112,7 +111,10 @@ public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetI byteBuf.writeUtf("teleportLimitHoriz"); byteBuf.writeUtf("" + ServerConfig.teleportHorizontalLimit.get()); - listener.send(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.SETTING_OVERRIDE, byteBuf.readByteArray())); + byte[] array = new byte[byteBuf.readableBytes()]; + byteBuf.readBytes(array); + byteBuf.release(); + packetConsumer.accept(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.SETTING_OVERRIDE, array)); } if (ServerConfig.worldscaleLimited.get()) { @@ -123,17 +125,31 @@ public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetI byteBuf.writeUtf("worldScale.max"); byteBuf.writeUtf("" + ServerConfig.worldscaleMax.get()); - listener.send(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.SETTING_OVERRIDE, byteBuf.readByteArray())); + byte[] array = new byte[byteBuf.readableBytes()]; + byteBuf.readBytes(array); + byteBuf.release(); + packetConsumer.accept(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.SETTING_OVERRIDE, array)); + } + + if (ServerConfig.forceThirdPersonItems.get()) { + FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer()); + byteBuf.writeUtf("thirdPersonItems"); + byteBuf.writeUtf("" + true); + + byte[] array = new byte[byteBuf.readableBytes()]; + byteBuf.readBytes(array); + byteBuf.release(); + packetConsumer.accept(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.SETTING_OVERRIDE, array)); } if (ServerConfig.crawlingEnabled.get()) { - listener.send(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.CRAWL, new byte[0])); + packetConsumer.accept(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.CRAWL, new byte[0])); } // send if hotswitching is allowed - listener.send(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.VR_SWITCHING, new byte[]{(byte) (ServerConfig.vrSwitchingEnabled.get() && !ServerConfig.vr_only.get() ? 1 : 0)})); + packetConsumer.accept(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.VR_SWITCHING, new byte[]{(byte) (ServerConfig.vrSwitchingEnabled.get() && !ServerConfig.vr_only.get() ? 1 : 0)})); - listener.send(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.NETWORK_VERSION, new byte[]{(byte) vivePlayer.networkVersion})); + packetConsumer.accept(getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators.NETWORK_VERSION, new byte[]{(byte) vivePlayer.networkVersion})); break; case IS_VR_ACTIVE: @@ -142,11 +158,11 @@ public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetI } vivePlayer.setVR(!vivePlayer.isVR()); if (!vivePlayer.isVR()) { - for (var trackingPlayer : ServerNetworking.getTrackingPlayers(playerEntity)) { - if (!ServerVRPlayers.getPlayersWithVivecraft(listener.player.server).containsKey(trackingPlayer.getPlayer().getUUID()) || trackingPlayer.getPlayer() == playerEntity) { + for (var trackingPlayer : ServerNetworking.getTrackingPlayers(player)) { + if (!ServerVRPlayers.getPlayersWithVivecraft(player.server).containsKey(trackingPlayer.getPlayer().getUUID()) || trackingPlayer.getPlayer() == player) { continue; } - trackingPlayer.send(createVRActivePlayerPacket(false, playerEntity.getUUID())); + trackingPlayer.send(createVRActivePlayerPacket(false, player.getUUID())); } } break; @@ -174,11 +190,11 @@ public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetI float f = buffer.readFloat(); float f1 = buffer.readFloat(); float f2 = buffer.readFloat(); - playerEntity.absMoveTo(f, f1, f2, playerEntity.getYRot(), playerEntity.getXRot()); + player.absMoveTo(f, f1, f2, player.getYRot(), player.getXRot()); break; case CLIMBING: - playerEntity.fallDistance = 0.0F; + player.fallDistance = 0.0F; break; case ACTIVEHAND: vivePlayer.activeHand = buffer.readByte(); @@ -193,7 +209,7 @@ public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetI vivePlayer.crawling = buffer.readByte() != 0; if (vivePlayer.crawling) { - playerEntity.setPose(Pose.SWIMMING); + player.setPose(Pose.SWIMMING); } break; // legacy support @@ -201,9 +217,9 @@ public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetI case CONTROLLER1DATA: case HEADDATA: Map playerData; - if ((playerData = legacyDataMap.get(playerEntity.getUUID())) == null) { + if ((playerData = legacyDataMap.get(player.getUUID())) == null) { playerData = new HashMap<>(); - legacyDataMap.put(playerEntity.getUUID(), playerData); + legacyDataMap.put(player.getUUID(), playerData); } // keep the buffer around buffer.retain(); @@ -228,7 +244,7 @@ public static void handlePacket(CommonNetworkHelper.PacketDiscriminators packetI headData.release(); controller0Data.release(); controller1Data.release(); - legacyDataMap.remove(playerEntity.getUUID()); + legacyDataMap.remove(player.getUUID()); } break; } @@ -242,7 +258,7 @@ public static Set getTrackingPlayers(Entity entity) { } public static ClientboundCustomPayloadPacket createVRActivePlayerPacket(boolean vrActive, UUID playerID) { - var buffer = new FriendlyByteBuf(Unpooled.buffer()); + FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); buffer.writeByte(CommonNetworkHelper.PacketDiscriminators.IS_VR_ACTIVE.ordinal()); buffer.writeBoolean(vrActive); buffer.writeUUID(playerID); @@ -250,7 +266,7 @@ public static ClientboundCustomPayloadPacket createVRActivePlayerPacket(boolean } public static ClientboundCustomPayloadPacket createUberPacket(Player player, VrPlayerState vrPlayerState, float worldScale, float heightScale) { - var buffer = new FriendlyByteBuf(Unpooled.buffer()); + FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); buffer.writeByte(CommonNetworkHelper.PacketDiscriminators.UBERPACKET.ordinal()); buffer.writeUUID(player.getUUID()); vrPlayerState.serialize(buffer); @@ -260,10 +276,10 @@ public static ClientboundCustomPayloadPacket createUberPacket(Player player, VrP } public static ClientboundCustomPayloadPacket getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators command, byte[] payload) { - FriendlyByteBuf friendlybytebuf = new FriendlyByteBuf(Unpooled.buffer()); - friendlybytebuf.writeByte(command.ordinal()); - friendlybytebuf.writeBytes(payload); - return new ClientboundCustomPayloadPacket(CommonNetworkHelper.CHANNEL, friendlybytebuf); + FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); + buffer.writeByte(command.ordinal()); + buffer.writeBytes(payload); + return new ClientboundCustomPayloadPacket(CommonNetworkHelper.CHANNEL, buffer); } public static ClientboundCustomPayloadPacket getClimbeyServerPacket() { @@ -287,10 +303,10 @@ public static ClientboundCustomPayloadPacket getClimbeyServerPacket() { } public static ClientboundCustomPayloadPacket getVivecraftServerPacket(CommonNetworkHelper.PacketDiscriminators command, String payload) { - FriendlyByteBuf friendlybytebuf = new FriendlyByteBuf(Unpooled.buffer()); - friendlybytebuf.writeByte(command.ordinal()); - friendlybytebuf.writeUtf(payload); - return new ClientboundCustomPayloadPacket(CommonNetworkHelper.CHANNEL, friendlybytebuf); + FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); + buffer.writeByte(command.ordinal()); + buffer.writeUtf(payload); + return new ClientboundCustomPayloadPacket(CommonNetworkHelper.CHANNEL, buffer); } public static void sendVrPlayerStateToClients(ServerPlayer vrPlayerEntity) { diff --git a/common/src/main/java/org/vivecraft/server/config/ServerConfig.java b/common/src/main/java/org/vivecraft/server/config/ServerConfig.java index e3c40adc6..6c6823ad3 100644 --- a/common/src/main/java/org/vivecraft/server/config/ServerConfig.java +++ b/common/src/main/java/org/vivecraft/server/config/ServerConfig.java @@ -62,6 +62,8 @@ public class ServerConfig { public static ConfigBuilder.DoubleValue worldscaleMax; public static ConfigBuilder.DoubleValue worldscaleMin; + public static ConfigBuilder.BooleanValue forceThirdPersonItems; + public static ConfigBuilder.BooleanValue vrSwitchingEnabled; private static CommentedFileConfig config; @@ -307,6 +309,16 @@ private static void fixConfig(CommentedConfig config, ConfigSpec.CorrectionListe // end worldScale builder.pop(); + builder + .push("settingOverrides") + .comment("Other client settings to override"); + forceThirdPersonItems = builder + .push("thirdPersonItems") + .comment("Forces players to use the raw item position setting") + .define(false); + // end settingOverrides + builder.pop(); + builder .push("vrSwitching") .comment("VR hotswitch settings"); diff --git a/common/src/main/resources/assets/vivecraft/lang/de_de.json b/common/src/main/resources/assets/vivecraft/lang/de_de.json index 3626635ab..73304a5d4 100644 --- a/common/src/main/resources/assets/vivecraft/lang/de_de.json +++ b/common/src/main/resources/assets/vivecraft/lang/de_de.json @@ -41,6 +41,19 @@ "vivecraft.key.keyboardShift": "Umschalt", "vivecraft.key.climbeyGrab": "Kletterausrüstung", "vivecraft.key.climbeyJump": "Sprung-Schuhe", + "_comment_quickcommands": "double spacing is intentional, to get minecraft to sort them right", + "vivecraft.key.quickcommand1": "Schnellbefehl 1", + "vivecraft.key.quickcommand2": "Schnellbefehl 2", + "vivecraft.key.quickcommand3": "Schnellbefehl 3", + "vivecraft.key.quickcommand4": "Schnellbefehl 4", + "vivecraft.key.quickcommand5": "Schnellbefehl 5", + "vivecraft.key.quickcommand6": "Schnellbefehl 6", + "vivecraft.key.quickcommand7": "Schnellbefehl 7", + "vivecraft.key.quickcommand8": "Schnellbefehl 8", + "vivecraft.key.quickcommand9": "Schnellbefehl 9", + "vivecraft.key.quickcommand10": "Schnellbefehl 10", + "vivecraft.key.quickcommand11": "Schnellbefehl 11", + "vivecraft.key.quickcommand12": "Schnellbefehl 12", "_comment2": "Key binding categories", "vivecraft.key.category.gui": "Benutzeroberfläche", "vivecraft.key.category.climbey": "Kletter Bewegung", @@ -102,6 +115,7 @@ "vivecraft.options.CROSSHAIR_SCALES_WITH_DISTANCE": "Fadenkreuzskalierung", "vivecraft.options.RENDER_BLOCK_OUTLINE_MODE": "Blockumriss anzeigen", "vivecraft.options.AUTO_OPEN_KEYBOARD": "Tastatur immer öffnen", + "vivecraft.options.AUTO_CLOSE_KEYBOARD": "Tastatur auto schließen", "vivecraft.options.RADIAL_MODE_HOLD": "Kreismenü Modus", "vivecraft.options.PHYSICAL_KEYBOARD": "Tastaturtyp", "vivecraft.options.PHYSICAL_KEYBOARD_SCALE": "Tastaturgröße", @@ -140,6 +154,7 @@ "vivecraft.options.REALISTIC_CLIMB": "Raumskala Klettern", "vivecraft.options.REALISTIC_SWIM": "Raumskala Schwimmen", "vivecraft.options.REALISTIC_ROW": "Raumskala Rudern", + "vivecraft.options.REALISTIC_DISMOUNT": "Raumskala Absteigen", "vivecraft.options.WALK_MULTIPLIER": "Lauf Multiplikator", "vivecraft.options.FREEMOVE_MODE": "Frei Bewegen", "vivecraft.options.VEHICLE_ROTATION": "Vehikel Rotation", @@ -190,6 +205,7 @@ "vivecraft.options.CROSSHAIR_SCALES_WITH_DISTANCE.tooltip": "Bestimmt, wie sich das Fadenkreuz mit der Entfernung verändert.\n An: Das Fadenkreuz wird in der Entfernung größer, um aus Ihrer Sicht gleich groß zu bleiben.\n Aus: Das Fadenkreuz wird in der Welt immer gleich groß sein und mit der Entfernung schrumpfen.", "vivecraft.options.RENDER_BLOCK_OUTLINE_MODE.tooltip": "Legt den Anzeigemodus der Blockumrisse im Spiel fest.\n Immer: Der Blockumriss wird immer angezeigt, auch wenn das HUD deaktiviert ist.\n Mit HUD: Der Blockumriss wird nur angezeigt, wenn das HUD aktiviert ist.\n Nie: Der Blockumriss wird nie angezeigt.", "vivecraft.options.AUTO_OPEN_KEYBOARD.tooltip": "Wenn deaktiviert, wird die Tastatur nur geöffnet, wenn Sie auf ein Textfeld klicken oder wenn ein Textfeld den Fokus nicht verlieren kann.\n\nWenn aktiviert, öffnet sich die Tastatur automatisch, sobald ein Textfeld den Fokus erhält. Wenn sie aktiviert ist, wird sie in unerwünschten Situationen mit Mods geöffnet.", + "vivecraft.options.AUTO_CLOSE_KEYBOARD.tooltip": "Wenn aktiviert, wird die Tastatur automatisch geschlossen, wenn das aktive Menü wechselt.", "vivecraft.options.RADIAL_MODE_HOLD.tooltip": "Verhalten des Kreismenüs beim Drücken der Taste.\n Halten: Kreismenü-Taste halten, über Auswahl schweben und loslassen.\n Drücken: Kreismenü-Taste drücken, Knöpfe anklicken, Kreismenü-Taste erneut drücken um zu schließen.", "vivecraft.options.PHYSICAL_KEYBOARD.tooltip": "Welche Art von VR-Tastatur zum Tippen verwendet werden soll.\n Physisch: Eine Tastatur, auf der Sie wie auf einer echten Tastatur tippen können.\n Zeiger: Eine Tastatur, die Sie verwenden können, indem Sie mit dem Fadenkreuz des Controllers von einen der beiden Controller zeigen und drücken.", "vivecraft.options.PHYSICAL_KEYBOARD_SCALE.tooltip": "Wie groß die physische Tastatur im Verhältnis zu ihrer Basisgröße sein sollte.", @@ -222,12 +238,13 @@ "vivecraft.options.RENDER_SCALEFACTOR.tooltip": "Die interne Rendering-Skala des Spiels, relativ zum nativen HMD-Display. Höhere Werte verbessern die visuelle Qualität auf Kosten der Leistung.", "vivecraft.options.MONO_FOV.tooltip": "Das für den unverzerrten Spiegelmodus verwendete FOV.", "vivecraft.options.MIRROR_CENTER_SMOOTH.tooltip": "Glättet die Position und Richtung des Headsets für die Spiegel Darstellung über die angegebene Zeit. Reduziert abrupte Änderungen und zittern.", - "vivecraft.options.REALISTIC_JUMP.tooltip": "Wenn eingeschaltet, springt Ihr Spieler sobald Sie im wirklichen Leben springen. Aktiviert auch Jump Boots.", + "vivecraft.options.REALISTIC_JUMP.tooltip": "Wenn eingeschaltet, springt Ihr Spieler sobald Sie im wirklichen Leben springen. Aktiviert auch die Sprung-Schuhe.\nAutomatisch deaktiviert das Springen wenn die Sprung-Schuhe ausgerüstet sind, um versehentliches springen zu verhindern.", "vivecraft.options.REALISTIC_SNEAK.tooltip": "Wenn eingeschaltet , wird sich Ihr Spieler sobald Sie sich im wirklichen Leben ducken, auch schleichen.", "vivecraft.options.PHYSICAL_GUI.tooltip": "Wenn sie eingeschaltet ist, werden GUIs durch interaktionsfähige 3D-Modelle ersetzt.\nWenn die Rucksackverfolgung aktiviert ist, bringt ein Griff auf den Rücken den Inventarbeutel zum Vorschein.", "vivecraft.options.REALISTIC_CLIMB.tooltip": "Wenn eingeschaltet, erlauben Sie das Besteigen von Leitern und Ranken, indem Sie diese berühren. Ermöglicht auch das Besteigen von Krallen.", "vivecraft.options.REALISTIC_SWIM.tooltip": "Falls eingeschaltet, erlauben Sie das Schwimmen durch Brustschwimm-Bewegung mit den Controllern.", - "vivecraft.options.REALISTIC_ROW.tooltip": "Ruder, Ruder, Ruder dein Boot... wie verrückt mit den Armen .", + "vivecraft.options.REALISTIC_ROW.tooltip": "Ruder, Ruder, Ruder dein Boot... wie verrückt mit den Armen.", + "vivecraft.options.REALISTIC_DISMOUNT.tooltip": "Steige von Objekten ab, indem du dich einen Meter von ihnen entfernst.\nKann Probleme haben mit großen Objekten von anderen Mods.", "vivecraft.options.WALK_MULTIPLIER.tooltip": "Multipliziert Ihre Position im Raum mit einem Faktor.\nErlaubt Ihnen, mehr herumzulaufen, kann aber Bewegungsübelkeit verursachen.", "vivecraft.options.FREEMOVE_MODE.tooltip": "Die Quelle für die Frei Bewegen-Richtung.\n\n Controller: Richtung des nicht dominanten Controllers.\n HMD: Blickrichtung des Headsets.\n Run-In-Place: Die Neigung basiert auf dem Schwingen der Controller. Pitch ist Ihr Headset.\n Raum: Die Neigung ist relativ zu Ihrem VR-Raum nach vorne. Neigung: Die Neigung ist basiert auf Ihr Headset. Dieser Modus ist am besten nur für 180 Setups geeignet.", "vivecraft.options.VEHICLE_ROTATION.tooltip": "Wenn man in einem Vehikel fährt, dreht sich die Welt, während sich das Vehikel dreht. Kann verwirrend sein.", @@ -355,6 +372,9 @@ "vivecraft.gui.alignkatwalk": "KAT WALK Ausrichten", "vivecraft.gui.movethirdpersoncam": "Bewege 3. Kamera", "vivecraft.gui.social": "Sozial", + "vivecraft.gui.downloadfrom": "Von %s herunterladen", + "vivecraft.gui.dontshowagain": "Nicht mehr anzeigen", + "vivecraft.gui.openguide": "Anleitung öffnen", "_comment13": "Items", "vivecraft.item.jumpboots": "Sprung-Schuhe", "vivecraft.item.climbclaws": "Kletterkrallen", @@ -380,12 +400,14 @@ "vivecraft.messages.teleportenabled": "Bewegungseinschränkung deaktiviert (Teleportation erlaubt)", "vivecraft.messages.walkupblocks": "Blöcke hochlaufen (RCTRL+B): %s", "vivecraft.messages.showaim": "Ziel zeigen (RCTRL+RSHIFT): aktiviert", - "vivecraft.messages.playerinertia": "Spieler Bewegungsträgheit (LCTRL+I): %s", + "vivecraft.messages.playerinertia": "Spieler Bewegungsträgheit (RCTRL+I): %s", "vivecraft.messages.movementmodeswitch": "Bewegungsmodus gewechselt zu: %s", "vivecraft.messages.coords": "X: %.2f Y: %.2f Z: %.2f", "vivecraft.messages.angles": "Längsachse: %.1f Querachse: %.1f Vertikalachse: %.1f", "vivecraft.messages.heightset": "Körpergröße gesetzt auf %d%%", "vivecraft.messages.airtypingwarning": "Du tipps ohne einen Bildschirm offen zu haben. Wenn du eine Tastenbindung aktivieren wolltest, aktiviere \"Tastatur aktiviert Bindungen\" in den VR Einstellungen.", + "vivecraft.messages.gctitle": "Nicht optimaler Garbage Collector", + "vivecraft.messages.gcinfo": "Ihr derzeitiger Garbage Collector ist %s, welcher nicht optimal for Vivecraft ist und Ruckler oder verringerte Bildraten verursachen kann. \n\nIhr System scheint für %s und %s GB oder mehr Heap Speicher auszureichen. Dies ist empfohlen für das flüssigste Spielerlebnis. Fügen Sie %s zu ihren Java Argumenten um diese zu nutzen.\n\nWenn Sie unsicher sind wie Sie die Java Argumente anpassen können, klicken Sie unten auf \"%s\".", "_comment_m": "mixin version exclusive strings", "_comment_m0": "Option values", @@ -394,6 +416,7 @@ "vivecraft.options.shaderguirender.aftershader": "Nach Shader", "vivecraft.options.shaderguirender.aftertranslucent": "Transparent", "vivecraft.options.shaderguirender.beforetranslucentsolid": "Undurchsichtig", + "vivecraft.options.freemove.auto": "Automatisch", "vivecraft.options.chatserverpluginmessage.always": "Immer", "vivecraft.options.chatserverpluginmessage.serveronly": "Nur Server", "vivecraft.options.chatserverpluginmessage.never": "Nie", @@ -403,6 +426,9 @@ "vivecraft.options.addnew": "Neuen hinzufügen", "vivecraft.options.menuworldfallback.dirtbox": "Erdbox", "vivecraft.options.menuworldfallback.panorama": "Panorama", + "vivecraft.options.vrprovider.openvr": "OpenVR/SteamVR", + "vivecraft.options.vrprovider.nullvr": "NullVR", + "vivecraft.options.realisticjump.auto": "Automatisch", "_comment_m5": "Option names", "vivecraft.options.LOW_HEALTH_INDICATOR": "Gesundheit Indikator", "vivecraft.options.SHADER_GUI_RENDER": "Shader GUI", @@ -416,33 +442,41 @@ "vivecraft.options.SHOW_PLUGIN_MISSING": "Plugin fehlt Nachricht", "vivecraft.options.CHAT_MESSAGE_STENCIL": "Schablonen Nachricht", "vivecraft.options.VR_HOTSWITCH": "Schnellwechsel", + "vivecraft.options.VR_ENABLED": "VR aktiv", + "vivecraft.options.VR_REMEMBER_ENABLED": "VR Status merken", + "vivecraft.options.VR_PLUGIN": "VR Plugin", "vivecraft.options.VR_TOGGLE_BUTTON_VISIBLE": "VR Aktivierungsknopf Sichtbar", "vivecraft.options.VR_SETTINGS_BUTTON_VISIBLE": "VR Einstellungsknopf Sichtbar", "vivecraft.options.VR_SETTINGS_BUTTON_POSITION": "VR Einstellungsknopf Position", "vivecraft.options.INGAME_BINDINGS_IN_GUI": "Im-Spiel Tasten im GUI", "vivecraft.options.MENU_WORLD_FALLBACK": "Ersatz Methode", + "vivecraft.options.MIRROR_CROP": "Spiegel Zuschnitt", "_comment_m6": "Option tooltips", "vivecraft.options.LOW_HEALTH_INDICATOR.tooltip": "Pulsiert den Bildschirm Rot bei niedriger Gesundheit, um den derzeitigen Gesundheitszustand anzuzeigen.", "vivecraft.options.SHADER_GUI_RENDER.tooltip": "Bestimmt wie die Benutzeroberfläche mit Shadern dargestellt wird.\n Nach Shader: zeigt die Benutzeroberfläche ohne Shader, beste Kompatibilität. (Probleme mit PTGI HRR)\n Transparent: zeigt die Benutzeroberfläche mit Shadern und transparent. (Probleme mit Sildurs Vibrant)\n Undurchsichtig: zeigt die Benutzeroberfläche mit Shadern, aber Undurchsichtig", "vivecraft.options.DOUBLE_GUI_RESOLUTION.tooltip": "Wenn dies eingeschalten ist, wird das GUI in 1440p dargestellt anstatt von 720p, welches die Schärfe enorm erhöht.\nKann mehr Leistung benötigen, bei Grafikkarten mit begrenzter Speicherbandbreite.", "vivecraft.options.GUI_SCALE.tooltip": "Die anzuwendende GUI Skalierung, wenn VR aktiv ist.", "vivecraft.options.HUD_MAX_GUI_SCALE.tooltip": "Wenn dies eingeschalten ist, wird das HUD immer die maximale GUI Skalierung verwenden, egal auf was 'VR GUI Skalierung' gestellt ist.", - "vivecraft.options.VR_MODE.tooltip": "wechsle zwischen VR/NONVR", - "vivecraft.options.FREEMOVE_FLY_MODE.tooltip": "Die Quelle für die Frei Bewegen-Richtung im Flugmodus.\n\n Auto: Verwendet die gleiche richtung wie das normale Frei Bewegen.\n Controller: Richtung des nicht dominanten Controllers.\n HMD: Blickrichtung des Headsets.", + "vivecraft.options.VR_ENABLED.tooltip": "wechsle zwischen VR/NONVR", + "vivecraft.options.VR_REMEMBER_ENABLED.tooltip": "Aktiviert VR beim starten des Spiels, wenn es das letzte mal aktiv war.", + "vivecraft.options.VR_PLUGIN.tooltip": "Welches VR Plugin genutzt werden soll:\n OpenVR: Benützt SteamVR als Backend.\n NullVR: Benützt keine VR Api und lässt das Spiel im VR Modus laufen ohne Headset.", + "vivecraft.options.FREEMOVE_FLY_MODE.tooltip": "Die Quelle für die Frei Bewegen-Richtung im Flugmodus.\n\n Automatisch: Verwendet die gleiche richtung wie das normale Frei Bewegen.\n Controller: Richtung des nicht dominanten Controllers.\n HMD: Blickrichtung des Headsets.", "vivecraft.options.SHOW_UPDATES.tooltip": "Wie oft eine Update Nachricht im Chat gezeigt werden soll.\n Immer: zeigt die Nachricht immer, wenn eine Welt geladen wird.\n Einmal: Zeigt die Nachricht einmal, wenn ein neues Update verfügbar ist.", - "vivecraft.options.SHOW_PLUGIN.tooltip": "Wann die Server Mod erkannt Nachricht im Chat gezeigt werden soll.\n Immer: Zeigt die Nachricht in Einzel/Mehrspieler.\n Nur Server: Zeigt die Nachricht nur im Mehrspieler.\n Nie: Zeigt die Nachricht niemals.", + "vivecraft.options.SHOW_PLUGIN.tooltip": "Wann die \"Server Mod erkannt\" Nachricht im Chat gezeigt werden soll.\n Immer: Zeigt die Nachricht in Einzel/Mehrspieler.\n Nur Server: Zeigt die Nachricht nur im Mehrspieler.\n Nie: Zeigt die Nachricht niemals.", "vivecraft.options.UPDATE_TYPE.tooltip": "Gibt an, welche Updates eine Benachrichtigung verursachen.", - "vivecraft.options.SHOW_PLUGIN_MISSING.tooltip": "Wie oft die Server Mod nicht erkannt Nachricht im Chat gezeigt werden soll.\n Immer: Zeigt die Nachricht bei Server beitritt und Dimension/Server wechsel.\n Einmal: Zeigt die Nachricht nur beim beitreten eines Servers.", + "vivecraft.options.SHOW_PLUGIN_MISSING.tooltip": "Wie oft die \"Server Mod nicht erkannt\" Nachricht im Chat gezeigt werden soll.\n Immer: Zeigt die Nachricht bei Server beitritt und Dimension/Server wechsel.\n Einmal: Zeigt die Nachricht nur beim beitreten eines Servers.", "vivecraft.options.CHAT_MESSAGE_STENCIL.tooltip": "Schreibt eine Nachricht in den Chat, wenn ein anderer Mod erkannt wird, der ebenfalls die Schablone verwendet.", "vivecraft.options.VR_HOTSWITCH.tooltip": "Schnellwechsel wechselt automatisch zu NONVR wenn das Headset abgenommen wird.\nWenn diese Einstellung ausgeschalten ist, befindet sich das Spiel dauerhaft im VR Modus, sobald VR eingeschalten wurde", "vivecraft.options.INGAME_BINDINGS_IN_GUI.tooltip": "Erlaubt es alle Im-Spiel Tasten in Menüs zu verwenden. Dies kann zu nicht gewollten doppel Tastendrücken führen.", "vivecraft.options.MENU_WORLD_FALLBACK.tooltip": "Wenn Menü Welten deaktiviert sind oder noch nicht geladen sind, wird dieser Ersatz stattdessen verwendet", + "vivecraft.options.MIRROR_CROP.tooltip": "Gibt and um wie viel das VR Bild zugeschnitten wird. Der Standardwert von 15%% versteckt die Augenschablone ganz gut. Wenn Sie ohne Augenschablone spielen, können Sie den Wert reduzieren, um ein größeres Sichtfeld im Desktop Spiegel zu bekommen.", "_comment_m10": "Messages", "vivecraft.messages.mode": "Modus:", "vivecraft.messages.novrhotswitchinglegacy": "Veralteten Vivecraft server mod erkannt. Dieser Server unterstützt kein VR Schnellwechsel. Sie können den Modus nur im Hauptmenü wechseln.", "vivecraft.messages.novrhotswitching": "Dieser Server hat VR Schnellwechsel deaktiviert. Sie können den Modus nur im Hauptmenü wechseln.", "vivecraft.messages.vrhotswitchinginfo": "VR Schnellwechsel aktiviert: Setze dein Headset auf, um zu VR zu wechseln", "vivecraft.messages.updateAvailable": "§a[Vivecraft]§r Update verfügbar: %s. Klicke für mehr Details.", + "vivecraft.messages.updateTitle": "Neues Update Verfügbar", "vivecraft.messages.click": "Klicke für mehr Details.", "vivecraft.messages.incompatiblesettings": "Inkompatible Einstellungen", "vivecraft.messages.optifineaa": "Optifines Antialiasing ist nicht compatible mit VR. Um VR zu nutzen, deaktiviere Antialiasing und starte das Spiel neu.", @@ -451,6 +485,8 @@ "vivecraft.messages.3options": "%s > %s > %s", "vivecraft.messages.openSettings": "Klicken um die Einstellungen zu öffnen.", "vivecraft.message.kofi": "Unterstütze uns auf Ko-Fi", + "vivecraft.message.overriddenbyserver": "§6Einstellung überschrieben vom Server.§r\n", + "vivecraft.message.limitedbyserver": "§6Einstellungsbereich vom Server limitiert (%s - %s)§r\n", "vivecraft.gui.update": "§aⓘ§r Update", "vivecraft.gui.vr": "VR: %s", diff --git a/common/src/main/resources/assets/vivecraft/lang/en_us.json b/common/src/main/resources/assets/vivecraft/lang/en_us.json index 935011161..703346fbf 100644 --- a/common/src/main/resources/assets/vivecraft/lang/en_us.json +++ b/common/src/main/resources/assets/vivecraft/lang/en_us.json @@ -40,6 +40,19 @@ "vivecraft.key.keyboardShift": "Shift", "vivecraft.key.climbeyGrab": "Climb Claws", "vivecraft.key.climbeyJump": "Jump Boots", + "_comment_quickcommands": "double spacing is intentional, to get minecraft to sort them right", + "vivecraft.key.quickcommand1": "Quick Command 1", + "vivecraft.key.quickcommand2": "Quick Command 2", + "vivecraft.key.quickcommand3": "Quick Command 3", + "vivecraft.key.quickcommand4": "Quick Command 4", + "vivecraft.key.quickcommand5": "Quick Command 5", + "vivecraft.key.quickcommand6": "Quick Command 6", + "vivecraft.key.quickcommand7": "Quick Command 7", + "vivecraft.key.quickcommand8": "Quick Command 8", + "vivecraft.key.quickcommand9": "Quick Command 9", + "vivecraft.key.quickcommand10": "Quick Command 10", + "vivecraft.key.quickcommand11": "Quick Command 11", + "vivecraft.key.quickcommand12": "Quick Command 12", "_comment1": "Key binding categories", "vivecraft.key.category.gui": "GUI", "vivecraft.key.category.climbey": "Climbey Motion", @@ -101,6 +114,7 @@ "vivecraft.options.CROSSHAIR_SCALES_WITH_DISTANCE": "Crosshair Scaling", "vivecraft.options.RENDER_BLOCK_OUTLINE_MODE": "Show Block Outline", "vivecraft.options.AUTO_OPEN_KEYBOARD": "Always Open Keyboard", + "vivecraft.options.AUTO_CLOSE_KEYBOARD": "Auto Close Keyboard", "vivecraft.options.RADIAL_MODE_HOLD": "Radial Menu Mode", "vivecraft.options.PHYSICAL_KEYBOARD": "Keyboard Type", "vivecraft.options.PHYSICAL_KEYBOARD_SCALE": "Keyboard Size", @@ -139,6 +153,7 @@ "vivecraft.options.REALISTIC_CLIMB": "Roomscale Climbing", "vivecraft.options.REALISTIC_SWIM": "Roomscale Swimming", "vivecraft.options.REALISTIC_ROW": "Roomscale Rowing", + "vivecraft.options.REALISTIC_DISMOUNT": "Roomscale Dismounting", "vivecraft.options.WALK_MULTIPLIER": "Walking Multiplier", "vivecraft.options.FREEMOVE_MODE": "Free Move Type", "vivecraft.options.VEHICLE_ROTATION": "Vehicle Rotation", @@ -189,6 +204,7 @@ "vivecraft.options.CROSSHAIR_SCALES_WITH_DISTANCE.tooltip": "Determines how the crosshair changes with distance.\n ON: The crosshair will grow larger in the distance to remain the same apparent size from your viewpoint.\n OFF: The crosshair will always be the same size in the world and appear to shrink with distance.", "vivecraft.options.RENDER_BLOCK_OUTLINE_MODE.tooltip": "Sets the in-game block outline display mode.\n Always: The block outline is always shown even if the HUD is disabled.\n With HUD: The block outline is only shown when the HUD is enabled.\n Never: The block outline is never shown.", "vivecraft.options.AUTO_OPEN_KEYBOARD.tooltip": "If disabled, the keyboard will only open when you click a text field, or if a text field can't lose focus.\n\nIf enabled, the keyboard will open automatically any time a text field comes into focus. Enabling this will cause it to open in unwanted situations with mods.", + "vivecraft.options.AUTO_CLOSE_KEYBOARD.tooltip": "If enabled, the keyboard will automatically close, when the screen changes.", "vivecraft.options.RADIAL_MODE_HOLD.tooltip": "Behavior of the radial menu when pressing the button.\n Hold: Hold radial menu button, hover over selection and release.\n Press: Press radial menu button, click buttons, press radial menu button again to dismiss.", "vivecraft.options.PHYSICAL_KEYBOARD.tooltip": "Which type of VR keyboard to use for typing.\n Physical: A keyboard which you can type on like a real keyboard.\n Pointer: A keyboard which you can use by pointing either controller's crosshair at and pressing buttons.", "vivecraft.options.PHYSICAL_KEYBOARD_SCALE.tooltip": "How large the physical keyboard should be, relative to its base size.", @@ -221,12 +237,13 @@ "vivecraft.options.RENDER_SCALEFACTOR.tooltip": "The internal rendering scale of the game, relative to the native HMD display. Higher values improve visual quality at the cost of performance.", "vivecraft.options.MONO_FOV.tooltip": "The FOV used for the undistorted mirror mode.", "vivecraft.options.MIRROR_CENTER_SMOOTH.tooltip": "Smooths the HMD position and rotation for the mirror over the given time. Reduces sudden changes and jitter.", - "vivecraft.options.REALISTIC_JUMP.tooltip": "If turned on, once you jump in real life your player will also jump. Also enables Jump Boots.", + "vivecraft.options.REALISTIC_JUMP.tooltip": "If turned on, once you jump in real life your player will also jump. Also enables Jump Boots.\nAuto disables jumping when Jump Boots are equipped, to prevent accidental jumps.", "vivecraft.options.REALISTIC_SNEAK.tooltip": "If turned on, once you duck in real life your player will also sneak.", "vivecraft.options.PHYSICAL_GUI.tooltip": "If turned on, GUIs will be replaced with 3d interactable models.\nIf Backpack tracking is enabled, reaching on your back will bring out your inventory bag.", "vivecraft.options.REALISTIC_CLIMB.tooltip": "If turned on, allow climbing ladders and vines by touching them. Also enables Climb Claws.", "vivecraft.options.REALISTIC_SWIM.tooltip": "If turned on, allow swimming by doing the breaststroke with the controllers.", "vivecraft.options.REALISTIC_ROW.tooltip": "Row, row, row your boat... by flapping your arms like mad.", + "vivecraft.options.REALISTIC_DISMOUNT.tooltip": "Dismounts from entities, when walking away 1 meter.\nCan have issues with large modded entities.", "vivecraft.options.WALK_MULTIPLIER.tooltip": "Multiplies your position in the room by a factor.\nAllows you to walk around more, but may cause motion sickness.", "vivecraft.options.FREEMOVE_MODE.tooltip": "The source for freemove direction.\n\n Controller: Offhand controller pointing direction.\n HMD: Headset look direction.\n Run-In-Place: Yaw is based on how controllers are swinging. Pitch is your Headset.\n Room: Yaw is relative to your VR room forward. Pitch is your Headset. This mode is best only for 180 setups.", "vivecraft.options.VEHICLE_ROTATION.tooltip": "Riding in a vehicle will rotate the world as the vehicle rotates. May be disorienting.", @@ -354,6 +371,9 @@ "vivecraft.gui.alignkatwalk": "Align KAT WALK", "vivecraft.gui.movethirdpersoncam": "Move Third Cam", "vivecraft.gui.social": "Social", + "vivecraft.gui.downloadfrom": "Download from %s", + "vivecraft.gui.dontshowagain": "Don't Show Again", + "vivecraft.gui.openguide": "Open Guide", "_comment9": "Items", "vivecraft.item.jumpboots": "Jump Boots", "vivecraft.item.climbclaws": "Climb Claws", @@ -379,12 +399,14 @@ "vivecraft.messages.teleportenabled": "Restricted movement disabled (teleporting allowed)", "vivecraft.messages.walkupblocks": "Walk up blocks (RCTRL+B): %s", "vivecraft.messages.showaim": "Show aim (RCTRL+RSHIFT): enabled", - "vivecraft.messages.playerinertia": "Player movement inertia (LCTRL+I): %s", + "vivecraft.messages.playerinertia": "Player movement inertia (RCTRL+I): %s", "vivecraft.messages.movementmodeswitch": "Movement mode switched to: %s", "vivecraft.messages.coords": "X: %.2f Y: %.2f Z: %.2f", "vivecraft.messages.angles": "Pitch: %.1f Yaw: %.1f Roll: %.1f", "vivecraft.messages.heightset": "User height set to %d%%", "vivecraft.messages.airtypingwarning": "You are typing without a screen open. If you're trying to use key bindings, enable \"Keyboard Presses Bindings\" in the VR settings.", + "vivecraft.messages.gctitle": "Non-optimal Garbage Collector", + "vivecraft.messages.gcinfo": "Your current garbage collector is %s, which is not optimal for Vivecraft and will likely cause hitching and framerate drops.\n\nYour system appears sufficient to use %s and %s GB or more of heap memory, which is recommended for the smoothest experience. Add %s to your Java arguments to use it.\n\nIf you're unsure how to modify your Java arguments, press \"%s\" below.", "_comment_m": "mixin version exclusive strings", "vivecraft.options.screen.settings": "Vivecraft Settings", @@ -406,6 +428,9 @@ "vivecraft.options.updatetype.release": "Release", "vivecraft.options.menuworldfallback.dirtbox": "Dirtbox", "vivecraft.options.menuworldfallback.panorama": "Panorama", + "vivecraft.options.vrprovider.openvr": "OpenVR/SteamVR", + "vivecraft.options.vrprovider.nullvr": "NullVR", + "vivecraft.options.realisticjump.auto": "Auto", "_comment_m5": "Option names", "vivecraft.options.LOW_HEALTH_INDICATOR": "Health Indicator", "vivecraft.options.SHADER_GUI_RENDER": "Shaders GUI", @@ -419,33 +444,41 @@ "vivecraft.options.SHOW_PLUGIN_MISSING": "Plugin Missing Message", "vivecraft.options.CHAT_MESSAGE_STENCIL": "Stencil Message", "vivecraft.options.VR_HOTSWITCH": "Hotswitching", + "vivecraft.options.VR_ENABLED": "VR Enabled", + "vivecraft.options.VR_REMEMBER_ENABLED": "Remember VR State", + "vivecraft.options.VR_PLUGIN": "VR Plugin", "vivecraft.options.VR_TOGGLE_BUTTON_VISIBLE": "VR Toggle Button Visible", "vivecraft.options.VR_SETTINGS_BUTTON_VISIBLE": "VR Settings Button Visible", "vivecraft.options.VR_SETTINGS_BUTTON_POSITION": "VR Settings Button Position", "vivecraft.options.INGAME_BINDINGS_IN_GUI": "In-Game Bindings In GUI", "vivecraft.options.MENU_WORLD_FALLBACK": "Fallback Method", + "vivecraft.options.MIRROR_CROP": "Mirror Cropping", "_comment_m6": "Option tooltips", "vivecraft.options.LOW_HEALTH_INDICATOR.tooltip": "Pulses the screen red, when at low health, to indicate your current health status", "vivecraft.options.SHADER_GUI_RENDER.tooltip": "Determines how the GUI is rendered with shaders.\n After Shader: renders the GUI without using the shader, best compatibility. (issues with PTGI HRR)\n Translucent: renders the GUI with shader and transparency. (issues with Sildurs Vibrant)\n Opaque: renders the GUI with shader and opaque", "vivecraft.options.DOUBLE_GUI_RESOLUTION.tooltip": "If enabled, GUIs will be rendered at 1440p instead of 720p, greatly increasing sharpness.\nMay be more resource intensive on GPUs with limited memory bandwidth.", "vivecraft.options.GUI_SCALE.tooltip": "The GUI scale to apply when VR is active.", "vivecraft.options.HUD_MAX_GUI_SCALE.tooltip": "If enabled, the HUD will use max GUI Scale, regardless of what is set as 'VR GUI Scale'.", - "vivecraft.options.VR_MODE.tooltip": "change between VR/NONVR", + "vivecraft.options.VR_ENABLED.tooltip": "Change between VR/NONVR", + "vivecraft.options.VR_REMEMBER_ENABLED.tooltip": "Activates VR on startup, if it was enabled the last time.", + "vivecraft.options.VR_PLUGIN.tooltip": "Which VR plugin to use:\n OpenVR: uses SteamVR as a backend.\n NullVR: Uses no VR Api and runs the game in VR mode without a headset.", "vivecraft.options.FREEMOVE_FLY_MODE.tooltip": "The source for freemove direction when flying.\n\n Auto: uses the same direction as regular Freemove.\n Controller: Offhand controller pointing direction.\n HMD: Headset look direction.", "vivecraft.options.SHOW_UPDATES.tooltip": "How often an update message should show up in chat.\n Always: Shows the update message each time a world is loaded.\n Once: Shows the update message only on the first world load after a new update is out.", "vivecraft.options.UPDATE_TYPE.tooltip": "Specifies what updates should trigger a notification.", - "vivecraft.options.SHOW_PLUGIN.tooltip": "When the server mod detected message should show up in chat.\n Always: Shows the message on single/multiplayer.\n Server Only: Only shows the message in multiplayer.\n Never: Never shows the message.", - "vivecraft.options.SHOW_PLUGIN_MISSING.tooltip": "How often the server mod not detected message should show up in chat.\n Always: Shows the message on server join and dimension/server change.\n Once: Only shows the message when joining a server.", + "vivecraft.options.SHOW_PLUGIN.tooltip": "When the \"server mod detected\" message should show up in chat.\n Always: Shows the message on single/multiplayer.\n Server Only: Only shows the message in multiplayer.\n Never: Never shows the message.", + "vivecraft.options.SHOW_PLUGIN_MISSING.tooltip": "How often the \"server mod not detected\" message should show up in chat.\n Always: Shows the message on server join and dimension/server change.\n Once: Only shows the message when joining a server.", "vivecraft.options.CHAT_MESSAGE_STENCIL.tooltip": "Prints a message in chat, when another mod is detected, that also uses the stencil buffer.", "vivecraft.options.VR_HOTSWITCH.tooltip": "Hotswitching switches to NONVR when the headset is taken off.\nIf this setting is off, the game will always be in VR mode, when VR is enabled", "vivecraft.options.INGAME_BINDINGS_IN_GUI.tooltip": "Allows for all In-Game bindings to be used in menus, this can cause unwanted double presses.", "vivecraft.options.MENU_WORLD_FALLBACK.tooltip": "If Menuworlds are disabled or not loaded yet, this fallback will be shown instead.", + "vivecraft.options.MIRROR_CROP.tooltip": "Specifies how much of the VR image gets cropped. The default 15%% hides the stencil pretty good. If you play without stencil, you can reduce this, to get a bigger FOV for the mirror.", "_comment_m10": "Messages", "vivecraft.messages.mode": "Mode:", "vivecraft.messages.novrhotswitchinglegacy": "Legacy Vivecraft server mod detected. This Server does not support VR hot switching, you can only change it in the main menu.", "vivecraft.messages.novrhotswitching": "This Server has VR hot switching disabled, you can only change it in the main menu.", - "vivecraft.messages.vrhotswitchinginfo": "VR Hotswitching enabled: Put on your headset to swtich to VR", + "vivecraft.messages.vrhotswitchinginfo": "VR Hotswitching enabled: Put on your headset to switch to VR", "vivecraft.messages.updateAvailable": "§a[Vivecraft]§r Update available: %s. click for more details.", + "vivecraft.messages.updateTitle": "New Update Available", "vivecraft.messages.click": "Click for more details.", "vivecraft.messages.incompatiblesettings": "Incompatible Settings", "vivecraft.messages.optifineaa": "Optifine antialiasing is not compatible with VR. To use VR disable antialiasing and restart the game.", @@ -454,6 +487,8 @@ "vivecraft.messages.3options": "%s > %s > %s", "vivecraft.messages.openSettings": "Click to open settings", "vivecraft.message.kofi": "Support us on Ko-Fi", + "vivecraft.message.overriddenbyserver": "§6Setting overridden by server.§r\n", + "vivecraft.message.limitedbyserver": "§6Setting range limited by server (%s - %s)§r\n", "vivecraft.gui.update": "§aⓘ§r Update", "vivecraft.gui.vr": "VR: %s", diff --git a/common/src/main/resources/assets/vivecraft/models/item/climb_claws.json b/common/src/main/resources/assets/vivecraft/models/item/climb_claws.json new file mode 100644 index 000000000..fb158e1d1 --- /dev/null +++ b/common/src/main/resources/assets/vivecraft/models/item/climb_claws.json @@ -0,0 +1,153 @@ +{ + "textures": { + "claws": "vivecraft:item/climb_claws" + }, + "elements": [ + { + "from": [5.5, 9.5, 12], + "to": [10.5, 10.5, 13], + "faces": { + "up": { + "uv": [5, 12, 10, 13], + "texture": "#claws" + }, + "down": { + "uv": [5, 14, 10, 15], + "texture": "#claws" + }, + "south": { + "uv": [5, 13, 10, 14], + "texture": "#claws" + }, + "west": { + "uv": [4, 12, 5, 13], + "texture": "#claws", + "rotation": 270 + }, + "east": { + "uv": [10, 12, 11, 13], + "texture": "#claws", + "rotation": 90 + } + } + }, + { + "from": [5.5, 8.5, 9], + "to": [10.5, 10.5, 12], + "faces": { + "up": { + "uv": [5, 9, 10, 12], + "texture": "#claws" + }, + "down": { + "uv": [5, 4, 10, 7], + "texture": "#claws" + }, + "north": { + "uv": [10, 9, 5, 7], + "texture": "#claws" + }, + "south": { + "uv": [5, 14, 10, 16], + "texture": "#claws" + }, + "west": { + "uv": [3, 9, 5, 12], + "texture": "#claws", + "rotation": 270 + }, + "east": { + "uv": [10, 9, 12, 12], + "texture": "#claws", + "rotation": 90 + } + } + }, + { + "from": [6.5, 9.5, 5], + "to": [7.5, 10.5, 9], + "faces": { + "up": { + "uv": [1, 2, 2, 6], + "texture": "#claws" + }, + "down": { + "uv": [4, 6, 3, 2], + "texture": "#claws" + }, + "north": { + "uv": [2, 2, 1, 1], + "texture": "#claws" + }, + "west": { + "uv": [0, 2, 1, 6], + "texture": "#claws", + "rotation": 270 + }, + "east": { + "uv": [2, 2, 3, 6], + "texture": "#claws", + "rotation": 90 + } + } + }, + { + "from": [8.5, 9.5, 5], + "to": [9.5, 10.5, 9], + "faces": { + "up": { + "uv": [13, 2, 14, 6], + "texture": "#claws" + }, + "down": { + "uv": [16, 6, 15, 2], + "texture": "#claws" + }, + "north": { + "uv": [14, 2, 13, 1], + "texture": "#claws" + }, + "west": { + "uv": [12, 2, 13, 6], + "texture": "#claws", + "rotation": 270 + }, + "east": { + "uv": [14, 2, 15, 6], + "texture": "#claws", + "rotation": 90 + } + } + } + ], + "gui_light": "front", + "display": { + "firstperson_righthand": { + "rotation": [30, -15, -15], + "scale": [0.68, 0.68, 0.68], + "translation": [-2, 4, 0] + }, + "fixed": { + "rotation": [270, 180, 0], + "translation": [0, 0, 2] + }, + "ground": { + "rotation": [90, 0, 0], + "scale": [0.5, 0.5, 0.5], + "translation": [0, 3, 0] + }, + "gui": { + "rotation": [90, 0, 0], + "translation": [-0.5, 1, 0] + }, + "head": { + "scale": [3, 3, 3], + "translation": [0, 0, -8] + }, + "thirdperson_righthand": { + "rotation": [0, 0, 270], + "scale": [0.94, 0.94, 0.94], + "translation": [0.09, -2, 0] + } + } +} diff --git a/common/src/main/resources/assets/vivecraft/textures/item/climb_claws.png b/common/src/main/resources/assets/vivecraft/textures/item/climb_claws.png new file mode 100644 index 000000000..db0a48061 Binary files /dev/null and b/common/src/main/resources/assets/vivecraft/textures/item/climb_claws.png differ diff --git a/common/src/main/resources/data/vivecraft/recipes/climbclaws.json b/common/src/main/resources/data/vivecraft/recipes/climbclaws.json index da1b82050..d9508594e 100644 --- a/common/src/main/resources/data/vivecraft/recipes/climbclaws.json +++ b/common/src/main/resources/data/vivecraft/recipes/climbclaws.json @@ -16,6 +16,7 @@ "item": "vivecraft:climbclaws", "vanillaitem": "minecraft:shears", "name": "vivecraft.item.climbclaws", + "fallbackname": "Climb Claws", "hideflags": 4, "unbreakable": true } diff --git a/common/src/main/resources/data/vivecraft/recipes/jumpboots.json b/common/src/main/resources/data/vivecraft/recipes/jumpboots.json index 969322352..22ab76536 100644 --- a/common/src/main/resources/data/vivecraft/recipes/jumpboots.json +++ b/common/src/main/resources/data/vivecraft/recipes/jumpboots.json @@ -16,7 +16,9 @@ "item": "vivecraft:jumpboots", "vanillaitem": "minecraft:leather_boots", "name": "vivecraft.item.jumpboots", + "fallbackname": "Jump Boots", "hideflags": 4, - "unbreakable": true + "unbreakable": true, + "color": 9233775 } } diff --git a/common/src/main/resources/data/vivecraft/tags/items/bow_exclusion.json b/common/src/main/resources/data/vivecraft/tags/items/bow_exclusion.json new file mode 100644 index 000000000..aa13c1978 --- /dev/null +++ b/common/src/main/resources/data/vivecraft/tags/items/bow_exclusion.json @@ -0,0 +1,11 @@ +{ + "replace": false, + "values": [ + { + "id": "#pokecube:pokecubes", + "required": false + }, + + "#vivecraft:moditems/irons_spellbooks" + ] +} diff --git a/common/src/main/resources/data/vivecraft/tags/items/moditems/irons_spellbooks.json b/common/src/main/resources/data/vivecraft/tags/items/moditems/irons_spellbooks.json new file mode 100644 index 000000000..f69a85bbf --- /dev/null +++ b/common/src/main/resources/data/vivecraft/tags/items/moditems/irons_spellbooks.json @@ -0,0 +1,69 @@ +{ + "replace": false, + "values": [ + { + "id": "irons_spellbooks:scroll", + "required": false + }, + { + "id": "irons_spellbooks:wimpy_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:legendary_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:netherite_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:diamond_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:gold_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:iron_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:copper_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:rotten_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:blaze_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:dragonskin_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:druidic_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:villager_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:blood_staff", + "required": false + }, + { + "id": "irons_spellbooks:evoker_spell_book", + "required": false + }, + { + "id": "irons_spellbooks:spellbreaker", + "required": false + } + ] +} diff --git a/common/src/main/resources/data/vivecraft/tags/items/moditems/mvw_weapons.json b/common/src/main/resources/data/vivecraft/tags/items/moditems/mvw_weapons.json new file mode 100644 index 000000000..a48b1c16c --- /dev/null +++ b/common/src/main/resources/data/vivecraft/tags/items/moditems/mvw_weapons.json @@ -0,0 +1,346 @@ +{ + "replace": false, + "values": [ + { + "id": "mvw:wooden_double_axe", + "required": false + }, + { + "id": "mvw:wooden_knife", + "required": false + }, + { + "id": "mvw:wooden_katana", + "required": false + }, + { + "id": "mvw:wooden_hammer", + "required": false + }, + { + "id": "mvw:wooden_scythe", + "required": false + }, + { + "id": "mvw:wooden_spade", + "required": false + }, + { + "id": "mvw:wooden_rapier", + "required": false + }, + { + "id": "mvw:wooden_lance", + "required": false + }, + { + "id": "mvw:wooden_halberd", + "required": false + }, + { + "id": "mvw:wooden_long_sword", + "required": false + }, + { + "id": "mvw:wooden_mace", + "required": false + }, + { + "id": "mvw:wooden_pole", + "required": false + }, + { + "id": "mvw:wooden_warhammer", + "required": false + }, + { + "id": "mvw:wooden_spear", + "required": false + }, + + { + "id": "mvw:stone_double_axe", + "required": false + }, + { + "id": "mvw:stone_knife", + "required": false + }, + { + "id": "mvw:stone_katana", + "required": false + }, + { + "id": "mvw:stone_hammer", + "required": false + }, + { + "id": "mvw:stone_scythe", + "required": false + }, + { + "id": "mvw:stone_spade", + "required": false + }, + { + "id": "mvw:stone_rapier", + "required": false + }, + { + "id": "mvw:stone_lance", + "required": false + }, + { + "id": "mvw:stone_halberd", + "required": false + }, + { + "id": "mvw:stone_long_sword", + "required": false + }, + { + "id": "mvw:stone_mace", + "required": false + }, + { + "id": "mvw:stone_pole", + "required": false + }, + { + "id": "mvw:stone_warhammer", + "required": false + }, + { + "id": "mvw:stone_spear", + "required": false + }, + + { + "id": "mvw:iron_double_axe", + "required": false + }, + { + "id": "mvw:iron_knife", + "required": false + }, + { + "id": "mvw:iron_katana", + "required": false + }, + { + "id": "mvw:iron_hammer", + "required": false + }, + { + "id": "mvw:iron_scythe", + "required": false + }, + { + "id": "mvw:iron_spade", + "required": false + }, + { + "id": "mvw:iron_rapier", + "required": false + }, + { + "id": "mvw:iron_lance", + "required": false + }, + { + "id": "mvw:iron_halberd", + "required": false + }, + { + "id": "mvw:iron_long_sword", + "required": false + }, + { + "id": "mvw:iron_mace", + "required": false + }, + { + "id": "mvw:iron_pole", + "required": false + }, + { + "id": "mvw:iron_warhammer", + "required": false + }, + { + "id": "mvw:iron_spear", + "required": false + }, + + { + "id": "mvw:gold_double_axe", + "required": false + }, + { + "id": "mvw:gold_knife", + "required": false + }, + { + "id": "mvw:gold_katana", + "required": false + }, + { + "id": "mvw:gold_hammer", + "required": false + }, + { + "id": "mvw:gold_scythe", + "required": false + }, + { + "id": "mvw:gold_spade", + "required": false + }, + { + "id": "mvw:gold_rapier", + "required": false + }, + { + "id": "mvw:gold_lance", + "required": false + }, + { + "id": "mvw:gold_halberd", + "required": false + }, + { + "id": "mvw:gold_long_sword", + "required": false + }, + { + "id": "mvw:gold_mace", + "required": false + }, + { + "id": "mvw:gold_pole", + "required": false + }, + { + "id": "mvw:gold_warhammer", + "required": false + }, + { + "id": "mvw:gold_spear", + "required": false + }, + + { + "id": "mvw:diamond_double_axe", + "required": false + }, + { + "id": "mvw:diamond_knife", + "required": false + }, + { + "id": "mvw:diamond_katana", + "required": false + }, + { + "id": "mvw:diamond_hammer", + "required": false + }, + { + "id": "mvw:diamond_scythe", + "required": false + }, + { + "id": "mvw:diamond_spade", + "required": false + }, + { + "id": "mvw:diamond_rapier", + "required": false + }, + { + "id": "mvw:diamond_lance", + "required": false + }, + { + "id": "mvw:diamond_halberd", + "required": false + }, + { + "id": "mvw:diamond_long_sword", + "required": false + }, + { + "id": "mvw:diamond_mace", + "required": false + }, + { + "id": "mvw:diamond_pole", + "required": false + }, + { + "id": "mvw:diamond_warhammer", + "required": false + }, + { + "id": "mvw:diamond_spear", + "required": false + }, + + { + "id": "mvw:netherite_double_axe", + "required": false + }, + { + "id": "mvw:netherite_knife", + "required": false + }, + { + "id": "mvw:netherite_katana", + "required": false + }, + { + "id": "mvw:netherite_hammer", + "required": false + }, + { + "id": "mvw:netherite_scythe", + "required": false + }, + { + "id": "mvw:netherite_spade", + "required": false + }, + { + "id": "mvw:netherite_rapier", + "required": false + }, + { + "id": "mvw:netherite_lance", + "required": false + }, + { + "id": "mvw:netherite_halberd", + "required": false + }, + { + "id": "mvw:netherite_long_sword", + "required": false + }, + { + "id": "mvw:netherite_mace", + "required": false + }, + { + "id": "mvw:netherite_pole", + "required": false + }, + { + "id": "mvw:netherite_warhammer", + "required": false + }, + { + "id": "mvw:netherite_spear", + "required": false + } + ] +} diff --git a/common/src/main/resources/data/vivecraft/tags/items/swords.json b/common/src/main/resources/data/vivecraft/tags/items/swords.json index 76a5627a6..eeb2de91c 100644 --- a/common/src/main/resources/data/vivecraft/tags/items/swords.json +++ b/common/src/main/resources/data/vivecraft/tags/items/swords.json @@ -26,6 +26,8 @@ { "id": "tconstruct:cleaver", "required": false - } + }, + + "#vivecraft:moditems/mvw_weapons" ] } diff --git a/common/src/main/resources/vivecraft.accesswidener b/common/src/main/resources/vivecraft.accesswidener index 4f28d6cc2..9ea8f6656 100644 --- a/common/src/main/resources/vivecraft.accesswidener +++ b/common/src/main/resources/vivecraft.accesswidener @@ -12,7 +12,6 @@ extendable method net/minecraft/client/renderer/entity/player/PlayerRenderer set # modded layer supports accessible method net/minecraft/client/renderer/entity/LivingEntityRenderer addLayer (Lnet/minecraft/client/renderer/entity/layers/RenderLayer;)Z -extendable method net/minecraft/client/renderer/entity/LivingEntityRenderer addLayer (Lnet/minecraft/client/renderer/entity/layers/RenderLayer;)Z mutable field net/minecraft/client/renderer/entity/layers/RenderLayer renderer Lnet/minecraft/client/renderer/entity/RenderLayerParent; accessible field net/minecraft/client/renderer/entity/layers/RenderLayer renderer Lnet/minecraft/client/renderer/entity/RenderLayerParent; @@ -28,7 +27,7 @@ accessible field net/minecraft/network/Connection channel Lio/netty/channel/Chan # for quicktorch accessible method net/minecraft/client/Minecraft startUseItem ()V -# to switch rendrtargetrs for VR passes +# to switch rendertargets for VR passes mutable field net/minecraft/client/Minecraft mainRenderTarget Lcom/mojang/blaze3d/pipeline/RenderTarget; accessible field net/minecraft/client/Minecraft mainRenderTarget Lcom/mojang/blaze3d/pipeline/RenderTarget; @@ -101,4 +100,8 @@ accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J accessible class net/minecraft/world/level/biome/Biome$ClimateSettings accessible field net/minecraft/world/level/biome/AmbientParticleSettings probability F extendable class net/minecraft/world/level/material/FluidState -accessible field net/minecraft/world/level/block/state/StateHolder propertiesCodec Lcom/mojang/serialization/MapCodec; \ No newline at end of file +accessible field net/minecraft/world/level/block/state/StateHolder propertiesCodec Lcom/mojang/serialization/MapCodec; + +# to init VR +accessible class net/minecraft/client/ResourceLoadStateTracker$ReloadState +accessible field net/minecraft/client/ResourceLoadStateTracker$ReloadState reloadReason Lnet/minecraft/client/ResourceLoadStateTracker$ReloadReason; diff --git a/common/src/main/resources/vivecraft.bedrockify.mixins.json b/common/src/main/resources/vivecraft.bedrockify.mixins.json new file mode 100644 index 000000000..f051059c3 --- /dev/null +++ b/common/src/main/resources/vivecraft.bedrockify.mixins.json @@ -0,0 +1,10 @@ +{ + "required": false, + "package": "org.vivecraft.mod_compat_vr.bedrockify.mixin", + "plugin": "org.vivecraft.MixinConfig", + "compatibilityLevel": "JAVA_17", + "client": [ + "BedrockBlockShadingMixin" + ], + "minVersion": "0.8.4" +} diff --git a/common/src/main/resources/vivecraft.iris.mixins.json b/common/src/main/resources/vivecraft.iris.mixins.json index 5a8d4f0e1..2673ae2d4 100644 --- a/common/src/main/resources/vivecraft.iris.mixins.json +++ b/common/src/main/resources/vivecraft.iris.mixins.json @@ -6,17 +6,20 @@ "client": [ "IrisBeginFrameHack", "IrisBlockRenderingSettingsMixin", - "IrisChunkProgramOverridesMixin", - "IrisChunkProgramOverridesMixinSodium_0_4_11", - "IrisChunkProgramOverridesMixinSodium_0_4_8", - "IrisChunkProgramOverridesMixinSodium_0_4_9", "IrisHandRendererVRMixin", - "IrisNewWorldRenderingPipelineVRMixin", - "IrisPipelineManagerVRMixin", "IrisProgramUniformsMixin", "IrisRenderSystemVRMixin", "IrisShadowMatricesMixin", - "IrisShadowRendererMixin" + "IrisShadowRendererMixin", + "coderbot.IrisChunkProgramOverridesMixin", + "coderbot.IrisChunkProgramOverridesMixinSodium_0_4_11", + "coderbot.IrisChunkProgramOverridesMixinSodium_0_4_9", + "coderbot.IrisNewWorldRenderingPipelineVRMixin", + "coderbot.IrisPipelineManagerVRMixin", + "irisshaders.IrisChunkProgramOverridesMixin", + "irisshaders.IrisChunkProgramOverridesMixinSodium_0_6", + "irisshaders.IrisNewWorldRenderingPipelineVRMixin", + "irisshaders.IrisPipelineManagerVRMixin" ], "minVersion": "0.8.4", "mixins": [ diff --git a/common/src/main/resources/vivecraft.mixins.json b/common/src/main/resources/vivecraft.mixins.json index 9d6c37b32..94eb00976 100644 --- a/common/src/main/resources/vivecraft.mixins.json +++ b/common/src/main/resources/vivecraft.mixins.json @@ -12,13 +12,15 @@ "client.gui.screens.ScreenMixin", "client.gui.screens.TitleScreenMixin", "client.main.MainMixin", + "client.particle.SparkParticleMixin", "client.player.AbstractClientPlayerMixin", "client.renderer.ItemBlockRenderTypesMixin", "client.renderer.RenderStateShardAccessor", "client.renderer.block.LiquidBlockRendererMixin", "client.renderer.entity.EntityRenderDispatcherMixin", "client.renderer.entity.ItemRendererVRMixin", - "client.renderer.entity.PlayerRendererMixin", + "client.renderer.entity.LivingEntityRendererMixin", + "client.renderer.entity.layers.ItemInHandLayerMixin", "client.renderer.entity.layers.RenderLayerMixin", "client_vr.ClientBrandRetrieverVRMixin", "client_vr.KeyboardHandlerVRMixin", @@ -44,6 +46,7 @@ "client_vr.gui.screens.inventory.BookEditScreenVRMixin", "client_vr.gui.screens.inventory.CreativeModeInventoryScreenVRMixin", "client_vr.gui.screens.inventory.SignEditScreenVRMixin", + "client_vr.lwjgl.OpenVRMixin", "client_vr.multiplayer.ClientPacketListenerVRMixin", "client_vr.multiplayer.MultiPlayerGameModeVRMixin", "client_vr.particle.ItemPickupParticleVRMixin", diff --git a/common/src/main/resources/vivecraft.sodium.mixins.json b/common/src/main/resources/vivecraft.sodium.mixins.json index 5a1885ad2..98ccee3f1 100644 --- a/common/src/main/resources/vivecraft.sodium.mixins.json +++ b/common/src/main/resources/vivecraft.sodium.mixins.json @@ -4,7 +4,9 @@ "plugin": "org.vivecraft.MixinConfig", "compatibilityLevel": "JAVA_17", "client": [ - "RenderSectionManagerVRMixin", + "caffeinemc.EntityRendererMixin", + "jellysquid.EntityRendererMixin", + "ModelCuboidMixin", "SodiumLeavesBlockMixin", "SodiumWorldRendererVRMixin" ], diff --git a/fabric/build.gradle b/fabric/build.gradle index 915179175..01ae95aa9 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -26,14 +26,14 @@ dependencies { common(project(path: ":common", configuration: "namedElements")) { transitive false } shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false } - modApi("dev.architectury:architectury-fabric:${rootProject.architectury_version}") + modApi("dev.architectury:architectury-fabric:${rootProject.architectury_version}") { exclude group: "net.fabricmc" exclude group: "net.fabricmc.fabric-api" } // for sodium compat modRuntimeOnly "maven.modrinth:sodium:mc1.19.2-0.4.4" modRuntimeOnly 'org.joml:joml:1.10.4' //temp sodium // for iris compat - modRuntimeOnly "maven.modrinth:iris:1.6.5+1.19.2" + modRuntimeOnly "maven.modrinth:iris:1.6.11+1.19.4" modRuntimeOnly 'org.anarres:jcpp:1.4.14' //temp iris modRuntimeOnly 'io.github.douira:glsl-transformer:2.0.0-pre13' //temp iris @@ -42,33 +42,23 @@ dependencies { //modRuntimeOnly 'io.github.douira:glsl-transformer:1.0.1' //temp iris // for REI compat - modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:9.1.619" + modRuntimeOnly("me.shedaniel:RoughlyEnoughItems-fabric:11.0.683") { exclude group: "net.fabricmc" exclude group: "net.fabricmc.fabric-api" exclude group: "dev.architectury" } // for Pehkui compat - modRuntimeOnly("com.github.Virtuoel:Pehkui:3.7.7", { exclude group: "net.fabricmc.fabric-api" }) + modCompileOnly("com.github.Virtuoel:Pehkui:3.7.12") { exclude group: "net.fabricmc" exclude group: "net.fabricmc.fabric-api" } // other mods // modRuntimeOnly("com.simibubi.create:create-fabric-1.19.2:0.5.0.i-969+1.19.2") - modCompileOnly "maven.modrinth:lithium:mc1.19.2-0.11.1" - modCompileOnly "maven.modrinth:indium:1.0.9+mc1.19.2" + // modCompileOnly "maven.modrinth:lithium:mc1.19.4-0.11.1" + // modCompileOnly "maven.modrinth:indium:1.0.19+mc1.19.4" //mod menu - modApi("com.terraformersmc:modmenu:4.1.2") + modApi("com.terraformersmc:modmenu:6.3.1") { exclude group: "net.fabricmc" exclude group: "net.fabricmc.fabric-api" } // for immersive portals compat - modCompileOnly('com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:v2.3.1-1.19') { - exclude(group: "net.fabricmc.fabric-api") - transitive(false) - } - modCompileOnly('com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:v2.3.1-1.19') { - exclude(group: "net.fabricmc.fabric-api") - transitive(false) - } - modCompileOnly('com.github.iPortalTeam.ImmersivePortalsMod:build:v2.3.1-1.19') { - exclude(group: "net.fabricmc.fabric-api") - transitive(false) - } - modRuntimeOnly("com.github.llamalad7.mixinextras:mixinextras-fabric:0.2.0-beta.9") + modCompileOnly('com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:v2.7.5-mc1.19.4') { transitive false } + modCompileOnly('com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:v2.7.5-mc1.19.4') { transitive false } + modCompileOnly('com.github.iPortalTeam.ImmersivePortalsMod:build:v2.7.5-mc1.19.4') { transitive false } // needed for resource loading include(modImplementation(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version))) diff --git a/fabric/src/main/java/org/vivecraft/client/fabric/XplatImpl.java b/fabric/src/main/java/org/vivecraft/client/fabric/XplatImpl.java index e8e173d52..818bea3b9 100644 --- a/fabric/src/main/java/org/vivecraft/client/fabric/XplatImpl.java +++ b/fabric/src/main/java/org/vivecraft/client/fabric/XplatImpl.java @@ -9,6 +9,8 @@ import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.core.BlockPos; import net.minecraft.tags.FluidTags; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeSpecialEffects; @@ -94,4 +96,8 @@ public static Biome.ClimateSettings getBiomeClimateSettings(Biome biome) { public static BiomeSpecialEffects getBiomeEffects(Biome biome) { return biome.getSpecialEffects(); } + + public static double getItemEntityReach(double baseRange, ItemStack itemStack, EquipmentSlot slot) { + return baseRange; + } } diff --git a/fabric/src/main/java/org/vivecraft/fabric/mixin/client/resources/model/FabricModelBakeryMixin.java b/fabric/src/main/java/org/vivecraft/fabric/mixin/client/resources/model/FabricModelBakeryMixin.java index ec5710684..584f1b11e 100644 --- a/fabric/src/main/java/org/vivecraft/fabric/mixin/client/resources/model/FabricModelBakeryMixin.java +++ b/fabric/src/main/java/org/vivecraft/fabric/mixin/client/resources/model/FabricModelBakeryMixin.java @@ -12,6 +12,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.gameplay.trackers.CameraTracker; +import org.vivecraft.client_vr.gameplay.trackers.ClimbTracker; import org.vivecraft.client_vr.gameplay.trackers.TelescopeTracker; @Mixin(ModelBakery.class) @@ -22,6 +23,7 @@ public abstract class FabricModelBakeryMixin { @Inject(method = "", at = @At(value = "CONSTANT", args = "stringValue=textures")) private void loadModels(ResourceManager resourceManager, BlockColors blockColors, ProfilerFiller profilerFiller, int i, CallbackInfo ci) { this.loadTopLevel(TelescopeTracker.scopeModel); + this.loadTopLevel(ClimbTracker.clawsModel); this.loadTopLevel(ClientDataHolderVR.thirdPersonCameraModel); this.loadTopLevel(ClientDataHolderVR.thirdPersonCameraDisplayModel); this.loadTopLevel(CameraTracker.cameraModel); diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 225dbb616..f14cffda5 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -32,6 +32,7 @@ "mixins": [ "vivecraft.mixins.json", "vivecraft.blur.mixins.json", + "vivecraft.bedrockify.mixins.json", "vivecraft.dynamicfps.mixins.json", "vivecraft.sodium.mixins.json", "vivecraft.fabric.sodium.mixins.json", @@ -48,6 +49,9 @@ "minecraft": "1.19.2", "java": ">=17" }, + "breaks": { + "sodium": ["0.4.11+build.25", "0.4.11+build.26"] + }, "suggests": { "another-mod": "*" }, diff --git a/forge/build.gradle b/forge/build.gradle index 214c648a9..3977e51ae 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -16,6 +16,7 @@ loom { mixinConfig "vivecraft.mixins.json" mixinConfig "vivecraft.alexmobs.mixins.json" mixinConfig "vivecraft.blur.mixins.json" + mixinConfig "vivecraft.bedrockify.mixins.json" mixinConfig "vivecraft.cataclysm.mixins.json" mixinConfig "vivecraft.dynamicfps.mixins.json" mixinConfig "vivecraft.sodium.mixins.json" @@ -51,8 +52,8 @@ dependencies { common(project(path: ":common", configuration: "namedElements")) { transitive false } shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false } - modCompileOnly("maven.modrinth:rubidium:0.6.2b") - modCompileOnly("maven.modrinth:oculus:1.19.2-1.6.4") + // modCompileOnly("maven.modrinth:rubidium:0.6.4") + // modCompileOnly("maven.modrinth:oculus:1.19.4-1.5.2") forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.1") forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.1:natives-linux") diff --git a/forge/src/main/java/org/vivecraft/client/forge/XplatImpl.java b/forge/src/main/java/org/vivecraft/client/forge/XplatImpl.java index f50c8b5ca..6ae336f70 100644 --- a/forge/src/main/java/org/vivecraft/client/forge/XplatImpl.java +++ b/forge/src/main/java/org/vivecraft/client/forge/XplatImpl.java @@ -3,12 +3,16 @@ import com.mojang.blaze3d.pipeline.RenderTarget; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeSpecialEffects; import net.minecraft.world.level.material.FluidState; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.ForgeHooksClient; +import net.minecraftforge.common.ForgeMod; import net.minecraftforge.fml.loading.FMLEnvironment; import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLPaths; @@ -77,4 +81,25 @@ public static Biome.ClimateSettings getBiomeClimateSettings(Biome biome) { public static BiomeSpecialEffects getBiomeEffects(Biome biome) { return biome.getModifiedSpecialEffects(); } + + public static double getItemEntityReach(double baseRange, ItemStack itemStack, EquipmentSlot slot) { + var attributes = itemStack.getAttributeModifiers(slot).get(ForgeMod.ENTITY_REACH.get()); + for (var a : attributes) { + if (a.getOperation() == AttributeModifier.Operation.ADDITION) { + baseRange += a.getAmount(); + } + } + double totalRange = baseRange; + for (var a : attributes) { + if (a.getOperation() == AttributeModifier.Operation.MULTIPLY_BASE) { + totalRange += baseRange * a.getAmount(); + } + } + for (var a : attributes) { + if (a.getOperation() == AttributeModifier.Operation.MULTIPLY_TOTAL) { + totalRange *= 1.0 + a.getAmount(); + } + } + return totalRange; + } } diff --git a/forge/src/main/java/org/vivecraft/forge/event/ClientEvents.java b/forge/src/main/java/org/vivecraft/forge/event/ClientEvents.java index 0f25a5695..765fdfcf5 100644 --- a/forge/src/main/java/org/vivecraft/forge/event/ClientEvents.java +++ b/forge/src/main/java/org/vivecraft/forge/event/ClientEvents.java @@ -10,6 +10,7 @@ import org.vivecraft.client.gui.settings.VivecraftMainSettings; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.gameplay.trackers.CameraTracker; +import org.vivecraft.client_vr.gameplay.trackers.ClimbTracker; import org.vivecraft.client_vr.gameplay.trackers.TelescopeTracker; import org.vivecraft.forge.Vivecraft; @@ -18,6 +19,7 @@ public class ClientEvents { @SubscribeEvent public static void registerModels(ModelEvent.RegisterAdditional event) { event.register(TelescopeTracker.scopeModel); + event.register(ClimbTracker.clawsModel); event.register(ClientDataHolderVR.thirdPersonCameraModel); event.register(ClientDataHolderVR.thirdPersonCameraDisplayModel); event.register(CameraTracker.cameraModel); diff --git a/gradle.properties b/gradle.properties index 78d914e21..73af97777 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,15 +4,15 @@ minecraft_version=1.19.2 enabled_platforms=fabric,forge archives_base_name=vivecraft -mod_version=1.1.5 +mod_version=1.1.7 maven_group=org.vivecraft -architectury_version=6.5.85 +architectury_version=8.2.91 -fabric_loader_version=0.14.21 -fabric_api_version=0.76.0+1.19.2 +fabric_loader_version=0.15.7 +fabric_api_version=0.87.2+1.19.4 -forge_version=1.19.2-43.2.14 +forge_version=1.19.4-45.2.8 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 59bc51a20..db9a6b825 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-8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index 167edc2b4..1049520c2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,6 +8,7 @@ pluginManagement { } include("common") +include("stubs") include("fabric") include("forge") diff --git a/stubs/build.gradle b/stubs/build.gradle new file mode 100644 index 000000000..91355f0bd --- /dev/null +++ b/stubs/build.gradle @@ -0,0 +1,10 @@ +plugins { + id 'java' +} + +group = 'org.vivecraft' +version = '1.0' + +repositories { + mavenCentral() +} diff --git a/stubs/src/main/java/me/jellysquid/mods/sodium/client/gl/shader/GlProgram.java b/stubs/src/main/java/me/jellysquid/mods/sodium/client/gl/shader/GlProgram.java new file mode 100644 index 000000000..64ace808b --- /dev/null +++ b/stubs/src/main/java/me/jellysquid/mods/sodium/client/gl/shader/GlProgram.java @@ -0,0 +1,5 @@ +package me.jellysquid.mods.sodium.client.gl.shader; + +public class GlProgram { + public void delete(){} +} diff --git a/stubs/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType.java b/stubs/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType.java new file mode 100644 index 000000000..8f5c20d7c --- /dev/null +++ b/stubs/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType.java @@ -0,0 +1,4 @@ +package me.jellysquid.mods.sodium.client.render.chunk.vertex.format; + +public interface ChunkVertexType { +} diff --git a/stubs/src/main/java/me/jellysquid/mods/sodium/client/render/immediate/model/ModelCuboid.java b/stubs/src/main/java/me/jellysquid/mods/sodium/client/render/immediate/model/ModelCuboid.java new file mode 100644 index 000000000..71e0a6d49 --- /dev/null +++ b/stubs/src/main/java/me/jellysquid/mods/sodium/client/render/immediate/model/ModelCuboid.java @@ -0,0 +1,4 @@ +package me.jellysquid.mods.sodium.client.render.immediate.model; + +public interface ModelCuboid { +} diff --git a/stubs/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/type/ChunkVertexType.java b/stubs/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/type/ChunkVertexType.java new file mode 100644 index 000000000..edd8034ee --- /dev/null +++ b/stubs/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/type/ChunkVertexType.java @@ -0,0 +1,4 @@ +package me.jellysquid.mods.sodium.client.render.vertex.type; + +public interface ChunkVertexType { +} diff --git a/stubs/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/GlProgram.java b/stubs/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/GlProgram.java new file mode 100644 index 000000000..0b3e6d5b8 --- /dev/null +++ b/stubs/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/GlProgram.java @@ -0,0 +1,5 @@ +package net.caffeinemc.mods.sodium.client.gl.shader; + +public class GlProgram { + public void delete(){} +} diff --git a/stubs/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType.java b/stubs/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType.java new file mode 100644 index 000000000..e3572fca8 --- /dev/null +++ b/stubs/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType.java @@ -0,0 +1,4 @@ +package net.caffeinemc.mods.sodium.client.render.chunk.vertex.format; + +public interface ChunkVertexType { +} diff --git a/stubs/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/ModelCuboid.java b/stubs/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/ModelCuboid.java new file mode 100644 index 000000000..76c09a399 --- /dev/null +++ b/stubs/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/ModelCuboid.java @@ -0,0 +1,4 @@ +package net.caffeinemc.mods.sodium.client.render.immediate.model; + +public interface ModelCuboid { +} diff --git a/stubs/src/main/java/net/irisshaders/iris/Iris.java b/stubs/src/main/java/net/irisshaders/iris/Iris.java new file mode 100644 index 000000000..76e044f6d --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/Iris.java @@ -0,0 +1,11 @@ +package net.irisshaders.iris; + +import net.irisshaders.iris.pipeline.PipelineManager; +import org.jetbrains.annotations.NotNull; + +public class Iris { + @NotNull + public static PipelineManager getPipelineManager(){ + return null; + } +} diff --git a/stubs/src/main/java/net/irisshaders/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides.java b/stubs/src/main/java/net/irisshaders/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides.java new file mode 100644 index 000000000..5b1866cb3 --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides.java @@ -0,0 +1,9 @@ +package net.irisshaders.iris.compat.sodium.impl.shader_overrides; + +import net.caffeinemc.mods.sodium.client.gl.shader.GlProgram; + +import java.util.EnumMap; + +public class IrisChunkProgramOverrides { + private final EnumMap> programs = null; +} diff --git a/stubs/src/main/java/net/irisshaders/iris/compat/sodium/impl/shader_overrides/IrisChunkShaderInterface.java b/stubs/src/main/java/net/irisshaders/iris/compat/sodium/impl/shader_overrides/IrisChunkShaderInterface.java new file mode 100644 index 000000000..c652c862e --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/compat/sodium/impl/shader_overrides/IrisChunkShaderInterface.java @@ -0,0 +1,4 @@ +package net.irisshaders.iris.compat.sodium.impl.shader_overrides; + +public interface IrisChunkShaderInterface { +} diff --git a/stubs/src/main/java/net/irisshaders/iris/compat/sodium/impl/shader_overrides/IrisTerrainPass.java b/stubs/src/main/java/net/irisshaders/iris/compat/sodium/impl/shader_overrides/IrisTerrainPass.java new file mode 100644 index 000000000..10c133518 --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/compat/sodium/impl/shader_overrides/IrisTerrainPass.java @@ -0,0 +1,4 @@ +package net.irisshaders.iris.compat.sodium.impl.shader_overrides; + +public enum IrisTerrainPass { +} diff --git a/stubs/src/main/java/net/irisshaders/iris/gl/program/ProgramImages.java b/stubs/src/main/java/net/irisshaders/iris/gl/program/ProgramImages.java new file mode 100644 index 000000000..98e40a4a3 --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/gl/program/ProgramImages.java @@ -0,0 +1,4 @@ +package net.irisshaders.iris.gl.program; + +public interface ProgramImages { +} diff --git a/stubs/src/main/java/net/irisshaders/iris/gl/program/ProgramSamplers.java b/stubs/src/main/java/net/irisshaders/iris/gl/program/ProgramSamplers.java new file mode 100644 index 000000000..6b5c926bf --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/gl/program/ProgramSamplers.java @@ -0,0 +1,4 @@ +package net.irisshaders.iris.gl.program; + +public interface ProgramSamplers { +} diff --git a/stubs/src/main/java/net/irisshaders/iris/pipeline/PipelineManager.java b/stubs/src/main/java/net/irisshaders/iris/pipeline/PipelineManager.java new file mode 100644 index 000000000..fef6342df --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/pipeline/PipelineManager.java @@ -0,0 +1,11 @@ +package net.irisshaders.iris.pipeline; + +import java.util.function.Function; + +public class PipelineManager { + private WorldRenderingPipeline pipeline; + private final Function pipelineFactory = null; + + private void resetTextureState() { + } +} diff --git a/stubs/src/main/java/net/irisshaders/iris/pipeline/ShadowRenderer.java b/stubs/src/main/java/net/irisshaders/iris/pipeline/ShadowRenderer.java new file mode 100644 index 000000000..749f4523f --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/pipeline/ShadowRenderer.java @@ -0,0 +1,4 @@ +package net.irisshaders.iris.pipeline; + +public interface ShadowRenderer { +} diff --git a/stubs/src/main/java/net/irisshaders/iris/pipeline/SodiumTerrainPipeline.java b/stubs/src/main/java/net/irisshaders/iris/pipeline/SodiumTerrainPipeline.java new file mode 100644 index 000000000..dc2f08933 --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/pipeline/SodiumTerrainPipeline.java @@ -0,0 +1,4 @@ +package net.irisshaders.iris.pipeline; + +public interface SodiumTerrainPipeline { +} diff --git a/stubs/src/main/java/net/irisshaders/iris/pipeline/WorldRenderingPipeline.java b/stubs/src/main/java/net/irisshaders/iris/pipeline/WorldRenderingPipeline.java new file mode 100644 index 000000000..17a10817a --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/pipeline/WorldRenderingPipeline.java @@ -0,0 +1,7 @@ +package net.irisshaders.iris.pipeline; + +public interface WorldRenderingPipeline { + void destroy(); + + SodiumTerrainPipeline getSodiumTerrainPipeline(); +} diff --git a/stubs/src/main/java/net/irisshaders/iris/pipeline/newshader/NewWorldRenderingPipeline.java b/stubs/src/main/java/net/irisshaders/iris/pipeline/newshader/NewWorldRenderingPipeline.java new file mode 100644 index 000000000..9caa3e272 --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/pipeline/newshader/NewWorldRenderingPipeline.java @@ -0,0 +1,10 @@ +package net.irisshaders.iris.pipeline.newshader; + +import net.irisshaders.iris.pipeline.ShadowRenderer; +import net.irisshaders.iris.shadows.ShadowRenderTargets; + +public class NewWorldRenderingPipeline { + private ShadowRenderTargets shadowRenderTargets; + + private final ShadowRenderer shadowRenderer = null; +} diff --git a/stubs/src/main/java/net/irisshaders/iris/shaderpack/DimensionId.java b/stubs/src/main/java/net/irisshaders/iris/shaderpack/DimensionId.java new file mode 100644 index 000000000..2f94a3391 --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/shaderpack/DimensionId.java @@ -0,0 +1,4 @@ +package net.irisshaders.iris.shaderpack; + +public interface DimensionId { +} diff --git a/stubs/src/main/java/net/irisshaders/iris/shaderpack/PackShadowDirectives.java b/stubs/src/main/java/net/irisshaders/iris/shaderpack/PackShadowDirectives.java new file mode 100644 index 000000000..416620bb8 --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/shaderpack/PackShadowDirectives.java @@ -0,0 +1,4 @@ +package net.irisshaders.iris.shaderpack; + +public interface PackShadowDirectives { +} diff --git a/stubs/src/main/java/net/irisshaders/iris/shaderpack/ProgramSet.java b/stubs/src/main/java/net/irisshaders/iris/shaderpack/ProgramSet.java new file mode 100644 index 000000000..1859d16c3 --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/shaderpack/ProgramSet.java @@ -0,0 +1,4 @@ +package net.irisshaders.iris.shaderpack; + +public interface ProgramSet { +} diff --git a/stubs/src/main/java/net/irisshaders/iris/shaderpack/materialmap/NamespacedId.java b/stubs/src/main/java/net/irisshaders/iris/shaderpack/materialmap/NamespacedId.java new file mode 100644 index 000000000..edfefcf20 --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/shaderpack/materialmap/NamespacedId.java @@ -0,0 +1,4 @@ +package net.irisshaders.iris.shaderpack.materialmap; + +public interface NamespacedId { +} diff --git a/stubs/src/main/java/net/irisshaders/iris/shadows/ShadowRenderTargets.java b/stubs/src/main/java/net/irisshaders/iris/shadows/ShadowRenderTargets.java new file mode 100644 index 000000000..87b27f7b5 --- /dev/null +++ b/stubs/src/main/java/net/irisshaders/iris/shadows/ShadowRenderTargets.java @@ -0,0 +1,4 @@ +package net.irisshaders.iris.shadows; + +public interface ShadowRenderTargets { +}