Indium suppor + github runner #7
34
.github/workflows/publish.yml
vendored
Normal file
34
.github/workflows/publish.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
name: Publish mod on Modrinth
|
||||
|
||||
on: [ push, workflow_dispatch ]
|
||||
|
||||
env:
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
- name: validate gradle wrapper
|
||||
uses: https://github.com/gradle/wrapper-validation-action@v1
|
||||
- name: setup jdk
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: 'oracle'
|
||||
- name: make gradle wrapper executable
|
||||
if: ${{ runner.os != 'Windows' }}
|
||||
run: |
|
||||
chmod +x ./gradlew
|
||||
touch local.properties
|
||||
- name: Generate data
|
||||
run: ./gradlew runDatagen
|
||||
- name: Publish Modrinth
|
||||
run: ./gradlew modrinth
|
||||
env:
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
37
build.gradle
37
build.gradle
@ -3,6 +3,7 @@ import fr.altarik.CreateTag
|
||||
|
||||
|
||||
plugins {
|
||||
id "com.modrinth.minotaur" version "2.+"
|
||||
id 'fabric-loom' version '1.5-SNAPSHOT'
|
||||
id 'maven-publish'
|
||||
}
|
||||
@ -72,6 +73,17 @@ repositories {
|
||||
maven {
|
||||
url "https://maven.resourcefulbees.com/repository/maven-public/"
|
||||
}
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven {
|
||||
name = "Modrinth"
|
||||
url = "https://api.modrinth.com/maven"
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup "maven.modrinth"
|
||||
}
|
||||
}
|
||||
mavenCentral()
|
||||
|
||||
// Add repositories to retrieve artifacts from in here.
|
||||
@ -88,6 +100,12 @@ dependencies {
|
||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
|
||||
// Indium and sodium for sodium support
|
||||
modCompileOnly "maven.modrinth:indium:${project.indium_version}+mc${project.minecraft_version}"
|
||||
modCompileOnly "maven.modrinth:sodium:mc${project.minecraft_version}-${project.sodium_version}"
|
||||
// modRuntimeOnly "maven.modrinth:indium:${project.indium_version}+mc${project.minecraft_version}"
|
||||
// modRuntimeOnly "maven.modrinth:sodium:mc${project.minecraft_version}-${project.sodium_version}"
|
||||
|
||||
// Athena for connected texture
|
||||
modCompileOnly "earth.terrarium.athena:athena-fabric-${project.minecraft_version}:${project.athena_version}"
|
||||
modRuntimeOnly "earth.terrarium.athena:athena-fabric-${project.minecraft_version}:${project.athena_version}"
|
||||
@ -106,6 +124,8 @@ processResources {
|
||||
inputs.property "loader_version", project.loader_version
|
||||
inputs.property "mod_id", project.mod_id
|
||||
inputs.property "athena_version", project.athena_version
|
||||
inputs.property "indium_version", project.indium_version
|
||||
inputs.property "sodium_version", project.sodium_version
|
||||
filteringCharset "UTF-8"
|
||||
|
||||
filesMatching("fabric.mod.json") {
|
||||
@ -171,6 +191,23 @@ publishing {
|
||||
}
|
||||
}
|
||||
|
||||
// configure modrinth publication
|
||||
modrinth {
|
||||
token = getEnv("MODRINTH_TOKEN", local.getProperty("modrinth_token"))
|
||||
projectId = project.modrinth_id
|
||||
versionNumber = project.mod_version
|
||||
versionName = "${project.archives_base_name} ${project.mod_version}"
|
||||
versionType = project.mod_version.endsWith('SNAPSHOT') ? 'beta' : 'release'
|
||||
uploadFile = remapJar
|
||||
gameVersions = [project.minecraft_version]
|
||||
loaders = ["fabric"]
|
||||
dependencies {
|
||||
required.project "fabric-api"
|
||||
optional.version "b1ZV3DIJ", "${project.athena_version}"
|
||||
optional.version "Orvt0mRa", "${project.indium_version}+mc${project.minecraft_version}"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("reportToDiscord", ReportDiscord) {
|
||||
config.set(reportConfig)
|
||||
}
|
||||
|
@ -8,7 +8,8 @@ yarn_mappings=1.20.4+build.3
|
||||
loader_version=0.15.6
|
||||
|
||||
# Mod Properties
|
||||
mod_version = 1.3
|
||||
modrinth_id = jCpoCBpn
|
||||
mod_version = 1.3.1
|
||||
maven_group = fr.adrien1106
|
||||
archives_base_name = ReFramed
|
||||
mod_id = reframed
|
||||
@ -21,3 +22,5 @@ git_owner=Altarik
|
||||
git_repo=ReFramed
|
||||
|
||||
athena_version=3.3.0
|
||||
sodium_version=0.5.8
|
||||
indium_version=1.0.30
|
||||
|
@ -25,7 +25,7 @@ import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* TODO self culling, fix other models, better connected textures
|
||||
* TODO self culling, fix other models, better connected textures, preload items, walking sound, state replacement
|
||||
*/
|
||||
public class ReFramed implements ModInitializer {
|
||||
public static final String MODID = "reframed";
|
||||
|
@ -2,6 +2,8 @@ package fr.adrien1106.reframed.mixin;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
@ -12,9 +14,17 @@ import java.util.function.Supplier;
|
||||
|
||||
public class CompatMixinPlugin implements IMixinConfigPlugin {
|
||||
|
||||
private static final FabricLoader LOADER = FabricLoader.getInstance();
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("ReFramed MIXIN");
|
||||
private static final List<String> COMPAT_MOD = List.of("athena", "indium", "sodium");
|
||||
private static final Map<String, Supplier<Boolean>> CONDITIONS = Map.of(
|
||||
"fr.adrien1106.reframed.mixin.compat.AthenaBakedModelMixin", () -> FabricLoader.getInstance().isModLoaded("athena"),
|
||||
"fr.adrien1106.reframed.mixin.compat.AthenaWrappedGetterMixin", () -> FabricLoader.getInstance().isModLoaded("athena")
|
||||
"fr.adrien1106.reframed.mixin.compat.AthenaBakedModelMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(0)),
|
||||
"fr.adrien1106.reframed.mixin.compat.AthenaWrappedGetterMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(0)),
|
||||
"fr.adrien1106.reframed.mixin.render.TerrainRenderContextMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)),
|
||||
"fr.adrien1106.reframed.mixin.compat.IndiumTerrainRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)),
|
||||
"fr.adrien1106.reframed.mixin.render.BlockRenderInfoMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)),
|
||||
"fr.adrien1106.reframed.mixin.compat.IndiumTerrainBlockRenderInfoMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)),
|
||||
"fr.adrien1106.reframed.mixin.compat.SodiumBlockOcclusionCacheMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(2))
|
||||
);
|
||||
|
||||
|
||||
@ -44,12 +54,16 @@ public class CompatMixinPlugin implements IMixinConfigPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
public void preApply(String target_class_name, ClassNode target_class, String mixin_class_name, IMixinInfo mixin_info) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
|
||||
public void postApply(String target_class, ClassNode target, String mixin_class, IMixinInfo mixin_info) {
|
||||
String mixin_class_name = mixin_class.substring(mixin_class.lastIndexOf('.') + 1);
|
||||
COMPAT_MOD.forEach(mod -> {
|
||||
if (mixin_class_name.toLowerCase().startsWith(mod))
|
||||
LOGGER.info("Loaded compatibility mixin class for mod \"" + mod + "\" (class: " + target_class + ")");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ import java.util.*;
|
||||
@Mixin(AthenaBakedModel.class)
|
||||
public abstract class AthenaBakedModelMixin implements DynamicBakedModel, BakedModel {
|
||||
|
||||
@Shadow @Final private AthenaBlockModel model;
|
||||
@Shadow(remap = false) @Final private AthenaBlockModel model;
|
||||
|
||||
@Shadow @Final private Int2ObjectMap<Sprite> textures;
|
||||
@Shadow(remap = false) @Final private Int2ObjectMap<Sprite> textures;
|
||||
|
||||
/**
|
||||
* Reuses the emitQuad method to compute the quads to be used by the frame
|
||||
|
@ -0,0 +1,43 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import fr.adrien1106.reframed.block.ReFramedBlock;
|
||||
import fr.adrien1106.reframed.util.IBlockRenderInfoMixin;
|
||||
import fr.adrien1106.reframed.util.ThemeableBlockEntity;
|
||||
import link.infra.indium.renderer.render.BlockRenderInfo;
|
||||
import link.infra.indium.renderer.render.TerrainBlockRenderInfo;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(TerrainBlockRenderInfo.class)
|
||||
public abstract class IndiumTerrainBlockRenderInfoMixin extends BlockRenderInfo implements IBlockRenderInfoMixin {
|
||||
|
||||
@Unique private int theme_index = 1;
|
||||
|
||||
@Redirect(
|
||||
method = "shouldDrawFaceInner",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lme/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache;shouldDrawSide(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;)Z"
|
||||
)
|
||||
)
|
||||
private boolean shouldDrawCamoSide(BlockOcclusionCache instance, BlockState state, BlockView view, BlockPos pos, Direction face) {
|
||||
BlockPos other_pos = pos.offset(face);
|
||||
if (!(view.getBlockEntity(pos) instanceof ThemeableBlockEntity
|
||||
|| view.getBlockEntity(other_pos) instanceof ThemeableBlockEntity))
|
||||
return instance.shouldDrawSide(state, view, pos, face);
|
||||
return ReFramedBlock.shouldDrawSide(state, view, pos, face, other_pos, theme_index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareForBlock(BlockState blockState, BlockPos blockPos, long seed, boolean modelAo, int theme_index) {
|
||||
this.theme_index = theme_index;
|
||||
prepareForBlock(blockState, blockPos, seed, modelAo);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import fr.adrien1106.reframed.client.model.MultiRetexturableModel;
|
||||
import fr.adrien1106.reframed.util.IBlockRenderInfoMixin;
|
||||
import fr.adrien1106.reframed.util.IMultipartBakedModelMixin;
|
||||
import link.infra.indium.renderer.render.AbstractBlockRenderContext;
|
||||
import link.infra.indium.renderer.render.TerrainRenderContext;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderContext;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Mixin(TerrainRenderContext.class)
|
||||
public abstract class IndiumTerrainRenderContextMixin extends AbstractBlockRenderContext {
|
||||
|
||||
@Inject(
|
||||
method = "tessellateBlock",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Llink/infra/indium/renderer/aocalc/AoCalculator;clear()V"
|
||||
), remap = false,
|
||||
cancellable = true)
|
||||
private void renderMultipleModels(BlockRenderContext ctx, CallbackInfo ci) {
|
||||
if (!(ctx.model() instanceof IMultipartBakedModelMixin wrapped)
|
||||
|| !(wrapped.getModel(ctx.state()) instanceof MultiRetexturableModel retexturing_model)) return;
|
||||
|
||||
List<BakedModel> models = retexturing_model.models();
|
||||
int i = 0;
|
||||
for (BakedModel bakedModel : models) {
|
||||
i++;
|
||||
aoCalc.clear();
|
||||
((IBlockRenderInfoMixin) blockInfo).prepareForBlock(ctx.state(), ctx.pos(), ctx.seed(), bakedModel.useAmbientOcclusion(), i);
|
||||
bakedModel.emitBlockQuads(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, blockInfo.randomSupplier, this);
|
||||
}
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package fr.adrien1106.reframed.mixin.compat;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import fr.adrien1106.reframed.block.ReFramedBlock;
|
||||
import fr.adrien1106.reframed.util.ThemeableBlockEntity;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(BlockOcclusionCache.class)
|
||||
public class SodiumBlockOcclusionCacheMixin {
|
||||
|
||||
@Inject(
|
||||
method = "shouldDrawSide",
|
||||
at = @At(
|
||||
value = "INVOKE_ASSIGN",
|
||||
target = "Lnet/minecraft/world/BlockView;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;",
|
||||
shift = At.Shift.AFTER
|
||||
), cancellable = true)
|
||||
private void shouldDrawFrameNeighborSide(BlockState self_state, BlockView view, BlockPos self_pos, Direction face, CallbackInfoReturnable<Boolean> cir, @Local BlockPos.Mutable other_pos) {
|
||||
if (!(view.getBlockEntity(other_pos) instanceof ThemeableBlockEntity)) return;
|
||||
cir.setReturnValue(ReFramedBlock.shouldDrawSide(self_state, view, self_pos, face, other_pos, 0));
|
||||
}
|
||||
}
|
@ -7,34 +7,23 @@ import fr.adrien1106.reframed.util.ThemeableBlockEntity;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.minecraft.world.BlockView;
|
||||
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.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(BlockRenderInfo.class)
|
||||
public abstract class BlockRenderInfoMixin implements IBlockRenderInfoMixin {
|
||||
|
||||
@Shadow public BlockPos blockPos;
|
||||
|
||||
@Shadow public BlockState blockState;
|
||||
|
||||
@Shadow public BlockRenderView blockView;
|
||||
|
||||
@Shadow @Final private BlockPos.Mutable searchPos;
|
||||
|
||||
@Shadow public abstract void prepareForBlock(BlockState blockState, BlockPos blockPos, boolean modelAo);
|
||||
|
||||
@Shadow public BlockRenderView blockView;
|
||||
@Unique
|
||||
private int theme_index = 1;
|
||||
|
||||
@ -42,27 +31,18 @@ public abstract class BlockRenderInfoMixin implements IBlockRenderInfoMixin {
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayers;" +
|
||||
"getBlockLayer(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/RenderLayer;"))
|
||||
public BlockState prepareCamoLayer(BlockState state, @Local(argsOnly = true) BlockPos pos) {
|
||||
BlockEntity block_entity = MinecraftClient.getInstance().world.getBlockEntity(pos);
|
||||
BlockEntity block_entity = blockView.getBlockEntity(pos);
|
||||
if (!(block_entity instanceof ThemeableBlockEntity frame_entity)) return state;
|
||||
return frame_entity.getTheme(theme_index);
|
||||
}
|
||||
|
||||
@Inject(method = "shouldDrawFace",
|
||||
at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/util/math/Direction;getId()I"),
|
||||
cancellable = true)
|
||||
private void shouldDrawCamoFace(Direction face, CallbackInfoReturnable<Boolean> cir) {
|
||||
// early injection for camos themselves
|
||||
BlockEntity block_entity = MinecraftClient.getInstance().world.getBlockEntity(blockPos);
|
||||
if (!(block_entity instanceof ThemeableBlockEntity)) return;
|
||||
cir.setReturnValue(ReFramedBlock.shouldDrawSide(blockState, blockView, blockPos, face, searchPos.set(blockPos, face), theme_index));
|
||||
}
|
||||
|
||||
@Redirect(method = "shouldDrawFace", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;shouldDrawSide(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;Lnet/minecraft/util/math/BlockPos;)Z"))
|
||||
private boolean shouldDrawAdjacentCamoSide(BlockState state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos) {
|
||||
return ReFramedBlock.shouldDrawSide(state, world, pos, side, other_pos, theme_index);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Unique
|
||||
public void prepareForBlock(BlockState state, BlockPos pos, boolean ao, int theme_index) {
|
||||
this.theme_index = theme_index;
|
||||
prepareForBlock(state, pos, ao);
|
||||
|
@ -21,9 +21,9 @@ public abstract class TerrainRenderContextMixin extends AbstractBlockRenderConte
|
||||
|
||||
@Inject(method = "tessellateBlock", at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator;clear()V",
|
||||
shift = At.Shift.AFTER
|
||||
), cancellable = true)
|
||||
target = "Lnet/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator;clear()V"
|
||||
), remap = false,
|
||||
cancellable = true)
|
||||
private void renderMultipleModels(BlockState state, BlockPos pos, BakedModel wrapper, MatrixStack matrixStack, CallbackInfo ci) {
|
||||
if (!(wrapper instanceof IMultipartBakedModelMixin wrapped)
|
||||
|| !(wrapped.getModel(state) instanceof MultiRetexturableModel retexturing_model)) return;
|
||||
|
@ -6,4 +6,6 @@ import net.minecraft.util.math.BlockPos;
|
||||
public interface IBlockRenderInfoMixin {
|
||||
|
||||
void prepareForBlock(BlockState state, BlockPos pos, boolean ao, int theme_index);
|
||||
|
||||
void prepareForBlock(BlockState state, BlockPos pos, long seed, boolean ao, int theme_index);
|
||||
}
|
||||
|
@ -31,6 +31,8 @@
|
||||
"fabric-api": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"athena": "^${athena_version}"
|
||||
"athena": "^${athena_version}",
|
||||
"sodium": "^${sodium_version}",
|
||||
"indium": "^${indium_version}"
|
||||
}
|
||||
}
|
@ -6,13 +6,17 @@
|
||||
"mixins": [
|
||||
"WallBlockAccessor",
|
||||
"particles.MixinEntity",
|
||||
"particles.MixinLivingEntity"
|
||||
"particles.MixinLivingEntity",
|
||||
"sound.LivingEntityMixin"
|
||||
],
|
||||
"client": [
|
||||
"MinecraftAccessor",
|
||||
"compat.AthenaBakedModelMixin",
|
||||
"compat.AthenaConnectedBlockModelMixin",
|
||||
"compat.AthenaWrappedGetterMixin",
|
||||
"compat.IndiumTerrainBlockRenderInfoMixin",
|
||||
"compat.IndiumTerrainRenderContextMixin",
|
||||
"compat.SodiumBlockOcclusionCacheMixin",
|
||||
"model.WeightedBakedModelAccessor",
|
||||
"particles.AccessorParticle",
|
||||
"particles.AccessorSpriteBillboardParticle",
|
||||
|
Loading…
Reference in New Issue
Block a user