2 Commits
dev ... mc_1217

Author SHA1 Message Date
mcrcortex
a06fc754fc bring 1.21.8 up to date 2025-10-04 12:38:49 +10:00
mcrcortex
8546a754c7 things 2025-10-04 12:35:18 +10:00
18 changed files with 127 additions and 45 deletions

View File

@@ -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:

View File

@@ -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
run: ./gradlew -I init.gradle build

View File

@@ -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

View File

@@ -105,8 +105,8 @@ dependencies {
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
//TODO: this is to eventually not need sodium installed as atm its just used for parsing shaders
modRuntimeOnlyMsk "maven.modrinth:sodium:mc1.21.6-0.6.13-fabric"
modCompileOnly "maven.modrinth:sodium:mc1.21.6-0.6.13-fabric"
modRuntimeOnlyMsk "maven.modrinth:sodium:mc1.21.8-0.7.0-fabric"
modCompileOnly "maven.modrinth:sodium:mc1.21.8-0.7.0-fabric"
modImplementation("maven.modrinth:lithium:mc1.21.8-0.18.0-fabric")
@@ -117,7 +117,7 @@ dependencies {
modRuntimeOnlyMsk("maven.modrinth:modmenu:15.0.0-beta.3")
modCompileOnly("maven.modrinth:iris:1.9.1+1.21.7-fabric")
modRuntimeOnlyMsk("maven.modrinth:iris:1.9.1+1.21.7-fabric")
//modRuntimeOnlyMsk("maven.modrinth:iris:1.9.1+1.21.7-fabric")
//modCompileOnly("maven.modrinth:starlight:1.1.3+1.20.4")

View File

@@ -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

16
init.gradle Normal file
View File

@@ -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)
}
}
}

View File

