From cd96d4238df9df31bae093154f3b905dac1dd68d Mon Sep 17 00:00:00 2001 From: cputnam-a11y Date: Sun, 24 Nov 2024 15:34:30 -0600 Subject: [PATCH 1/6] Sodium Compat --- build.gradle | 251 ++++++++++-------- gradle.properties | 3 + .../illusionist/IllusionistClient.java | 4 +- .../accessor/ClonedChunkSectionAccessor.java | 14 + .../illusionist/debug/ClientDebugHelper.java | 16 ++ .../illusionist/debug/DebugKeybindings.java | 50 ++++ .../IllusionistClientMixinConfigPlugin.java | 46 ++++ .../mixin/client/RenderedChunkMixin.java | 2 - .../sodium/ChunkBuilderMeshingTaskMixin.java | 63 +++++ .../sodium/ClonedChunkSectionMixin.java | 51 ++++ .../client/sodium/LevelSliceAccessor.java | 44 +++ .../resources/illusionist.client.mixins.json | 22 +- .../illusionist/Illusionist.java | 9 +- .../cca/ShadowDisguiseMapComponent.java | 6 +- .../illusionist/debug/DebugHelper.java | 18 ++ .../illusionist/debug/item/DebugItems.java | 30 +++ .../debug/item/SodiumDeathStick.java | 53 ++++ .../illusionist/mixin/WorldChunkMixin.java | 10 +- .../assets/illusionist/lang/en_us.yml | 8 + .../models/item/sodium_death_stick.json | 3 + src/main/resources/fabric.mod.json | 2 +- 21 files changed, 564 insertions(+), 141 deletions(-) create mode 100644 src/client/java/stellarwitch7/illusionist/accessor/ClonedChunkSectionAccessor.java create mode 100644 src/client/java/stellarwitch7/illusionist/debug/ClientDebugHelper.java create mode 100644 src/client/java/stellarwitch7/illusionist/debug/DebugKeybindings.java create mode 100644 src/client/java/stellarwitch7/illusionist/mixin/client/IllusionistClientMixinConfigPlugin.java create mode 100644 src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java create mode 100644 src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java create mode 100644 src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceAccessor.java create mode 100644 src/main/java/stellarwitch7/illusionist/debug/DebugHelper.java create mode 100644 src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java create mode 100644 src/main/java/stellarwitch7/illusionist/debug/item/SodiumDeathStick.java create mode 100644 src/main/resources/assets/illusionist/models/item/sodium_death_stick.json diff --git a/build.gradle b/build.gradle index 7bbb087..a24bf1b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,164 +1,179 @@ plugins { - id 'fabric-loom' version '1.8-SNAPSHOT' - id 'maven-publish' - id "me.modmuss50.mod-publish-plugin" version "0.4.4" - id 'me.fallenbreath.yamlang' version '1.3.1' + id 'fabric-loom' version '1.8-SNAPSHOT' + id 'maven-publish' + id "me.modmuss50.mod-publish-plugin" version "0.4.4" + id 'me.fallenbreath.yamlang' version '1.3.1' } version = project.mod_version group = project.maven_group - base { - archivesName = project.archives_base_name + archivesName = project.archives_base_name } repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. - - maven { - url "https://maven.enjarai.dev/releases" - } - maven { - url "https://maven.enjarai.dev/mirrors" - } - - maven { - name "Terraformers Maven" - url 'https://maven.terraformersmc.com' - } + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. + + maven { + url "https://maven.enjarai.dev/releases" + } + maven { + url "https://maven.enjarai.dev/mirrors" + } + + maven { + //noinspection GroovyAssignabilityCheck + name "Terraformers Maven" + url 'https://maven.terraformersmc.com' + } + exclusiveContent { + forRepository { + //noinspection ForeignDelegate + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + } + filter { + includeGroup "maven.modrinth" + } + } } loom { - splitEnvironmentSourceSets() - - mods { - "illusionist" { - sourceSet sourceSets.main - sourceSet sourceSets.client - } - } - + splitEnvironmentSourceSets() + + mods { + "illusionist" { + sourceSet sourceSets.main + sourceSet sourceSets.client + } + } } dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${property('deps.minecraft')}" - mappings "net.fabricmc:yarn:${property('deps.yarn')}:v2" - modImplementation "net.fabricmc:fabric-loader:${property('deps.floader')}" - // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${property('deps.fabric-api')}" + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${property('deps.minecraft')}" + mappings "net.fabricmc:yarn:${property('deps.yarn')}:v2" + modImplementation "net.fabricmc:fabric-loader:${property('deps.floader')}" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${property('deps.fabric-api')}" + + modImplementation "dev.enjarai:trickster:${property('deps.trickster')}" - modImplementation "dev.enjarai:trickster:${property('deps.trickster')}" + modImplementation "com.terraformersmc:modmenu:${property('deps.modmenu')}" - modImplementation "com.terraformersmc:modmenu:${property('deps.modmenu')}" + modCompileOnly "maven.modrinth:sodium:${property("deps.sodium")}" + modLocalRuntime "maven.modrinth:sodium:${property("deps.sodium")}" } processResources { - inputs.property "version", project.version + inputs.property "version", project.version - filesMatching("fabric.mod.json") { - expand "version": project.version - } + filesMatching("fabric.mod.json") { + expand "version": project.version + } } tasks.withType(JavaCompile).configureEach { - it.options.release = 21 + it.options.release = 21 } java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } jar { - from("LICENSE") { - rename { "${it}_${project.base.archivesName.get()}"} - } + from("LICENSE") { + rename { "${it}_${project.base.archivesName.get()}" } + } } yamlang { - targetSourceSets = [sourceSets.main] - inputDir = "assets/illusionist/lang" + targetSourceSets = [sourceSets.main] + inputDir = "assets/illusionist/lang" } // configure the maven publication publishing { - repositories { - maven { - name = "enjaraiMaven" - url = "https://maven.enjarai.dev/releases" - credentials(PasswordCredentials) - authentication { - basic(BasicAuthentication) - } - } - } - - publications { - mavenJava(MavenPublication) { - groupId = group - artifactId = archivesBaseName - version = version - - from components.java - } - } + repositories { + maven { + name = "enjaraiMaven" + url = "https://maven.enjarai.dev/releases" + credentials(PasswordCredentials) + authentication { + basic(BasicAuthentication) + } + } + } + + publications { + mavenJava(MavenPublication) { + groupId = group + artifactId = archivesBaseName + version = version + + from components.java + } + } } publishMods { - file = remapJar.archiveFile - displayName = "Illusionist ${property('mod_version')} for Trickster ${property('deps.trickster')}" - version = project.version - changelog = getRootProject().file("CHANGELOG.md").text - type = STABLE - modLoaders.add("fabric") - - def min = property('publish_target_min') - def max = property('publish_target_max') - - if (providers.gradleProperty('enjaraiModrinthToken').present) { - modrinth { - projectId = property('mod_modrinth') - accessToken = providers.gradleProperty('enjaraiModrinthToken').get() - - if (min == max) { - minecraftVersions.add(min) - } else { - minecraftVersionRange { - start = min - end = max - } - } - - requires { - slug = "trickster" - } - } - } - - if (providers.gradleProperty('enjaraiGithubToken').present) { - github { - repository = property('mod_github') - accessToken = providers.gradleProperty('enjaraiGithubToken').get() - - commitish = property('git_branch') - tagName = project.version - } - } + file = remapJar.archiveFile + displayName = "Illusionist ${property('mod_version')} for Trickster ${property('deps.trickster')}" + version = project.version + changelog = getRootProject().file("CHANGELOG.md").text + type = STABLE + modLoaders.add("fabric") + + def min = property('publish_target_min') + def max = property('publish_target_max') + + if (providers.gradleProperty('enjaraiModrinthToken').present) { + modrinth { + projectId = property('mod_modrinth') + accessToken = providers.gradleProperty('enjaraiModrinthToken').get() + + if (min == max) { + minecraftVersions.add(min) + } else { + minecraftVersionRange { + start = min + end = max + } + } + + requires { + slug = "trickster" + } + } + } + + if (providers.gradleProperty('enjaraiGithubToken').present) { + github { + repository = property('mod_github') + accessToken = providers.gradleProperty('enjaraiGithubToken').get() + + commitish = property('git_branch') + tagName = project.version + } + } } tasks.register('publishAll') { - group 'publishing' - dependsOn 'publish' - dependsOn 'publishMods' + group 'publishing' + dependsOn 'publish' + dependsOn 'publishMods' } diff --git a/gradle.properties b/gradle.properties index 908dacc..035f588 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,3 +24,6 @@ deps.floader=0.15.11 deps.fabric-api=0.100.1+1.21 deps.trickster=2.0.0-beta.1 deps.modmenu=11.0.1 +#deps.sodium.v0.5.9=dNHeFokL +#deps.sodium.v0.5.11=RncWhTxD +deps.sodium=CcIWi5Av diff --git a/src/client/java/stellarwitch7/illusionist/IllusionistClient.java b/src/client/java/stellarwitch7/illusionist/IllusionistClient.java index d7b460e..220cf87 100644 --- a/src/client/java/stellarwitch7/illusionist/IllusionistClient.java +++ b/src/client/java/stellarwitch7/illusionist/IllusionistClient.java @@ -1,10 +1,12 @@ package stellarwitch7.illusionist; import net.fabricmc.api.ClientModInitializer; +import stellarwitch7.illusionist.debug.ClientDebugHelper; public class IllusionistClient implements ClientModInitializer { + @Override public void onInitializeClient() { - // This entrypoint is suitable for setting up client-specific logic, such as rendering. + ClientDebugHelper.registerIfInDev(); } } \ No newline at end of file diff --git a/src/client/java/stellarwitch7/illusionist/accessor/ClonedChunkSectionAccessor.java b/src/client/java/stellarwitch7/illusionist/accessor/ClonedChunkSectionAccessor.java new file mode 100644 index 0000000..78376f5 --- /dev/null +++ b/src/client/java/stellarwitch7/illusionist/accessor/ClonedChunkSectionAccessor.java @@ -0,0 +1,14 @@ +package stellarwitch7.illusionist.accessor; + +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.minecraft.block.Block; + +import java.util.concurrent.atomic.AtomicReference; + +public interface ClonedChunkSectionAccessor { + /** + * Gets the shadow block states for this chunk section. + * @return the shadow block states for this chunk section + */ + AtomicReference> illusionist$getBlockStates(); +} diff --git a/src/client/java/stellarwitch7/illusionist/debug/ClientDebugHelper.java b/src/client/java/stellarwitch7/illusionist/debug/ClientDebugHelper.java new file mode 100644 index 0000000..6c6c03c --- /dev/null +++ b/src/client/java/stellarwitch7/illusionist/debug/ClientDebugHelper.java @@ -0,0 +1,16 @@ +package stellarwitch7.illusionist.debug; + +import net.fabricmc.loader.api.FabricLoader; +/** + * A helper class for conditionally registering debug features. + */ +public class ClientDebugHelper { + /** + * Registers the debug features if the game is in a development environment. + */ + public static void registerIfInDev() { + if (!FabricLoader.getInstance().isDevelopmentEnvironment()) + return; + DebugKeybindings.register(); + } +} diff --git a/src/client/java/stellarwitch7/illusionist/debug/DebugKeybindings.java b/src/client/java/stellarwitch7/illusionist/debug/DebugKeybindings.java new file mode 100644 index 0000000..8ef5384 --- /dev/null +++ b/src/client/java/stellarwitch7/illusionist/debug/DebugKeybindings.java @@ -0,0 +1,50 @@ +package stellarwitch7.illusionist.debug; + +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.text.Text; +import net.minecraft.util.hit.BlockHitResult; +import stellarwitch7.illusionist.cca.ModChunkComponents; + +import java.util.Objects; + +public class DebugKeybindings { + public static final KeyBinding LOG_FUNNY_STATE = KeyBindingHelper.registerKeyBinding( + new KeyBinding("key.illusionist.log", InputUtil.UNKNOWN_KEY.getCode(), "key.categories.illusionist") + ); + + static { + ClientTickEvents.END_CLIENT_TICK.register(DebugKeybindings::onClientTick); + } + public static void register() { + + } + private static void onClientTick(MinecraftClient client) { + // only act if the keybinding was pressed + if (LOG_FUNNY_STATE.wasPressed()) { + // consume all remaining presses + //noinspection StatementWithEmptyBody + while (LOG_FUNNY_STATE.wasPressed()) ; + // if the crosshair target is not a block hit result, we are not interested in it, return + if (!(client.crosshairTarget instanceof BlockHitResult hitResult)) { + return; + } + // if world is null, we have bigger things to worry about + // the current world on the client (should be the one that is rendering) + var world = Objects.requireNonNull(client.world); + // the player + var player = Objects.requireNonNull(client.player); + // get the disguise map for the chunk that the block is in + var map = ModChunkComponents.SHADOW_DISGUISE_MAP.get(world.getChunk(hitResult.getBlockPos())); + // get the funny state of the block at the hit position + BlockState funnyState = map.getFunnyState(hitResult.getBlockPos()); + // send a message to the player with the funny state + player.sendMessage(Text.of("Funny state: " + funnyState), false); + } + } +} diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/IllusionistClientMixinConfigPlugin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/IllusionistClientMixinConfigPlugin.java new file mode 100644 index 0000000..a69ecf7 --- /dev/null +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/IllusionistClientMixinConfigPlugin.java @@ -0,0 +1,46 @@ +package stellarwitch7.illusionist.mixin.client; + +import net.fabricmc.loader.api.FabricLoader; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.util.List; +import java.util.Set; + +public class IllusionistClientMixinConfigPlugin implements IMixinConfigPlugin { + @Override + public void onLoad(String mixinPackage) { + + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + return !mixinClassName.contains("sodium") || FabricLoader.getInstance().isModLoaded("sodium"); + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + + } + + @Override + public List getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } +} diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/RenderedChunkMixin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/RenderedChunkMixin.java index c4392d8..ca23656 100644 --- a/src/client/java/stellarwitch7/illusionist/mixin/client/RenderedChunkMixin.java +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/RenderedChunkMixin.java @@ -6,7 +6,6 @@ import net.minecraft.world.chunk.WorldChunk; import stellarwitch7.illusionist.cca.ModChunkComponents; import stellarwitch7.illusionist.cca.ShadowDisguiseMapComponent; - import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -14,7 +13,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - import java.util.function.Supplier; @Mixin(targets = "net/minecraft/client/render/chunk/RenderedChunk") diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java new file mode 100644 index 0000000..efff58b --- /dev/null +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java @@ -0,0 +1,63 @@ +package stellarwitch7.illusionist.mixin.client.sodium; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderTask; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.caffeinemc.mods.sodium.client.world.cloned.ChunkRenderContext; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import org.joml.Vector3dc; +import org.spongepowered.asm.mixin.Debug; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import stellarwitch7.illusionist.accessor.ClonedChunkSectionAccessor; + +@Debug(export = true) +@Mixin(ChunkBuilderMeshingTask.class) +public abstract class ChunkBuilderMeshingTaskMixin extends ChunkBuilderTask { + @Shadow(remap = false) + @Final + private ChunkRenderContext renderContext; + + public ChunkBuilderMeshingTaskMixin(RenderSection render, int time, Vector3dc absoluteCameraPos) { + super(render, time, absoluteCameraPos); + } + + @WrapOperation( + method = "execute(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lnet/caffeinemc/mods/sodium/client/util/task/CancellationToken;)Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;", + at = @At( + value = "INVOKE", + target = "Lnet/caffeinemc/mods/sodium/client/world/LevelSlice;getBlockState(III)Lnet/minecraft/block/BlockState;" + ) + ) + private BlockState wrapGetBlockState(LevelSlice instance, int x, int y, int z, Operation original) { + BlockState state = original.call(instance, x, y, z); + int relBlockX = x - ((LevelSliceAccessor)(Object)instance).getOriginBlockX(); + @SuppressWarnings("DataFlowIssue") + int relBlockY = y - ((LevelSliceAccessor)(Object)instance).getOriginBlockY(); + @SuppressWarnings("DataFlowIssue") + int relBlockZ = z - ((LevelSliceAccessor)(Object)instance).getOriginBlockZ(); + var map = ((ClonedChunkSectionAccessor) this.renderContext.getSections()[LevelSliceAccessor.invokeGetLocalSectionIndex(relBlockX >> 4, relBlockY >> 4, relBlockZ >> 4)]).illusionist$getBlockStates(); + if (map.get().containsKey(encodePos(x, y, z))) { + state = map.get().get(encodePos(x, y, z)).getDefaultState(); + } + return state; + } + + private static int encodePos(BlockPos pos) { + return encodePos(pos.getX(), pos.getY(), pos.getZ()); + } + + private static int encodePos(int x, int y, int z) { + var xe = x & 15; + var ze = (z & 15) << 4; + var ye = y << 8; + return ye | ze | xe; + } +} diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java new file mode 100644 index 0000000..77bb93d --- /dev/null +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java @@ -0,0 +1,51 @@ +package stellarwitch7.illusionist.mixin.client.sodium; + +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.caffeinemc.mods.sodium.client.world.cloned.ClonedChunkSection; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask; +import net.minecraft.block.Block; +import net.minecraft.util.math.ChunkSectionPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.ChunkSection; +import net.minecraft.world.chunk.WorldChunk; +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 stellarwitch7.illusionist.accessor.ClonedChunkSectionAccessor; +import stellarwitch7.illusionist.cca.ModChunkComponents; + +import java.util.concurrent.atomic.AtomicReference; + +@Mixin(ClonedChunkSection.class) +public class ClonedChunkSectionMixin implements ClonedChunkSectionAccessor { + /** + * The shadow block states for this chunk section. + * stored as an atomic reference to allow for safe access in a {@link ChunkBuilderMeshingTask} + */ + @Unique + private final AtomicReference> blockStates = new AtomicReference<>(); + + /** + * Stores a copy of a chunks shadow disguise map with this section, to safely access it later in a {@link ChunkBuilderMeshingTask } + * @param level the world currently rendering + * @param chunk the chunk sodium is copying this section from + * @param section the chunk section sodium is copying + * @param pos the position of the chunk section sodium is copying + * @param ci no explanation needed + */ + @Inject(method = "", at = @At("TAIL")) + private void appendShadowDisguiseMap(World level, WorldChunk chunk, ChunkSection section, ChunkSectionPos pos, CallbackInfo ci) { + blockStates.set(ModChunkComponents.SHADOW_DISGUISE_MAP.get(chunk).toUpdateMap()); + } + + /** + * Gets the shadow block states for this chunk section. + * @return the shadow block states for this chunk section + */ + @Override + public AtomicReference> illusionist$getBlockStates() { + return blockStates; + } +} diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceAccessor.java b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceAccessor.java new file mode 100644 index 0000000..8f8137b --- /dev/null +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceAccessor.java @@ -0,0 +1,44 @@ +package stellarwitch7.illusionist.mixin.client.sodium; + +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.caffeinemc.mods.sodium.client.world.cloned.ChunkRenderContext; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(LevelSlice.class) +public interface LevelSliceAccessor { + /** + * Gets the x-coordinate of the origin block of this level slice. + * @return the x-coordinate of the origin block of this level slice + */ + @Accessor(value = "originBlockX", remap = false) + int getOriginBlockX(); + + /** + * Gets the y-coordinate of the origin block of this level slice. + * @return the y-coordinate of the origin block of this level slice + */ + @Accessor(value = "originBlockY", remap = false) + int getOriginBlockY(); + + /** + * Gets the z-coordinate of the origin block of this level slice. + * @return the z-coordinate of the origin block of this level slice + */ + @Accessor(value = "originBlockZ", remap = false) + int getOriginBlockZ(); + + /** + * Gets the local section index for the given coordinates + * + * @param x the x-coordinate of the section (different from the block x-coordinate) + * @param y the y-coordinate of the section (different from the block y-coordinate) + * @param z the z-coordinate of the section (different from the block z-coordinate) + * @return the index of the section in the local section array (the same as the one in {@link ChunkRenderContext}) + */ + @Invoker(value = "getLocalSectionIndex", remap = false) + static int invokeGetLocalSectionIndex(int x, int y, int z) { + throw new AssertionError("Implemented By Mixin"); + } +} diff --git a/src/client/resources/illusionist.client.mixins.json b/src/client/resources/illusionist.client.mixins.json index f980eab..93a6082 100644 --- a/src/client/resources/illusionist.client.mixins.json +++ b/src/client/resources/illusionist.client.mixins.json @@ -1,11 +1,15 @@ { - "required": true, - "package": "stellarwitch7.illusionist.mixin.client", - "compatibilityLevel": "JAVA_21", - "client": [ - "RenderedChunkMixin" - ], - "injectors": { - "defaultRequire": 1 - } + "required": true, + "package": "stellarwitch7.illusionist.mixin.client", + "compatibilityLevel": "JAVA_21", + "client": [ + "sodium.ChunkBuilderMeshingTaskMixin", + "RenderedChunkMixin", + "sodium.ClonedChunkSectionMixin", + "sodium.LevelSliceAccessor" + ], + "plugin": "stellarwitch7.illusionist.mixin.client.IllusionistClientMixinConfigPlugin", + "injectors": { + "defaultRequire": 1 + } } diff --git a/src/main/java/stellarwitch7/illusionist/Illusionist.java b/src/main/java/stellarwitch7/illusionist/Illusionist.java index b88fa57..a7071cc 100644 --- a/src/main/java/stellarwitch7/illusionist/Illusionist.java +++ b/src/main/java/stellarwitch7/illusionist/Illusionist.java @@ -2,21 +2,22 @@ import net.fabricmc.api.ModInitializer; import net.minecraft.util.Identifier; -import stellarwitch7.illusionist.spell.trick.ModTricks; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import stellarwitch7.illusionist.debug.DebugHelper; +import stellarwitch7.illusionist.debug.item.SodiumDeathStick; +import stellarwitch7.illusionist.spell.trick.ModTricks; + public class Illusionist implements ModInitializer { public static final String MOD_ID = "illusionist"; public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); - @Override public void onInitialize() { // This code runs as soon as Minecraft is in a mod-load-ready state. // However, some things (like resources) may still be uninitialized. // Proceed with mild caution. - + DebugHelper.registerIfInDev(); ModTricks.register(); } diff --git a/src/main/java/stellarwitch7/illusionist/cca/ShadowDisguiseMapComponent.java b/src/main/java/stellarwitch7/illusionist/cca/ShadowDisguiseMapComponent.java index 3350f03..cf2cf44 100644 --- a/src/main/java/stellarwitch7/illusionist/cca/ShadowDisguiseMapComponent.java +++ b/src/main/java/stellarwitch7/illusionist/cca/ShadowDisguiseMapComponent.java @@ -21,7 +21,6 @@ public class ShadowDisguiseMapComponent implements AutoSyncedComponent { Endec.INT, MinecraftEndecs.ofRegistry(Registries.BLOCK) ).xmap(Int2ObjectOpenHashMap::new, map -> map).keyed("disguises", Int2ObjectOpenHashMap::new); - private volatile Int2ObjectOpenHashMap disguises = new Int2ObjectOpenHashMap<>(0); private final Chunk chunk; @@ -100,4 +99,9 @@ public int encodePos(int x, int y, int z) { var ye = y << 8; return ye | ze | xe; } + public Int2ObjectOpenHashMap toUpdateMap() { + Int2ObjectOpenHashMap copy = new Int2ObjectOpenHashMap<>(disguises.size()); + copy.putAll(disguises); + return copy; + } } diff --git a/src/main/java/stellarwitch7/illusionist/debug/DebugHelper.java b/src/main/java/stellarwitch7/illusionist/debug/DebugHelper.java new file mode 100644 index 0000000..3a9a2e0 --- /dev/null +++ b/src/main/java/stellarwitch7/illusionist/debug/DebugHelper.java @@ -0,0 +1,18 @@ +package stellarwitch7.illusionist.debug; + +import net.fabricmc.loader.api.FabricLoader; +import stellarwitch7.illusionist.debug.item.DebugItems; + +/** + * A helper class for conditionally registering debug features. + */ +public class DebugHelper { + /** + * Registers the debug features if the game is in a development environment. + */ + public static void registerIfInDev() { + if (!FabricLoader.getInstance().isDevelopmentEnvironment()) + return; + DebugItems.register(); + } +} \ No newline at end of file diff --git a/src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java b/src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java new file mode 100644 index 0000000..2cea007 --- /dev/null +++ b/src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java @@ -0,0 +1,30 @@ +package stellarwitch7.illusionist.debug.item; + +import dev.enjarai.trickster.Trickster; +import dev.enjarai.trickster.item.ModItems; +import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; +import net.minecraft.item.Item; +import net.minecraft.registry.Registries; +import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; + +import static stellarwitch7.illusionist.Illusionist.id; + +public class DebugItems { + public static final Item SODIUM_DEATH_STICK = + Registry.register( + Registries.ITEM, + id("sodium_death_stick"), + new SodiumDeathStick() + ); + + public static void register() { + // Register the item in the Trickster item group + ItemGroupEvents.modifyEntriesEvent( + RegistryKey.of(RegistryKeys.ITEM_GROUP, Trickster.id("trickster")) + ).register((entries) -> { + entries.add(DebugItems.SODIUM_DEATH_STICK); + }); + } +} diff --git a/src/main/java/stellarwitch7/illusionist/debug/item/SodiumDeathStick.java b/src/main/java/stellarwitch7/illusionist/debug/item/SodiumDeathStick.java new file mode 100644 index 0000000..3a8e3f5 --- /dev/null +++ b/src/main/java/stellarwitch7/illusionist/debug/item/SodiumDeathStick.java @@ -0,0 +1,53 @@ +package stellarwitch7.illusionist.debug.item; + +import dev.enjarai.trickster.net.ModNetworking; +import dev.enjarai.trickster.net.RebuildChunkPacket; +import dev.enjarai.trickster.particle.ModParticles; +import net.minecraft.block.Blocks; +import net.minecraft.item.Item; +import net.minecraft.item.ItemUsageContext; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.math.BlockPos; +import stellarwitch7.illusionist.Illusionist; +import stellarwitch7.illusionist.cca.ModChunkComponents; + +import java.util.Objects; + +/** + * A debug item that allows the player to set and clear a "funny state" on a block. + */ +public class SodiumDeathStick extends Item { + public SodiumDeathStick() { + super(new Item.Settings().maxCount(1)); + } + + @Override + public ActionResult useOnBlock(ItemUsageContext context) { + if (context.getWorld().isClient()) return ActionResult.SUCCESS; + var world = (ServerWorld) context.getWorld(); + var chunk = world.getChunk(context.getBlockPos()); + var player = Objects.requireNonNull(context.getPlayer()); + var map = ModChunkComponents.SHADOW_DISGUISE_MAP.get(chunk); + if (map.getFunnyState(context.getBlockPos()) != null) { + map.clearFunnyState(context.getBlockPos()); + updateShadow((ServerWorld) context.getWorld(), context.getBlockPos()); + // "Cleared funny state" + player.sendMessage(Text.translatable(Illusionist.MOD_ID + ".debug.message.clear_state"), true); + } else { + map.setFunnyState(context.getBlockPos(), Blocks.AMETHYST_BLOCK); + updateShadow((ServerWorld) context.getWorld(), context.getBlockPos()); + // "Set funny state" + player.sendMessage(Text.translatable(Illusionist.MOD_ID + ".debug.message.set_state"), true); + } + return ActionResult.SUCCESS; + } + + private static void updateShadow(ServerWorld world, BlockPos blockPos) { + ModNetworking.CHANNEL.serverHandle(world, blockPos).send(new RebuildChunkPacket(blockPos)); + + var particlePos = blockPos.toCenterPos(); + world.spawnParticles(ModParticles.PROTECTED_BLOCK, particlePos.x, particlePos.y, particlePos.z, 1, 0, 0, 0, 0); + } +} diff --git a/src/main/java/stellarwitch7/illusionist/mixin/WorldChunkMixin.java b/src/main/java/stellarwitch7/illusionist/mixin/WorldChunkMixin.java index e146365..29e60ad 100644 --- a/src/main/java/stellarwitch7/illusionist/mixin/WorldChunkMixin.java +++ b/src/main/java/stellarwitch7/illusionist/mixin/WorldChunkMixin.java @@ -8,21 +8,21 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.EmptyChunk; import net.minecraft.world.chunk.WorldChunk; -import stellarwitch7.illusionist.cca.ModChunkComponents; - +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import stellarwitch7.illusionist.cca.ModChunkComponents; @Mixin(WorldChunk.class) public abstract class WorldChunkMixin { @Shadow - final World world; + @Final + World world; public WorldChunkMixin(World world) { - this.world = world; } @Inject(method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Z)Lnet/minecraft/block/BlockState;", at = @At("HEAD")) @@ -31,7 +31,7 @@ private void dispelShadowBlock(BlockPos pos, BlockState newState, boolean moved, if (newState != world.getBlockState(pos)) { var serverWorld = world.getServer().getWorld(world.getRegistryKey()); - var chunk = ((WorldChunk)(Object)this); + var chunk = ((WorldChunk) (Object) this); if (chunk instanceof EmptyChunk) return; var map = ModChunkComponents.SHADOW_DISGUISE_MAP.get(chunk); diff --git a/src/main/resources/assets/illusionist/lang/en_us.yml b/src/main/resources/assets/illusionist/lang/en_us.yml index a2283fb..6175692 100644 --- a/src/main/resources/assets/illusionist/lang/en_us.yml +++ b/src/main/resources/assets/illusionist/lang/en_us.yml @@ -2,3 +2,11 @@ trickster: trick.illusionist: disguise_block: Shadow Ploy dispel_block_disguise: Revelation Ploy +illusionist: + debug: + message: + clear_state: Cleared funny state + set_state: Set funny state +item: + illusionist: + sodium_death_stick: State Switcher \ No newline at end of file diff --git a/src/main/resources/assets/illusionist/models/item/sodium_death_stick.json b/src/main/resources/assets/illusionist/models/item/sodium_death_stick.json new file mode 100644 index 0000000..5a63746 --- /dev/null +++ b/src/main/resources/assets/illusionist/models/item/sodium_death_stick.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/stick" +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index aa1ba95..5406274 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -48,6 +48,6 @@ }, "breaks": { "optifabric": "*", - "sodium": "*" + "sodium": ["<0.6.0-beta.2+mc1.21.1", ">0.6.0-beta.2+mc1.21.1"] } } From b52e7b95d04d09549c95fc243932cf80b8c1ab3d Mon Sep 17 00:00:00 2001 From: cputnam-a11y Date: Sun, 24 Nov 2024 15:37:52 -0600 Subject: [PATCH 2/6] Sodium Compat --- README.md | 2 +- .../client/sodium/ChunkBuilderMeshingTaskMixin.java | 10 ++-------- .../java/stellarwitch7/illusionist/Illusionist.java | 1 - .../illusionist/debug/item/DebugItems.java | 5 +---- 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 8e88ee3..b1f622c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Illusionist -An official add-on for [Trickster](https://github.com/enjarai/trickster) which re-adds the Shadow Ploy and Revelation Ploy which are no longer present in Trickster 2.0.0-beta.1 and onward. These ploys exist to interact with shadow blocks, which are, quite simply, a method of disguising a block as any other. Shadow blocks were removed from the main Trickster mod due to issues regarding Sodium support; as such, this add-on currently breaks with Sodium. +An official add-on for [Trickster](https://github.com/enjarai/trickster) which re-adds the Shadow Ploy and Revelation Ploy which are no longer present in Trickster 2.0.0-beta.1 and onward. These ploys exist to interact with shadow blocks, which are, quite simply, a method of disguising a block as any other. Shadow blocks were removed from the main Trickster mod due to issues regarding Sodium support; as such, this add-on currently breaks with most versions of Sodium. ![](https://i.enjarai.dev/u/iNOvDC.png) diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java index efff58b..561abe5 100644 --- a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java @@ -11,10 +11,7 @@ import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import org.joml.Vector3dc; -import org.spongepowered.asm.mixin.Debug; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import stellarwitch7.illusionist.accessor.ClonedChunkSectionAccessor; @@ -50,10 +47,7 @@ private BlockState wrapGetBlockState(LevelSlice instance, int x, int y, int z, O return state; } - private static int encodePos(BlockPos pos) { - return encodePos(pos.getX(), pos.getY(), pos.getZ()); - } - + @Unique private static int encodePos(int x, int y, int z) { var xe = x & 15; var ze = (z & 15) << 4; diff --git a/src/main/java/stellarwitch7/illusionist/Illusionist.java b/src/main/java/stellarwitch7/illusionist/Illusionist.java index a7071cc..f5d18f7 100644 --- a/src/main/java/stellarwitch7/illusionist/Illusionist.java +++ b/src/main/java/stellarwitch7/illusionist/Illusionist.java @@ -5,7 +5,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import stellarwitch7.illusionist.debug.DebugHelper; -import stellarwitch7.illusionist.debug.item.SodiumDeathStick; import stellarwitch7.illusionist.spell.trick.ModTricks; diff --git a/src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java b/src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java index 2cea007..e5901d1 100644 --- a/src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java +++ b/src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java @@ -1,7 +1,6 @@ package stellarwitch7.illusionist.debug.item; import dev.enjarai.trickster.Trickster; -import dev.enjarai.trickster.item.ModItems; import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; import net.minecraft.item.Item; import net.minecraft.registry.Registries; @@ -23,8 +22,6 @@ public static void register() { // Register the item in the Trickster item group ItemGroupEvents.modifyEntriesEvent( RegistryKey.of(RegistryKeys.ITEM_GROUP, Trickster.id("trickster")) - ).register((entries) -> { - entries.add(DebugItems.SODIUM_DEATH_STICK); - }); + ).register((entries) -> entries.add(DebugItems.SODIUM_DEATH_STICK)); } } From 0638ff57e72421722c6131866ecb6fb3ee2d36ae Mon Sep 17 00:00:00 2001 From: cputnam-a11y Date: Mon, 25 Nov 2024 21:31:52 -0600 Subject: [PATCH 3/6] Sodium Compat * Move to 0.6 * Move from 800 copies of component per tick to 50ish? * move from atomic fields to volatile fields --- gradle.properties | 4 +--- .../accessor/ClonedChunkSectionAccessor.java | 2 +- .../sodium/ChunkBuilderMeshingTaskMixin.java | 14 +++----------- .../client/sodium/ClonedChunkSectionMixin.java | 6 +++--- .../cca/ShadowDisguiseMapComponent.java | 17 ++++++++++++----- .../illusionist/mixin/WorldChunkMixin.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 7 files changed, 22 insertions(+), 25 deletions(-) diff --git a/gradle.properties b/gradle.properties index 035f588..5c75420 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,6 +24,4 @@ deps.floader=0.15.11 deps.fabric-api=0.100.1+1.21 deps.trickster=2.0.0-beta.1 deps.modmenu=11.0.1 -#deps.sodium.v0.5.9=dNHeFokL -#deps.sodium.v0.5.11=RncWhTxD -deps.sodium=CcIWi5Av +deps.sodium=b70slbHV diff --git a/src/client/java/stellarwitch7/illusionist/accessor/ClonedChunkSectionAccessor.java b/src/client/java/stellarwitch7/illusionist/accessor/ClonedChunkSectionAccessor.java index 78376f5..91b24fd 100644 --- a/src/client/java/stellarwitch7/illusionist/accessor/ClonedChunkSectionAccessor.java +++ b/src/client/java/stellarwitch7/illusionist/accessor/ClonedChunkSectionAccessor.java @@ -10,5 +10,5 @@ public interface ClonedChunkSectionAccessor { * Gets the shadow block states for this chunk section. * @return the shadow block states for this chunk section */ - AtomicReference> illusionist$getBlockStates(); + Int2ObjectOpenHashMap illusionist$getBlockStates(); } diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java index 561abe5..27e41b1 100644 --- a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java @@ -9,11 +9,11 @@ import net.caffeinemc.mods.sodium.client.world.LevelSlice; import net.caffeinemc.mods.sodium.client.world.cloned.ChunkRenderContext; import net.minecraft.block.BlockState; -import net.minecraft.util.math.BlockPos; import org.joml.Vector3dc; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import stellarwitch7.illusionist.accessor.ClonedChunkSectionAccessor; +import stellarwitch7.illusionist.cca.ShadowDisguiseMapComponent; @Debug(export = true) @Mixin(ChunkBuilderMeshingTask.class) @@ -41,17 +41,9 @@ private BlockState wrapGetBlockState(LevelSlice instance, int x, int y, int z, O @SuppressWarnings("DataFlowIssue") int relBlockZ = z - ((LevelSliceAccessor)(Object)instance).getOriginBlockZ(); var map = ((ClonedChunkSectionAccessor) this.renderContext.getSections()[LevelSliceAccessor.invokeGetLocalSectionIndex(relBlockX >> 4, relBlockY >> 4, relBlockZ >> 4)]).illusionist$getBlockStates(); - if (map.get().containsKey(encodePos(x, y, z))) { - state = map.get().get(encodePos(x, y, z)).getDefaultState(); + if (map.containsKey(ShadowDisguiseMapComponent.encodePos(x, y, z))) { + state = map.get(ShadowDisguiseMapComponent.encodePos(x, y, z)).getDefaultState(); } return state; } - - @Unique - private static int encodePos(int x, int y, int z) { - var xe = x & 15; - var ze = (z & 15) << 4; - var ye = y << 8; - return ye | ze | xe; - } } diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java index 77bb93d..fdc0c44 100644 --- a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java @@ -25,7 +25,7 @@ public class ClonedChunkSectionMixin implements ClonedChunkSectionAccessor { * stored as an atomic reference to allow for safe access in a {@link ChunkBuilderMeshingTask} */ @Unique - private final AtomicReference> blockStates = new AtomicReference<>(); + private volatile Int2ObjectOpenHashMap blockStates = null; /** * Stores a copy of a chunks shadow disguise map with this section, to safely access it later in a {@link ChunkBuilderMeshingTask } @@ -37,7 +37,7 @@ public class ClonedChunkSectionMixin implements ClonedChunkSectionAccessor { */ @Inject(method = "", at = @At("TAIL")) private void appendShadowDisguiseMap(World level, WorldChunk chunk, ChunkSection section, ChunkSectionPos pos, CallbackInfo ci) { - blockStates.set(ModChunkComponents.SHADOW_DISGUISE_MAP.get(chunk).toUpdateMap()); + this.blockStates = ModChunkComponents.SHADOW_DISGUISE_MAP.get(chunk).toUpdateMap(); } /** @@ -45,7 +45,7 @@ private void appendShadowDisguiseMap(World level, WorldChunk chunk, ChunkSection * @return the shadow block states for this chunk section */ @Override - public AtomicReference> illusionist$getBlockStates() { + public Int2ObjectOpenHashMap illusionist$getBlockStates() { return blockStates; } } diff --git a/src/main/java/stellarwitch7/illusionist/cca/ShadowDisguiseMapComponent.java b/src/main/java/stellarwitch7/illusionist/cca/ShadowDisguiseMapComponent.java index cf2cf44..89fa6cc 100644 --- a/src/main/java/stellarwitch7/illusionist/cca/ShadowDisguiseMapComponent.java +++ b/src/main/java/stellarwitch7/illusionist/cca/ShadowDisguiseMapComponent.java @@ -22,6 +22,7 @@ public class ShadowDisguiseMapComponent implements AutoSyncedComponent { MinecraftEndecs.ofRegistry(Registries.BLOCK) ).xmap(Int2ObjectOpenHashMap::new, map -> map).keyed("disguises", Int2ObjectOpenHashMap::new); private volatile Int2ObjectOpenHashMap disguises = new Int2ObjectOpenHashMap<>(0); + private volatile Int2ObjectOpenHashMap disguisesCache = null; private final Chunk chunk; public ShadowDisguiseMapComponent(Chunk chunk) { @@ -36,6 +37,7 @@ public void writeToNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLo @Override public void readFromNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) { disguises = tag.get(DISGUISES); + disguisesCache = null; } @Override @@ -46,6 +48,7 @@ public void writeSyncPacket(RegistryByteBuf buf, ServerPlayerEntity recipient) { @Override public void applySyncPacket(RegistryByteBuf buf) { disguises = buf.read(DISGUISES.endec()); + disguisesCache = null; } /** @@ -71,6 +74,7 @@ public BlockState getFunnyState(int x, int y, int z) { public boolean setFunnyState(BlockPos pos, Block block) { if (disguises.put(encodePos(pos), block) != block) { + disguisesCache = null; chunk.setNeedsSaving(true); ModChunkComponents.SHADOW_DISGUISE_MAP.sync(chunk); return true; @@ -82,6 +86,7 @@ public boolean setFunnyState(BlockPos pos, Block block) { public boolean clearFunnyState(BlockPos pos) { if (disguises.remove(encodePos(pos)) != null) { chunk.setNeedsSaving(true); + disguisesCache = null; ModChunkComponents.SHADOW_DISGUISE_MAP.sync(chunk); return true; } @@ -89,19 +94,21 @@ public boolean clearFunnyState(BlockPos pos) { return false; } - public int encodePos(BlockPos pos) { + public static int encodePos(BlockPos pos) { return encodePos(pos.getX(), pos.getY(), pos.getZ()); } - public int encodePos(int x, int y, int z) { + public static int encodePos(int x, int y, int z) { var xe = x & 15; var ze = (z & 15) << 4; var ye = y << 8; return ye | ze | xe; } public Int2ObjectOpenHashMap toUpdateMap() { - Int2ObjectOpenHashMap copy = new Int2ObjectOpenHashMap<>(disguises.size()); - copy.putAll(disguises); - return copy; + if (this.disguisesCache != null) + return disguisesCache; + this.disguisesCache = new Int2ObjectOpenHashMap<>(disguises.size()); + this.disguisesCache.putAll(disguises); + return this.disguisesCache; } } diff --git a/src/main/java/stellarwitch7/illusionist/mixin/WorldChunkMixin.java b/src/main/java/stellarwitch7/illusionist/mixin/WorldChunkMixin.java index 29e60ad..ca4b5b8 100644 --- a/src/main/java/stellarwitch7/illusionist/mixin/WorldChunkMixin.java +++ b/src/main/java/stellarwitch7/illusionist/mixin/WorldChunkMixin.java @@ -27,7 +27,7 @@ public WorldChunkMixin(World world) { @Inject(method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Z)Lnet/minecraft/block/BlockState;", at = @At("HEAD")) private void dispelShadowBlock(BlockPos pos, BlockState newState, boolean moved, CallbackInfoReturnable cir) { - if (world.isClient) return; + if (world.isClient()) return; if (newState != world.getBlockState(pos)) { var serverWorld = world.getServer().getWorld(world.getRegistryKey()); diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 5406274..eb053a1 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -48,6 +48,6 @@ }, "breaks": { "optifabric": "*", - "sodium": ["<0.6.0-beta.2+mc1.21.1", ">0.6.0-beta.2+mc1.21.1"] + "sodium": ["<0.6.0-beta.2+mc1.21.1 <0.6.0+mc1.21.1", ">0.6.0-beta.2+mc1.21.1 >0.6.0+mc1.21.1"] } } From 2899e8b5929944a7fffa00eaf9463c8567ba6344 Mon Sep 17 00:00:00 2001 From: cputnam-a11y Date: Tue, 26 Nov 2024 00:35:11 -0600 Subject: [PATCH 4/6] Sodium Compat * make version number human-readable --- gradle.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5c75420..74efbef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,4 +24,5 @@ deps.floader=0.15.11 deps.fabric-api=0.100.1+1.21 deps.trickster=2.0.0-beta.1 deps.modmenu=11.0.1 -deps.sodium=b70slbHV +deps.sodium=mc1.21.1-0.6.0-fabric + From 1f94f565db7d01f3d8d203e2eaaafc6815f10b5d Mon Sep 17 00:00:00 2001 From: cputnam-a11y Date: Tue, 26 Nov 2024 22:46:06 -0600 Subject: [PATCH 5/6] Sodium Compat * Fix Culling Issues * General Cleanup * Remove Debug Items and Components and Keybindings --- build.gradle | 2 +- .../illusionist/IllusionistClient.java | 2 - .../LevelSliceExt.java} | 38 ++++++++----- .../illusionist/debug/ClientDebugHelper.java | 16 ------ .../illusionist/debug/DebugKeybindings.java | 50 ---------------- .../IllusionistClientMixinConfigPlugin.java | 39 +------------ .../sodium/BlockOcclusionCacheMixin.java | 28 +++++++++ .../sodium/ChunkBuilderMeshingTaskMixin.java | 33 ++++++----- .../sodium/ClonedChunkSectionMixin.java | 18 +++--- .../client/sodium/LevelSliceInvoker.java | 23 ++++++++ .../mixin/client/sodium/LevelSliceMixin.java | 57 +++++++++++++++++++ .../util/DefaultedMixinConfigPlugin.java | 45 +++++++++++++++ .../resources/illusionist.client.mixins.json | 6 +- .../illusionist/Illusionist.java | 2 - .../illusionist/debug/DebugHelper.java | 18 ------ .../illusionist/debug/item/DebugItems.java | 27 --------- .../debug/item/SodiumDeathStick.java | 53 ----------------- .../illusionist/mixin/LivingEntityMixin.java | 20 +------ .../assets/illusionist/lang/en_us.yml | 10 +--- .../models/item/sodium_death_stick.json | 3 - 20 files changed, 212 insertions(+), 278 deletions(-) rename src/client/java/stellarwitch7/illusionist/{mixin/client/sodium/LevelSliceAccessor.java => accessor/LevelSliceExt.java} (52%) delete mode 100644 src/client/java/stellarwitch7/illusionist/debug/ClientDebugHelper.java delete mode 100644 src/client/java/stellarwitch7/illusionist/debug/DebugKeybindings.java create mode 100644 src/client/java/stellarwitch7/illusionist/mixin/client/sodium/BlockOcclusionCacheMixin.java create mode 100644 src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceInvoker.java create mode 100644 src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceMixin.java create mode 100644 src/client/java/stellarwitch7/illusionist/util/DefaultedMixinConfigPlugin.java delete mode 100644 src/main/java/stellarwitch7/illusionist/debug/DebugHelper.java delete mode 100644 src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java delete mode 100644 src/main/java/stellarwitch7/illusionist/debug/item/SodiumDeathStick.java delete mode 100644 src/main/resources/assets/illusionist/models/item/sodium_death_stick.json diff --git a/build.gradle b/build.gradle index a24bf1b..ffc102e 100644 --- a/build.gradle +++ b/build.gradle @@ -70,7 +70,7 @@ dependencies { modImplementation "com.terraformersmc:modmenu:${property('deps.modmenu')}" modCompileOnly "maven.modrinth:sodium:${property("deps.sodium")}" - modLocalRuntime "maven.modrinth:sodium:${property("deps.sodium")}" +// modLocalRuntime "maven.modrinth:sodium:${property("deps.sodium")}" } processResources { diff --git a/src/client/java/stellarwitch7/illusionist/IllusionistClient.java b/src/client/java/stellarwitch7/illusionist/IllusionistClient.java index 220cf87..0e0e09b 100644 --- a/src/client/java/stellarwitch7/illusionist/IllusionistClient.java +++ b/src/client/java/stellarwitch7/illusionist/IllusionistClient.java @@ -1,12 +1,10 @@ package stellarwitch7.illusionist; import net.fabricmc.api.ClientModInitializer; -import stellarwitch7.illusionist.debug.ClientDebugHelper; public class IllusionistClient implements ClientModInitializer { @Override public void onInitializeClient() { - ClientDebugHelper.registerIfInDev(); } } \ No newline at end of file diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceAccessor.java b/src/client/java/stellarwitch7/illusionist/accessor/LevelSliceExt.java similarity index 52% rename from src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceAccessor.java rename to src/client/java/stellarwitch7/illusionist/accessor/LevelSliceExt.java index 8f8137b..a235b90 100644 --- a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceAccessor.java +++ b/src/client/java/stellarwitch7/illusionist/accessor/LevelSliceExt.java @@ -1,34 +1,36 @@ -package stellarwitch7.illusionist.mixin.client.sodium; +package stellarwitch7.illusionist.accessor; -import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.caffeinemc.mods.sodium.client.world.cloned.ChunkRenderContext; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; +import net.minecraft.block.Block; +import net.minecraft.util.math.BlockPos; +import stellarwitch7.illusionist.mixin.client.sodium.LevelSliceInvoker; + +public interface LevelSliceExt { -@Mixin(LevelSlice.class) -public interface LevelSliceAccessor { /** * Gets the x-coordinate of the origin block of this level slice. + * * @return the x-coordinate of the origin block of this level slice */ - @Accessor(value = "originBlockX", remap = false) int getOriginBlockX(); /** * Gets the y-coordinate of the origin block of this level slice. + * * @return the y-coordinate of the origin block of this level slice */ - @Accessor(value = "originBlockY", remap = false) int getOriginBlockY(); /** * Gets the z-coordinate of the origin block of this level slice. + * * @return the z-coordinate of the origin block of this level slice */ - @Accessor(value = "originBlockZ", remap = false) int getOriginBlockZ(); + Int2ObjectOpenHashMap illusionist$getShadowBlockStates(int sectionIndex); + /** * Gets the local section index for the given coordinates * @@ -37,8 +39,18 @@ public interface LevelSliceAccessor { * @param z the z-coordinate of the section (different from the block z-coordinate) * @return the index of the section in the local section array (the same as the one in {@link ChunkRenderContext}) */ - @Invoker(value = "getLocalSectionIndex", remap = false) - static int invokeGetLocalSectionIndex(int x, int y, int z) { - throw new AssertionError("Implemented By Mixin"); + private static int invokeGetLocalSectionIndexInternal(int x, int y, int z) { + return LevelSliceInvoker.invokeGetLocalSectionIndex(x, y, z); + } + + private static int getLocalSectionIndexO(int x, int y, int z) { + return invokeGetLocalSectionIndexInternal(x >> 4, y >> 4, z >> 4); + } + + default int getLocalSectionIndexO1(int x, int y, int z) { + return getLocalSectionIndexO(x - getOriginBlockX(), y - getOriginBlockY(), z - getOriginBlockZ()); + } + default int getLocalSectionIndexO1(BlockPos pos) { + return getLocalSectionIndexO1(pos.getX(), pos.getY(), pos.getZ()); } } diff --git a/src/client/java/stellarwitch7/illusionist/debug/ClientDebugHelper.java b/src/client/java/stellarwitch7/illusionist/debug/ClientDebugHelper.java deleted file mode 100644 index 6c6c03c..0000000 --- a/src/client/java/stellarwitch7/illusionist/debug/ClientDebugHelper.java +++ /dev/null @@ -1,16 +0,0 @@ -package stellarwitch7.illusionist.debug; - -import net.fabricmc.loader.api.FabricLoader; -/** - * A helper class for conditionally registering debug features. - */ -public class ClientDebugHelper { - /** - * Registers the debug features if the game is in a development environment. - */ - public static void registerIfInDev() { - if (!FabricLoader.getInstance().isDevelopmentEnvironment()) - return; - DebugKeybindings.register(); - } -} diff --git a/src/client/java/stellarwitch7/illusionist/debug/DebugKeybindings.java b/src/client/java/stellarwitch7/illusionist/debug/DebugKeybindings.java deleted file mode 100644 index 8ef5384..0000000 --- a/src/client/java/stellarwitch7/illusionist/debug/DebugKeybindings.java +++ /dev/null @@ -1,50 +0,0 @@ -package stellarwitch7.illusionist.debug; - -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; -import net.minecraft.block.BlockState; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.option.KeyBinding; -import net.minecraft.client.util.InputUtil; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.text.Text; -import net.minecraft.util.hit.BlockHitResult; -import stellarwitch7.illusionist.cca.ModChunkComponents; - -import java.util.Objects; - -public class DebugKeybindings { - public static final KeyBinding LOG_FUNNY_STATE = KeyBindingHelper.registerKeyBinding( - new KeyBinding("key.illusionist.log", InputUtil.UNKNOWN_KEY.getCode(), "key.categories.illusionist") - ); - - static { - ClientTickEvents.END_CLIENT_TICK.register(DebugKeybindings::onClientTick); - } - public static void register() { - - } - private static void onClientTick(MinecraftClient client) { - // only act if the keybinding was pressed - if (LOG_FUNNY_STATE.wasPressed()) { - // consume all remaining presses - //noinspection StatementWithEmptyBody - while (LOG_FUNNY_STATE.wasPressed()) ; - // if the crosshair target is not a block hit result, we are not interested in it, return - if (!(client.crosshairTarget instanceof BlockHitResult hitResult)) { - return; - } - // if world is null, we have bigger things to worry about - // the current world on the client (should be the one that is rendering) - var world = Objects.requireNonNull(client.world); - // the player - var player = Objects.requireNonNull(client.player); - // get the disguise map for the chunk that the block is in - var map = ModChunkComponents.SHADOW_DISGUISE_MAP.get(world.getChunk(hitResult.getBlockPos())); - // get the funny state of the block at the hit position - BlockState funnyState = map.getFunnyState(hitResult.getBlockPos()); - // send a message to the player with the funny state - player.sendMessage(Text.of("Funny state: " + funnyState), false); - } - } -} diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/IllusionistClientMixinConfigPlugin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/IllusionistClientMixinConfigPlugin.java index a69ecf7..0287180 100644 --- a/src/client/java/stellarwitch7/illusionist/mixin/client/IllusionistClientMixinConfigPlugin.java +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/IllusionistClientMixinConfigPlugin.java @@ -1,46 +1,11 @@ package stellarwitch7.illusionist.mixin.client; import net.fabricmc.loader.api.FabricLoader; -import org.objectweb.asm.tree.ClassNode; -import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; -import org.spongepowered.asm.mixin.extensibility.IMixinInfo; - -import java.util.List; -import java.util.Set; - -public class IllusionistClientMixinConfigPlugin implements IMixinConfigPlugin { - @Override - public void onLoad(String mixinPackage) { - - } - - @Override - public String getRefMapperConfig() { - return null; - } +import stellarwitch7.illusionist.util.DefaultedMixinConfigPlugin; +public class IllusionistClientMixinConfigPlugin implements DefaultedMixinConfigPlugin { @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { return !mixinClassName.contains("sodium") || FabricLoader.getInstance().isModLoaded("sodium"); } - - @Override - public void acceptTargets(Set myTargets, Set otherTargets) { - - } - - @Override - public List getMixins() { - return null; - } - - @Override - public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { - - } - - @Override - public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { - - } } diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/BlockOcclusionCacheMixin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/BlockOcclusionCacheMixin.java new file mode 100644 index 0000000..796953d --- /dev/null +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/BlockOcclusionCacheMixin.java @@ -0,0 +1,28 @@ +package stellarwitch7.illusionist.mixin.client.sodium; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockView; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import stellarwitch7.illusionist.accessor.LevelSliceExt; + +import static stellarwitch7.illusionist.cca.ShadowDisguiseMapComponent.encodePos; +@Mixin(value = BlockOcclusionCache.class, remap = false) +public class BlockOcclusionCacheMixin { + @WrapOperation(method = "shouldDrawSide", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/BlockView;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;")) + private BlockState wrapGetBlockState(BlockView instance, BlockPos blockPos, Operation original) { + if (instance instanceof LevelSliceExt accessor) { + int sectionIndex = accessor.getLocalSectionIndexO1(blockPos); + var map = accessor.illusionist$getShadowBlockStates(sectionIndex); + var posIndex = encodePos(blockPos); + if (map != null && map.containsKey(posIndex)) { + return map.get(posIndex).getDefaultState(); + } + } + return original.call(instance, blockPos); + } +} diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java index 27e41b1..251d77a 100644 --- a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java @@ -10,10 +10,15 @@ import net.caffeinemc.mods.sodium.client.world.cloned.ChunkRenderContext; import net.minecraft.block.BlockState; import org.joml.Vector3dc; -import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.Debug; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import stellarwitch7.illusionist.accessor.ClonedChunkSectionAccessor; -import stellarwitch7.illusionist.cca.ShadowDisguiseMapComponent; +import stellarwitch7.illusionist.accessor.LevelSliceExt; + +import static stellarwitch7.illusionist.cca.ShadowDisguiseMapComponent.encodePos; @Debug(export = true) @Mixin(ChunkBuilderMeshingTask.class) @@ -26,23 +31,17 @@ public ChunkBuilderMeshingTaskMixin(RenderSection render, int time, Vector3dc ab super(render, time, absoluteCameraPos); } - @WrapOperation( - method = "execute(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lnet/caffeinemc/mods/sodium/client/util/task/CancellationToken;)Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;", - at = @At( - value = "INVOKE", - target = "Lnet/caffeinemc/mods/sodium/client/world/LevelSlice;getBlockState(III)Lnet/minecraft/block/BlockState;" - ) - ) + @WrapOperation(method = "execute(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lnet/caffeinemc/mods/sodium/client/util/task/CancellationToken;)Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/world/LevelSlice;getBlockState(III)Lnet/minecraft/block/BlockState;")) private BlockState wrapGetBlockState(LevelSlice instance, int x, int y, int z, Operation original) { BlockState state = original.call(instance, x, y, z); - int relBlockX = x - ((LevelSliceAccessor)(Object)instance).getOriginBlockX(); - @SuppressWarnings("DataFlowIssue") - int relBlockY = y - ((LevelSliceAccessor)(Object)instance).getOriginBlockY(); - @SuppressWarnings("DataFlowIssue") - int relBlockZ = z - ((LevelSliceAccessor)(Object)instance).getOriginBlockZ(); - var map = ((ClonedChunkSectionAccessor) this.renderContext.getSections()[LevelSliceAccessor.invokeGetLocalSectionIndex(relBlockX >> 4, relBlockY >> 4, relBlockZ >> 4)]).illusionist$getBlockStates(); - if (map.containsKey(ShadowDisguiseMapComponent.encodePos(x, y, z))) { - state = map.get(ShadowDisguiseMapComponent.encodePos(x, y, z)).getDefaultState(); + //noinspection ConstantValue + if ((Object) instance instanceof LevelSliceExt accessor) { + int localSectionIndex = accessor.getLocalSectionIndexO1(x, y, z); + var map = ((ClonedChunkSectionAccessor) this.renderContext.getSections()[localSectionIndex]).illusionist$getBlockStates(); + int posIndex = encodePos(x, y, z); + if (map.containsKey(posIndex)) { + state = map.get(posIndex).getDefaultState(); + } } return state; } diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java index fdc0c44..8e24a98 100644 --- a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/ClonedChunkSectionMixin.java @@ -1,8 +1,8 @@ package stellarwitch7.illusionist.mixin.client.sodium; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import net.caffeinemc.mods.sodium.client.world.cloned.ClonedChunkSection; import net.caffeinemc.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask; +import net.caffeinemc.mods.sodium.client.world.cloned.ClonedChunkSection; import net.minecraft.block.Block; import net.minecraft.util.math.ChunkSectionPos; import net.minecraft.world.World; @@ -16,24 +16,23 @@ import stellarwitch7.illusionist.accessor.ClonedChunkSectionAccessor; import stellarwitch7.illusionist.cca.ModChunkComponents; -import java.util.concurrent.atomic.AtomicReference; - -@Mixin(ClonedChunkSection.class) +@Mixin(value = ClonedChunkSection.class, remap = false) public class ClonedChunkSectionMixin implements ClonedChunkSectionAccessor { /** * The shadow block states for this chunk section. - * stored as an atomic reference to allow for safe access in a {@link ChunkBuilderMeshingTask} + * volatile to allow for safe access in a {@link ChunkBuilderMeshingTask} */ @Unique private volatile Int2ObjectOpenHashMap blockStates = null; /** * Stores a copy of a chunks shadow disguise map with this section, to safely access it later in a {@link ChunkBuilderMeshingTask } - * @param level the world currently rendering - * @param chunk the chunk sodium is copying this section from + * + * @param level the world currently rendering + * @param chunk the chunk sodium is copying this section from * @param section the chunk section sodium is copying - * @param pos the position of the chunk section sodium is copying - * @param ci no explanation needed + * @param pos the position of the chunk section sodium is copying + * @param ci no explanation needed */ @Inject(method = "", at = @At("TAIL")) private void appendShadowDisguiseMap(World level, WorldChunk chunk, ChunkSection section, ChunkSectionPos pos, CallbackInfo ci) { @@ -42,6 +41,7 @@ private void appendShadowDisguiseMap(World level, WorldChunk chunk, ChunkSection /** * Gets the shadow block states for this chunk section. + * * @return the shadow block states for this chunk section */ @Override diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceInvoker.java b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceInvoker.java new file mode 100644 index 0000000..d932d3c --- /dev/null +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceInvoker.java @@ -0,0 +1,23 @@ +package stellarwitch7.illusionist.mixin.client.sodium; + +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.caffeinemc.mods.sodium.client.world.cloned.ChunkRenderContext; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(value = LevelSlice.class, remap = false) +public interface LevelSliceInvoker { + + /** + * Gets the local section index for the given coordinates + * + * @param x the x-coordinate of the section (different from the block x-coordinate) + * @param y the y-coordinate of the section (different from the block y-coordinate) + * @param z the z-coordinate of the section (different from the block z-coordinate) + * @return the index of the section in the local section array (the same as the one in {@link ChunkRenderContext}) + */ + @Invoker(value = "getLocalSectionIndex") + static int invokeGetLocalSectionIndex(int x, int y, int z) { + throw new AssertionError("Implemented By Mixin"); + } +} diff --git a/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceMixin.java b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceMixin.java new file mode 100644 index 0000000..80af9da --- /dev/null +++ b/src/client/java/stellarwitch7/illusionist/mixin/client/sodium/LevelSliceMixin.java @@ -0,0 +1,57 @@ +package stellarwitch7.illusionist.mixin.client.sodium; + +import com.llamalad7.mixinextras.sugar.Local; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.caffeinemc.mods.sodium.client.world.cloned.ChunkRenderContext; +import net.caffeinemc.mods.sodium.client.world.cloned.ClonedChunkSection; +import net.minecraft.block.Block; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import stellarwitch7.illusionist.accessor.ClonedChunkSectionAccessor; +import stellarwitch7.illusionist.accessor.LevelSliceExt; + +@Mixin(value = LevelSlice.class, remap = false) +public abstract class LevelSliceMixin implements LevelSliceExt { + @Accessor(value = "originBlockX") + public abstract int getOriginBlockX(); + + @Accessor(value = "originBlockY") + public abstract int getOriginBlockY(); + + @Accessor(value = "originBlockZ") + public abstract int getOriginBlockZ(); + + @Override + public Int2ObjectOpenHashMap illusionist$getShadowBlockStates(int sectionIndex) { + return shadowBlockStates[sectionIndex]; + } + + @Shadow + @Final + private static int SECTION_ARRAY_SIZE; + @Unique + @SuppressWarnings("unchecked") + private final Int2ObjectOpenHashMap[] shadowBlockStates = new Int2ObjectOpenHashMap[SECTION_ARRAY_SIZE]; + + @Inject(method = "copySectionData", at = @At("TAIL")) + private void copySectionData(ChunkRenderContext context, int sectionIndex, CallbackInfo ci, @Local ClonedChunkSection section) { + shadowBlockStates[sectionIndex] = ((ClonedChunkSectionAccessor) section).illusionist$getBlockStates(); + } + + /** + * ties into the for loop in the reset method to reset the shadow block states for each section + * + * @param sectionIndex the current section index in iteration + */ + @Inject(method = "reset", at = @At(value = "TAIL")) + private void reset(CallbackInfo ci, @Local int sectionIndex) { + shadowBlockStates[sectionIndex] = null; + } +} diff --git a/src/client/java/stellarwitch7/illusionist/util/DefaultedMixinConfigPlugin.java b/src/client/java/stellarwitch7/illusionist/util/DefaultedMixinConfigPlugin.java new file mode 100644 index 0000000..7ec0f37 --- /dev/null +++ b/src/client/java/stellarwitch7/illusionist/util/DefaultedMixinConfigPlugin.java @@ -0,0 +1,45 @@ +package stellarwitch7.illusionist.util; + +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.util.List; +import java.util.Set; + +public interface DefaultedMixinConfigPlugin extends IMixinConfigPlugin { + @Override + default void onLoad(String mixinPackage) { + + } + + @Override + default String getRefMapperConfig() { + return null; + } + + @Override + default boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + return true; + } + + @Override + default void acceptTargets(Set myTargets, Set otherTargets) { + + } + + @Override + default List getMixins() { + return null; + } + + @Override + default void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } + + @Override + default void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } +} diff --git a/src/client/resources/illusionist.client.mixins.json b/src/client/resources/illusionist.client.mixins.json index 93a6082..ebe429d 100644 --- a/src/client/resources/illusionist.client.mixins.json +++ b/src/client/resources/illusionist.client.mixins.json @@ -3,10 +3,12 @@ "package": "stellarwitch7.illusionist.mixin.client", "compatibilityLevel": "JAVA_21", "client": [ - "sodium.ChunkBuilderMeshingTaskMixin", "RenderedChunkMixin", + "sodium.ChunkBuilderMeshingTaskMixin", "sodium.ClonedChunkSectionMixin", - "sodium.LevelSliceAccessor" + "sodium.LevelSliceInvoker", + "sodium.BlockOcclusionCacheMixin", + "sodium.LevelSliceMixin" ], "plugin": "stellarwitch7.illusionist.mixin.client.IllusionistClientMixinConfigPlugin", "injectors": { diff --git a/src/main/java/stellarwitch7/illusionist/Illusionist.java b/src/main/java/stellarwitch7/illusionist/Illusionist.java index f5d18f7..799c42f 100644 --- a/src/main/java/stellarwitch7/illusionist/Illusionist.java +++ b/src/main/java/stellarwitch7/illusionist/Illusionist.java @@ -4,7 +4,6 @@ import net.minecraft.util.Identifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import stellarwitch7.illusionist.debug.DebugHelper; import stellarwitch7.illusionist.spell.trick.ModTricks; @@ -16,7 +15,6 @@ public void onInitialize() { // This code runs as soon as Minecraft is in a mod-load-ready state. // However, some things (like resources) may still be uninitialized. // Proceed with mild caution. - DebugHelper.registerIfInDev(); ModTricks.register(); } diff --git a/src/main/java/stellarwitch7/illusionist/debug/DebugHelper.java b/src/main/java/stellarwitch7/illusionist/debug/DebugHelper.java deleted file mode 100644 index 3a9a2e0..0000000 --- a/src/main/java/stellarwitch7/illusionist/debug/DebugHelper.java +++ /dev/null @@ -1,18 +0,0 @@ -package stellarwitch7.illusionist.debug; - -import net.fabricmc.loader.api.FabricLoader; -import stellarwitch7.illusionist.debug.item.DebugItems; - -/** - * A helper class for conditionally registering debug features. - */ -public class DebugHelper { - /** - * Registers the debug features if the game is in a development environment. - */ - public static void registerIfInDev() { - if (!FabricLoader.getInstance().isDevelopmentEnvironment()) - return; - DebugItems.register(); - } -} \ No newline at end of file diff --git a/src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java b/src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java deleted file mode 100644 index e5901d1..0000000 --- a/src/main/java/stellarwitch7/illusionist/debug/item/DebugItems.java +++ /dev/null @@ -1,27 +0,0 @@ -package stellarwitch7.illusionist.debug.item; - -import dev.enjarai.trickster.Trickster; -import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; -import net.minecraft.item.Item; -import net.minecraft.registry.Registries; -import net.minecraft.registry.Registry; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryKeys; - -import static stellarwitch7.illusionist.Illusionist.id; - -public class DebugItems { - public static final Item SODIUM_DEATH_STICK = - Registry.register( - Registries.ITEM, - id("sodium_death_stick"), - new SodiumDeathStick() - ); - - public static void register() { - // Register the item in the Trickster item group - ItemGroupEvents.modifyEntriesEvent( - RegistryKey.of(RegistryKeys.ITEM_GROUP, Trickster.id("trickster")) - ).register((entries) -> entries.add(DebugItems.SODIUM_DEATH_STICK)); - } -} diff --git a/src/main/java/stellarwitch7/illusionist/debug/item/SodiumDeathStick.java b/src/main/java/stellarwitch7/illusionist/debug/item/SodiumDeathStick.java deleted file mode 100644 index 3a8e3f5..0000000 --- a/src/main/java/stellarwitch7/illusionist/debug/item/SodiumDeathStick.java +++ /dev/null @@ -1,53 +0,0 @@ -package stellarwitch7.illusionist.debug.item; - -import dev.enjarai.trickster.net.ModNetworking; -import dev.enjarai.trickster.net.RebuildChunkPacket; -import dev.enjarai.trickster.particle.ModParticles; -import net.minecraft.block.Blocks; -import net.minecraft.item.Item; -import net.minecraft.item.ItemUsageContext; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.text.Text; -import net.minecraft.util.ActionResult; -import net.minecraft.util.math.BlockPos; -import stellarwitch7.illusionist.Illusionist; -import stellarwitch7.illusionist.cca.ModChunkComponents; - -import java.util.Objects; - -/** - * A debug item that allows the player to set and clear a "funny state" on a block. - */ -public class SodiumDeathStick extends Item { - public SodiumDeathStick() { - super(new Item.Settings().maxCount(1)); - } - - @Override - public ActionResult useOnBlock(ItemUsageContext context) { - if (context.getWorld().isClient()) return ActionResult.SUCCESS; - var world = (ServerWorld) context.getWorld(); - var chunk = world.getChunk(context.getBlockPos()); - var player = Objects.requireNonNull(context.getPlayer()); - var map = ModChunkComponents.SHADOW_DISGUISE_MAP.get(chunk); - if (map.getFunnyState(context.getBlockPos()) != null) { - map.clearFunnyState(context.getBlockPos()); - updateShadow((ServerWorld) context.getWorld(), context.getBlockPos()); - // "Cleared funny state" - player.sendMessage(Text.translatable(Illusionist.MOD_ID + ".debug.message.clear_state"), true); - } else { - map.setFunnyState(context.getBlockPos(), Blocks.AMETHYST_BLOCK); - updateShadow((ServerWorld) context.getWorld(), context.getBlockPos()); - // "Set funny state" - player.sendMessage(Text.translatable(Illusionist.MOD_ID + ".debug.message.set_state"), true); - } - return ActionResult.SUCCESS; - } - - private static void updateShadow(ServerWorld world, BlockPos blockPos) { - ModNetworking.CHANNEL.serverHandle(world, blockPos).send(new RebuildChunkPacket(blockPos)); - - var particlePos = blockPos.toCenterPos(); - world.spawnParticles(ModParticles.PROTECTED_BLOCK, particlePos.x, particlePos.y, particlePos.z, 1, 0, 0, 0, 0); - } -} diff --git a/src/main/java/stellarwitch7/illusionist/mixin/LivingEntityMixin.java b/src/main/java/stellarwitch7/illusionist/mixin/LivingEntityMixin.java index eadaa50..5ddcc70 100644 --- a/src/main/java/stellarwitch7/illusionist/mixin/LivingEntityMixin.java +++ b/src/main/java/stellarwitch7/illusionist/mixin/LivingEntityMixin.java @@ -1,42 +1,24 @@ package stellarwitch7.illusionist.mixin; import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import dev.enjarai.trickster.ModAttachments; -import dev.enjarai.trickster.cca.ModEntityComponents; -import dev.enjarai.trickster.spell.ItemTriggerHelper; -import dev.enjarai.trickster.spell.fragment.NumberFragment; -import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LimbAnimator; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.attribute.AttributeContainer; -import net.minecraft.entity.attribute.EntityAttributeModifier; -import net.minecraft.entity.attribute.EntityAttributes; -import net.minecraft.entity.damage.DamageSource; -import net.minecraft.entity.damage.DamageTracker; import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.sound.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.EmptyChunk; -import net.minecraft.world.event.GameEvent; -import stellarwitch7.illusionist.cca.ModChunkComponents; - import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import stellarwitch7.illusionist.cca.ModChunkComponents; @Mixin(LivingEntity.class) public abstract class LivingEntityMixin extends Entity { diff --git a/src/main/resources/assets/illusionist/lang/en_us.yml b/src/main/resources/assets/illusionist/lang/en_us.yml index 6175692..18c6e88 100644 --- a/src/main/resources/assets/illusionist/lang/en_us.yml +++ b/src/main/resources/assets/illusionist/lang/en_us.yml @@ -1,12 +1,4 @@ trickster: trick.illusionist: disguise_block: Shadow Ploy - dispel_block_disguise: Revelation Ploy -illusionist: - debug: - message: - clear_state: Cleared funny state - set_state: Set funny state -item: - illusionist: - sodium_death_stick: State Switcher \ No newline at end of file + dispel_block_disguise: Revelation Ploy \ No newline at end of file diff --git a/src/main/resources/assets/illusionist/models/item/sodium_death_stick.json b/src/main/resources/assets/illusionist/models/item/sodium_death_stick.json deleted file mode 100644 index 5a63746..0000000 --- a/src/main/resources/assets/illusionist/models/item/sodium_death_stick.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "parent": "minecraft:item/stick" -} \ No newline at end of file From 69761219798bc4f0fb61a66cfb52baffbde351f6 Mon Sep 17 00:00:00 2001 From: Aurora Dawn <131844170+StellarWitch7@users.noreply.github.com> Date: Wed, 27 Nov 2024 20:39:58 -0500 Subject: [PATCH 6/6] Bump Trickster dependency and notice issues ;-; --- build.gradle | 4 +--- gradle.properties | 4 ++-- src/main/java/stellarwitch7/illusionist/Illusionist.java | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index ffc102e..d1888e4 100644 --- a/build.gradle +++ b/build.gradle @@ -68,9 +68,7 @@ dependencies { modImplementation "dev.enjarai:trickster:${property('deps.trickster')}" modImplementation "com.terraformersmc:modmenu:${property('deps.modmenu')}" - - modCompileOnly "maven.modrinth:sodium:${property("deps.sodium")}" -// modLocalRuntime "maven.modrinth:sodium:${property("deps.sodium")}" + modClientCompileOnly modLocalRuntime("maven.modrinth:sodium:${property("deps.sodium")}") } processResources { diff --git a/gradle.properties b/gradle.properties index 74efbef..5fe0c47 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,7 +22,7 @@ deps.floader=0.15.11 # Dependencies deps.fabric-api=0.100.1+1.21 -deps.trickster=2.0.0-beta.1 +deps.trickster=2.0.0-beta.7 deps.modmenu=11.0.1 -deps.sodium=mc1.21.1-0.6.0-fabric +deps.sodium=mc1.21.1-0.6.0-fabric diff --git a/src/main/java/stellarwitch7/illusionist/Illusionist.java b/src/main/java/stellarwitch7/illusionist/Illusionist.java index 799c42f..36f7495 100644 --- a/src/main/java/stellarwitch7/illusionist/Illusionist.java +++ b/src/main/java/stellarwitch7/illusionist/Illusionist.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import stellarwitch7.illusionist.spell.trick.ModTricks; - +// testing spell: `YwqT9+bf4MHEysjIz8DAwMwIJBgYGRlBwgwuDlzIYlrPvmiCxD9wNSxnYmTDVH6AAV2MIwTEYWBihJKMzOgqAngcOpFVYLMwwMOhk5GRE10rowsTKzmOwGUd2EwGByL1AwC+fb+wOgEAAA==` public class Illusionist implements ModInitializer { public static final String MOD_ID = "illusionist"; public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);