diff --git a/.github/workflows/check-does-build-pr.yml b/.github/workflows/check-does-build-pr.yml index 17529549..08cc4d50 100644 --- a/.github/workflows/check-does-build-pr.yml +++ b/.github/workflows/check-does-build-pr.yml @@ -9,9 +9,6 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 - - name: Verify wrapper - uses: gradle/actions/wrapper-validation@v3 - - name: Setup Java uses: actions/setup-java@v4 with: diff --git a/.github/workflows/check-does-build.yml b/.github/workflows/check-does-build.yml index c672534d..353c6cfb 100644 --- a/.github/workflows/check-does-build.yml +++ b/.github/workflows/check-does-build.yml @@ -9,19 +9,24 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 - - name: Verify wrapper - uses: gradle/actions/wrapper-validation@v3 - - name: Setup Java uses: actions/setup-java@v4 with: distribution: temurin java-version: 21 + - name: Loom Cache + uses: actions/cache@v4 + with: + path: "**/.gradle/loom-cache" + key: "${{ runner.os }}-gradle-${{ hashFiles('**/libs.versions.*', '**/*.gradle*', '**/gradle-wrapper.properties') }}" + restore-keys: "${{ runner.os }}-gradle-" + - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 with: cache-read-only: false + cache-cleanup: never - name: Gradle build - run: ./gradlew build \ No newline at end of file + run: ./gradlew -I init.gradle build \ No newline at end of file diff --git a/.github/workflows/manual-artifact.yml b/.github/workflows/manual-artifact.yml index 15bb2960..7637d577 100644 --- a/.github/workflows/manual-artifact.yml +++ b/.github/workflows/manual-artifact.yml @@ -9,9 +9,6 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 - - name: Verify wrapper - uses: gradle/actions/wrapper-validation@v3 - - name: Setup Java uses: actions/setup-java@v4 with: @@ -22,6 +19,7 @@ jobs: uses: gradle/actions/setup-gradle@v4 with: cache-read-only: false + cache-cleanup: always - name: Gradle build run: ./gradlew build diff --git a/gradle.properties b/gradle.properties index d003c05b..33eb4930 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,6 +3,7 @@ org.gradle.jvmargs=-Xmx2G org.gradle.caching=true org.gradle.parallel=true +org.gradle.daemon = false # Fabric Properties # check these on https://modmuss50.me/fabric.html diff --git a/init.gradle b/init.gradle new file mode 100644 index 00000000..acb5f2ca --- /dev/null +++ b/init.gradle @@ -0,0 +1,16 @@ +if (System.getenv("GITHUB_ACTIONS") == "true") { + beforeSettings { settings -> + def cleanupTime = Long.parseLong(System.getProperty("CLEANUP_TIME", Long.toString(System.currentTimeMillis()-(60_000*10))));//Remove unused entries from more then 10 min old + + settings.caches { + //Note: this could be Cleanup.DEFAULT + cleanup = Cleanup.ALWAYS + + releasedWrappers.setRemoveUnusedEntriesOlderThan(cleanupTime) + snapshotWrappers.setRemoveUnusedEntriesOlderThan(cleanupTime) + downloadedResources.setRemoveUnusedEntriesOlderThan(cleanupTime) + createdResources.setRemoveUnusedEntriesOlderThan(cleanupTime) + buildCache.setRemoveUnusedEntriesOlderThan(cleanupTime) + } + } +} \ No newline at end of file diff --git a/src/main/java/me/cortex/voxy/client/VoxyClient.java b/src/main/java/me/cortex/voxy/client/VoxyClient.java index b07d2be7..90145571 100644 --- a/src/main/java/me/cortex/voxy/client/VoxyClient.java +++ b/src/main/java/me/cortex/voxy/client/VoxyClient.java @@ -57,4 +57,4 @@ public class VoxyClient implements ClientModInitializer { public static boolean isFrexActive() { return !FREX.isEmpty(); } -} +} \ No newline at end of file diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/SectionUpdateRouter.java b/src/main/java/me/cortex/voxy/client/core/rendering/SectionUpdateRouter.java index fba3d377..dd05474b 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/SectionUpdateRouter.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/SectionUpdateRouter.java @@ -69,7 +69,7 @@ public class SectionUpdateRouter implements ISectionWatcher { } lock.unlock(stamp); } - if ((delta&UPDATE_TYPE_BLOCK_BIT)!=0) { + if (((delta&types)&UPDATE_TYPE_BLOCK_BIT)!=0) { //If we added it, immediately invoke for an update this.initialRenderMeshGen.accept(position); } @@ -138,19 +138,32 @@ public class SectionUpdateRouter implements ISectionWatcher { var lock = this.locks[idx]; long stamp = lock.readLock(); - byte types = set.getOrDefault(position, (byte) 0); + byte types = (byte) (set.getOrDefault(position, (byte) 0)&type); lock.unlockRead(stamp); if (types!=0) { - if ((type&WorldEngine.UPDATE_TYPE_CHILD_EXISTENCE_BIT)!=0) { + if ((types&WorldEngine.UPDATE_TYPE_CHILD_EXISTENCE_BIT)!=0) { this.childUpdateCallback.accept(section); } - if ((type&UPDATE_TYPE_BLOCK_BIT)!=0) { + if ((types&UPDATE_TYPE_BLOCK_BIT)!=0) { this.renderMeshGen.accept(section.key); } } } + public void triggerRemesh(long position) { + int idx = getSliceIndex(position); + var set = this.slices[idx]; + var lock = this.locks[idx]; + + long stamp = lock.readLock(); + byte types = set.getOrDefault(position, (byte) 0); + lock.unlockRead(stamp); + if ((types&UPDATE_TYPE_BLOCK_BIT)!=0) { + this.renderMeshGen.accept(position); + } + } + private static int getSliceIndex(long value) { value = (value ^ value >>> 30) * -4658895280553007687L; value = (value ^ value >>> 27) * -7723592293110705685L; diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/AsyncNodeManager.java b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/AsyncNodeManager.java index 4055a00f..5fb9889a 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/AsyncNodeManager.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/AsyncNodeManager.java @@ -20,6 +20,7 @@ import me.cortex.voxy.common.Logger; import me.cortex.voxy.common.util.AllocationArena; import me.cortex.voxy.common.util.MemoryBuffer; import me.cortex.voxy.common.util.UnsafeUtil; +import me.cortex.voxy.common.world.WorldEngine; import me.cortex.voxy.common.world.WorldSection; import org.lwjgl.system.MemoryUtil; @@ -760,11 +761,20 @@ public class AsyncNodeManager { return this.workCounter.get()!=0 || RESULT_HANDLE.get(this) != null; } - public void worldEvent(WorldSection section, int flags) { + public void worldEvent(WorldSection section, int flags, int neighborMask) { //If there is any change, we need to clear the geometry cache before emitting update this.geometryCache.clear(section.key); this.router.forwardEvent(section, flags); + + if (neighborMask != 0) {//trigger rebuilds for neighbors + if ((neighborMask&0b000001)!=0) this.router.triggerRemesh(WorldEngine.getWorldSectionId(section.lvl, section.x, section.y-1, section.z));//-y + if ((neighborMask&0b000010)!=0) this.router.triggerRemesh(WorldEngine.getWorldSectionId(section.lvl, section.x, section.y+1, section.z));//+y + if ((neighborMask&0b000100)!=0) this.router.triggerRemesh(WorldEngine.getWorldSectionId(section.lvl, section.x-1, section.y, section.z));//-x + if ((neighborMask&0b001000)!=0) this.router.triggerRemesh(WorldEngine.getWorldSectionId(section.lvl, section.x+1, section.y, section.z));//+x + if ((neighborMask&0b010000)!=0) this.router.triggerRemesh(WorldEngine.getWorldSectionId(section.lvl, section.x, section.y, section.z-1));//-z + if ((neighborMask&0b100000)!=0) this.router.triggerRemesh(WorldEngine.getWorldSectionId(section.lvl, section.x, section.y, section.z+1));//+z + } } //Results object, which is to be synced between the render thread and worker thread diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java index 5409f7e0..34df90f4 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java @@ -17,6 +17,7 @@ import me.cortex.voxy.client.core.rendering.util.SharedIndexBuffer; import me.cortex.voxy.client.core.rendering.util.UploadStream; import me.cortex.voxy.common.Logger; import me.cortex.voxy.common.world.WorldEngine; +import net.minecraft.client.MinecraftClient; import org.joml.Matrix4f; import org.lwjgl.system.MemoryUtil; @@ -102,6 +103,9 @@ public class MDICSectionRenderer extends AbstractSectionRenderer>(lvl+1))==0?0:1<<0;//Down neighbors |= ((section.y^(section.y+1))>>(lvl+1))==0?0:1<<1;//Up neighbors |= ((section.x^(section.x-1))>>(lvl+1))==0?0:1<<2;//-x @@ -113,7 +113,7 @@ public class WorldUpdater { neighbors |= ((section.z^(section.z+1))>>(lvl+1))==0?0:1<<5;//+z } - into.markDirty(worldSection, (didStateChange?UPDATE_TYPE_BLOCK_BIT:0)|(emptinessStateChange!=0?UPDATE_TYPE_CHILD_EXISTENCE_BIT:0)); + into.markDirty(worldSection, (didStateChange?UPDATE_TYPE_BLOCK_BIT:0)|(emptinessStateChange!=0?UPDATE_TYPE_CHILD_EXISTENCE_BIT:0), neighbors); } //Need to release the section after using it diff --git a/src/main/java/me/cortex/voxy/common/world/other/Mapper.java b/src/main/java/me/cortex/voxy/common/world/other/Mapper.java index d7d00cf3..c10ec599 100644 --- a/src/main/java/me/cortex/voxy/common/world/other/Mapper.java +++ b/src/main/java/me/cortex/voxy/common/world/other/Mapper.java @@ -1,12 +1,16 @@ package me.cortex.voxy.common.world.other; +import com.mojang.serialization.Dynamic; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import me.cortex.voxy.common.Logger; import me.cortex.voxy.common.config.IMappingStorage; +import net.minecraft.SharedConstants; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.LeavesBlock; +import net.minecraft.datafixer.Schemas; +import net.minecraft.datafixer.TypeReferences; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.NbtOps; @@ -95,26 +99,31 @@ public class Mapper { } private void loadFromStorage() { + //TODO: FIXME: have/store the minecraft version the mappings are from (the data version) + // SharedConstants.getGameVersion().dataVersion().id() + // then use this to create an update path instead + var mappings = this.storage.getIdMappingsData(); List sentries = new ArrayList<>(); List bentries = new ArrayList<>(); List> sentryErrors = new ArrayList<>(); - + boolean[] forceResave = new boolean[1]; for (var entry : mappings.int2ObjectEntrySet()) { int entryType = entry.getIntKey()>>>30; int id = entry.getIntKey() & ((1<<30)-1); if (entryType == BLOCK_STATE_TYPE) { - var sentry = StateEntry.deserialize(id, entry.getValue()); + var sentry = StateEntry.deserialize(id, entry.getValue(), forceResave); if (sentry.state.isAir()) { Logger.error("Deserialization was air, removed block"); sentryErrors.add(new Pair<>(entry.getValue(), id)); continue; } sentries.add(sentry); - var oldEntry = this.block2stateEntry.put(sentry.state, sentry); + var oldEntry = this.block2stateEntry.putIfAbsent(sentry.state, sentry); if (oldEntry != null) { - throw new IllegalStateException("Multiple mappings for blockstate"); + //forceResave[0] |= true; + Logger.warn("Multiple mappings for blockstate, using old state, expect things to possibly go really badly. " + oldEntry.id + ":" + sentry.id + ":" + sentry.state ); } } else if (entryType == BIOME_TYPE) { var bentry = BiomeEntry.deserialize(id, entry.getValue()); @@ -127,7 +136,8 @@ public class Mapper { } } - { + if (!sentryErrors.isEmpty()) { + forceResave[0] |= true; //Insert garbage types into the mapping for those blocks, TODO:FIXME: Need to upgrade the type or have a solution to error blocks var rand = new Random(); for (var error : sentryErrors) { @@ -156,6 +166,10 @@ public class Mapper { this.biomeId2biomeEntry.add(entry); }); + if (forceResave[0]) { + Logger.warn("Forced state resave triggered"); + this.forceResaveStates(); + } } public final int getBlockStateCount() { @@ -357,16 +371,26 @@ public class Mapper { } } - public static StateEntry deserialize(int id, byte[] data) { + public static StateEntry deserialize(int id, byte[] data, boolean[] forceResave) { try { var compound = NbtIo.readCompressed(new ByteArrayInputStream(data), NbtSizeTracker.ofUnlimitedBytes()); if (compound.getInt("id", -1) != id) { throw new IllegalStateException("Encoded id != expected id"); } - var state = BlockState.CODEC.parse(NbtOps.INSTANCE, compound.getCompound("block_state").orElseThrow()); + var bsc = compound.getCompound("block_state").orElseThrow(); + var state = BlockState.CODEC.parse(NbtOps.INSTANCE, bsc); if (state.isError()) { - Logger.error("Could not decode blockstate setting to air. id:" + id + " error: " + state.error().get().message()); - return new StateEntry(id, Blocks.AIR.getDefaultState()); + Logger.info("Could not decode blockstate, attempting fixes, error: "+ state.error().get().message()); + bsc = (NbtCompound) Schemas.getFixer().update(TypeReferences.BLOCK_STATE, new Dynamic<>(NbtOps.INSTANCE,bsc),0, SharedConstants.getGameVersion().dataVersion().id()).getValue(); + state = BlockState.CODEC.parse(NbtOps.INSTANCE, bsc); + if (state.isError()) { + Logger.error("Could not decode blockstate setting to air. id:" + id + " error: " + state.error().get().message()); + return new StateEntry(id, Blocks.AIR.getDefaultState()); + } else { + Logger.info("Fixed blockstate to: " + state.getOrThrow()); + forceResave[0] |= true; + return new StateEntry(id, state.getOrThrow()); + } } else { return new StateEntry(id, state.getOrThrow()); } diff --git a/src/main/java/me/cortex/voxy/commonImpl/VoxyCommon.java b/src/main/java/me/cortex/voxy/commonImpl/VoxyCommon.java index bf8c9509..213378a4 100644 --- a/src/main/java/me/cortex/voxy/commonImpl/VoxyCommon.java +++ b/src/main/java/me/cortex/voxy/commonImpl/VoxyCommon.java @@ -86,6 +86,5 @@ public class VoxyCommon implements ModInitializer { return FACTORY != null; } - public static final boolean IS_MINE_IN_ABYSS = false; -} +} \ No newline at end of file diff --git a/src/main/resources/assets/voxy/shaders/lod/gl46/quads2.vert b/src/main/resources/assets/voxy/shaders/lod/gl46/quads2.vert index 2b0df07c..33580366 100644 --- a/src/main/resources/assets/voxy/shaders/lod/gl46/quads2.vert +++ b/src/main/resources/assets/voxy/shaders/lod/gl46/quads2.vert @@ -167,6 +167,21 @@ void main() { } //Apply face tint + #ifdef DARKENED_TINTING + if (isShaded) { + //TODO: make branchless, infact apply ahead of time to the texture itself in ModelManager since that is + // per face + if ((face>>1) == 1) {//NORTH, SOUTH + tinting.xyz *= 0.8f; + } else if ((face>>1) == 2) {//EAST, WEST + tinting.xyz *= 0.6f; + } else {//UP DOWN + tinting.xyz *= 0.9f; + } + } else { + tinting.xyz *= 0.9f; + } + #else if (isShaded) { //TODO: make branchless, infact apply ahead of time to the texture itself in ModelManager since that is // per face @@ -178,6 +193,7 @@ void main() { tinting.xyz *= 0.5f; } } + #endif setTintingAndExtra(tinting, conditionalTinting, addin|(face<<8)); #else