@@ -100,10 +100,10 @@ public class VoxyCommands {
}
File dbFile_ = dbFile;
var engine = WorldIdentifier.ofEngine(MinecraftClient.getInstance().player.clientWorld);
var engine = WorldIdentifier.ofEngine(MinecraftClient.getInstance().world);
if (engine==null)return 1;
return instance.getImportManager().makeAndRunIfNone(engine, ()->
new DHImporter(dbFile_, engine, MinecraftClient.getInstance().player.clientWorld, instance.getThreadPool(), instance.savingServiceRateLimiter))?0:1;
new DHImporter(dbFile_, engine, MinecraftClient.getInstance().world, instance.getThreadPool(), instance.savingServiceRateLimiter))?0:1;
}
private static boolean fileBasedImporter(File directory) {
@@ -112,10 +112,10 @@ public class VoxyCommands {
return false;
}
var engine = WorldIdentifier.ofEngine(MinecraftClient.getInstance().player.clientWorld);
var engine = WorldIdentifier.ofEngine(MinecraftClient.getInstance().world);
if (engine==null) return false;
return instance.getImportManager().makeAndRunIfNone(engine, ()->{
var importer = new WorldImporter(engine, MinecraftClient.getInstance().player.clientWorld, instance.getThreadPool(), instance.savingServiceRateLimiter);
var importer = new WorldImporter(engine, MinecraftClient.getInstance().world, instance.getThreadPool(), instance.savingServiceRateLimiter);
importer.importRegionDirectoryAsync(directory);
return importer;
});
@@ -221,10 +221,10 @@ public class VoxyCommands {
}
String finalInnerDir = innerDir;
var engine = WorldIdentifier.ofEngine(MinecraftClient.getInstance().player.clientWorld);
var engine = WorldIdentifier.ofEngine(MinecraftClient.getInstance().world);
if (engine != null) {
return instance.getImportManager().makeAndRunIfNone(engine, () -> {
var importer = new WorldImporter(engine, MinecraftClient.getInstance().player.clientWorld, instance.getThreadPool(), instance.savingServiceRateLimiter);
var importer = new WorldImporter(engine, MinecraftClient.getInstance().world, instance.getThreadPool(), instance.savingServiceRateLimiter);
importer.importZippedRegionDirectoryAsync(zip, finalInnerDir);
return importer;
}) ? 0 : 1;
@@ -238,7 +238,7 @@ public class VoxyCommands {
ctx.getSource().sendError(Text.translatable("Voxy must be enabled in settings to use this"));
return 1;
}
var world = WorldIdentifier.ofEngineNullable(MinecraftClient.getInstance().player.clientWorld);
var world = WorldIdentifier.ofEngineNullable(MinecraftClient.getInstance().world);
if (world != null) {
return instance.getImportManager().cancelImport(world)?0:1;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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<MDICViewport, B
var builder = Shader.make()
.defineIf("TAA_PATCH", taa != null)
.defineIf("DEBUG_RENDER", false)
.defineIf("DARKENED_TINTING", MinecraftClient.getInstance().world.getDimensionEffects().isDarkened())//TODO: FIXME: this is really jank atm
.addSource(ShaderType.VERTEX, vertex);
String frag = ShaderLoader.parse("voxy:lod/gl46/quads.frag");

View File

@@ -22,7 +22,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(WorldRenderer.class)
public abstract class MixinWorldRenderer implements IGetVoxyRenderSystem {
@Shadow private Frustum frustum;
@Shadow private @Nullable ClientWorld world;
@Unique private VoxyRenderSystem renderer;

View File

@@ -19,7 +19,7 @@ public class WorldEngine {
public static final int UPDATE_TYPE_DONT_SAVE = 4;
public static final int DEFAULT_UPDATE_FLAGS = UPDATE_TYPE_BLOCK_BIT | UPDATE_TYPE_CHILD_EXISTENCE_BIT;
public interface ISectionChangeCallback {void accept(WorldSection section, int updateFlags);}
public interface ISectionChangeCallback {void accept(WorldSection section, int updateFlags, int neighborMsk);}
public interface ISectionSaveCallback {void save(WorldEngine engine, WorldSection section);}
private final TrackedObject thisTracker = TrackedObject.createTrackedObject(this);
@@ -113,16 +113,16 @@ public class WorldEngine {
//Marks a section as dirty, enqueuing it for saving and or render data rebuilding
public void markDirty(WorldSection section) {
this.markDirty(section, DEFAULT_UPDATE_FLAGS);
this.markDirty(section, DEFAULT_UPDATE_FLAGS, 0);
}
public void markDirty(WorldSection section, int changeState) {
public void markDirty(WorldSection section, int changeState, int neighborMsk) {
if (!this.isLive) throw new IllegalStateException("World is not live");
if (section.tracker != this.sectionTracker) {
throw new IllegalStateException("Section is not from here");
}
if (this.dirtyCallback != null) {
this.dirtyCallback.accept(section, changeState);
this.dirtyCallback.accept(section, changeState, neighborMsk);
}
if ((!section.inSaveQueue)&&(changeState&UPDATE_TYPE_DONT_SAVE)==0) {
section.markDirty();

View File

@@ -104,7 +104,7 @@ public class WorldUpdater {
//Bitmask of neighboring sections
//Note, this may be zero (this is more likely to occure at higher lod levels) if it doesnt face any neighbors
int neighbors = 0;
{
if (didStateChange) {
neighbors |= ((section.y^(section.y-1))>>(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

View File

@@ -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<StateEntry> sentries = new ArrayList<>();
List<BiomeEntry> bentries = new ArrayList<>();
List<Pair<byte[], Integer>> 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.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());
}

View File

@@ -86,6 +86,5 @@ public class VoxyCommon implements ModInitializer {
return FACTORY != null;
}
public static final boolean IS_MINE_IN_ABYSS = false;
}

View File

@@ -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

View File

@@ -35,7 +35,7 @@
"minecraft": ["1.21.8","1.21.7","1.21.6"],
"fabricloader": ">=0.14.22",
"fabric-api": ">=0.91.1",
"sodium": ">=0.6.13"
"sodium": "=0.7.*"
},
"accessWidener": "voxy.accesswidener"
}