diff --git a/common/build.gradle b/common/build.gradle index 1de944b7..5e2ef966 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -11,7 +11,7 @@ dependencies { // Do NOT use other classes from fabric loader modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - modApi("dev.latvian.mods:kubejs:${kubejs_version}") { + modCompileOnly("dev.latvian.mods:kubejs:${kubejs_version}") { transitive = false } modApi("dev.latvian.mods:rhino:${rhino_version}") { diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/faster_command_suggestions/SuggestionsBuilderMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/faster_command_suggestions/SuggestionsBuilderMixin.java new file mode 100644 index 00000000..e27b0480 --- /dev/null +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/faster_command_suggestions/SuggestionsBuilderMixin.java @@ -0,0 +1,30 @@ +package org.embeddedt.modernfix.fabric.mixin.perf.faster_command_suggestions; + +import com.mojang.brigadier.suggestion.Suggestion; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.List; + +/** + * Simple hack-fix to limit the number of suggestions being processed. Not a perfect fix but mitigates lag decently + * on an i3-4150. + */ +@Mixin(SuggestionsBuilder.class) +public class SuggestionsBuilderMixin { + @Unique + private static final int MAX_SUGGESTIONS = 10000; + + @Shadow @Final @Mutable + private List result; + + @Redirect(method = "*", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z"), require = 0) + private boolean addIfFits(List list, T entry) { + if(list != result || list.size() < MAX_SUGGESTIONS) { + return list.add(entry); + } + return false; + } +} diff --git a/fabric/testmod/build.gradle b/fabric/testmod/build.gradle new file mode 100644 index 00000000..8fa9f8a2 --- /dev/null +++ b/fabric/testmod/build.gradle @@ -0,0 +1,34 @@ +apply plugin: "dev.architectury.loom" + +loom { + accessWidenerPath = project(":common").loom.accessWidenerPath +} + +dependencies { + minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" + mappings loom.layered() { + officialMojangMappings() + if(rootProject.hasProperty("parchment_version")) { + parchment("org.parchmentmc.data:parchment-${minecraft_version}:${parchment_version}@zip") + } + } + + modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" + modImplementation(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } + modImplementation(fabricApi.module("fabric-models-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } + modImplementation(fabricApi.module("fabric-registry-sync-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } + modImplementation(fabricApi.module("fabric-renderer-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } + modRuntimeOnly(fabricApi.module("fabric-renderer-indigo", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } + + implementation project(path: ":common", configuration: "namedElements") + implementation project(path: ":fabric", configuration: "namedElements") +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + diff --git a/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/TestBlock.java b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/TestBlock.java new file mode 100644 index 00000000..c10b8c09 --- /dev/null +++ b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/TestBlock.java @@ -0,0 +1,13 @@ +package org.embeddedt.modernfix.testmod; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockBehaviour; + +public class TestBlock extends Block { + private static final BlockBehaviour.Properties PROPERTIES = BlockBehaviour.Properties.copy(Blocks.STONE); + + public TestBlock() { + super(PROPERTIES); + } +} diff --git a/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/TestBlockItem.java b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/TestBlockItem.java new file mode 100644 index 00000000..cfc09cfa --- /dev/null +++ b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/TestBlockItem.java @@ -0,0 +1,13 @@ +package org.embeddedt.modernfix.testmod; + +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Item; + +public class TestBlockItem extends BlockItem { + private static final Item.Properties PROPERTIES = new Item.Properties().tab(CreativeModeTab.TAB_BUILDING_BLOCKS); + + public TestBlockItem(TestBlock block) { + super(block, PROPERTIES); + } +} diff --git a/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/TestMod.java b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/TestMod.java new file mode 100644 index 00000000..5ad72e50 --- /dev/null +++ b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/TestMod.java @@ -0,0 +1,64 @@ +package org.embeddedt.modernfix.testmod; + +import com.google.common.base.Stopwatch; +import net.fabricmc.api.ModInitializer; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; + +public class TestMod implements ModInitializer { + public static final String ID = "mfix_testmod"; + public static final Logger LOGGER = LogManager.getLogger("ModernFix TestMod"); + + public static final int NUM_COLORS = 100; + public static final int MAX_COLOR = NUM_COLORS - 1; + + public static final List WOOL_STATES = new ArrayList<>(); + + @Override + public void onInitialize() { + // Register 1 million blocks & items + Stopwatch watch = Stopwatch.createStarted(); + int totalToRegister = NUM_COLORS * NUM_COLORS * NUM_COLORS; + int progressReport = totalToRegister / 20; + int numRegistered = 0; + for(int r = 0; r < NUM_COLORS; r++) { + for(int g = 0; g < NUM_COLORS; g++) { + for(int b = 0; b < NUM_COLORS; b++) { + ResourceLocation name = new ResourceLocation(ID, "wool_" + r + "_" + g + "_" + b); + TestBlock block = Registry.register(Registry.BLOCK, name, new TestBlock()); + WOOL_STATES.add(block.defaultBlockState()); + Registry.register(Registry.ITEM, name, new TestBlockItem(block)); + numRegistered++; + if((numRegistered % progressReport) == 0) { + LOGGER.info(String.format("Registering... %.02f%%", ((float)numRegistered)/totalToRegister * 100)); + } + } + } + } + watch.stop(); + LOGGER.info("Registered {} registry entries in {}", totalToRegister, watch); + } + + private static final BlockState AIR = Blocks.AIR.defaultBlockState(); + + public static BlockState getColorCubeStateFor(int chunkX, int chunkY, int chunkZ) { + BlockState blockState = AIR; + if (chunkX >= 0 && chunkY >= 0 && chunkZ >= 0 && chunkX % 2 == 0 && chunkY % 2 == 0 && chunkZ % 2 == 0) { + chunkX /= 2; + chunkY /= 2; + chunkZ /= 2; + if(chunkX <= TestMod.MAX_COLOR && chunkY <= TestMod.MAX_COLOR && chunkZ <= TestMod.MAX_COLOR) { + blockState = TestMod.WOOL_STATES.get((chunkX * TestMod.NUM_COLORS * TestMod.NUM_COLORS) + (chunkY * TestMod.NUM_COLORS) + chunkZ); + } + } + + return blockState; + } +} diff --git a/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/client/TestModBlockModel.java b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/client/TestModBlockModel.java new file mode 100644 index 00000000..c2f8a5a7 --- /dev/null +++ b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/client/TestModBlockModel.java @@ -0,0 +1,146 @@ +package org.embeddedt.modernfix.testmod.client; + +import com.google.common.collect.ImmutableList; +import com.mojang.datafixers.util.Pair; +import net.fabricmc.fabric.api.renderer.v1.Renderer; +import net.fabricmc.fabric.api.renderer.v1.RendererAccess; +import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; +import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; +import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.*; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import org.embeddedt.modernfix.testmod.TestMod; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; + +public class TestModBlockModel implements UnbakedModel, BakedModel, FabricBakedModel { + private static final Material BASE_WOOL = new Material(TextureAtlas.LOCATION_BLOCKS, new ResourceLocation(TestMod.ID, "block/base_wool")); + + private Mesh mesh; + private TextureAtlasSprite texture; + + private final int r, g, b; + + public TestModBlockModel(int r, int g, int b) { + this.r = r; + this.g = g; + this.b = b; + } + + @Override + public boolean isVanillaAdapter() { + return false; + } + + @Override + public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { + context.meshConsumer().accept(mesh); + } + + @Override + public void emitItemQuads(ItemStack stack, Supplier randomSupplier, RenderContext context) { + context.meshConsumer().accept(mesh); + } + + @Override + public List getQuads(@Nullable BlockState state, @Nullable Direction side, RandomSource rand) { + return Collections.emptyList(); + } + + @Override + public boolean useAmbientOcclusion() { + return true; + } + + @Override + public boolean isGui3d() { + return true; + } + + @Override + public boolean usesBlockLight() { + return true; + } + + @Override + public boolean isCustomRenderer() { + return false; + } + + @Override + public TextureAtlasSprite getParticleIcon() { + return texture; + } + + @Override + public ItemTransforms getTransforms() { + return ModelHelper.MODEL_TRANSFORM_BLOCK; + } + + @Override + public ItemOverrides getOverrides() { + return ItemOverrides.EMPTY; + } + + @Override + public Collection getDependencies() { + return Collections.emptyList(); + } + + @Override + public Collection getMaterials(Function modelGetter, Set> missingTextureErrors) { + return ImmutableList.of(BASE_WOOL); + } + + private static int scaleColor(int c) { + return c * 255 / TestMod.MAX_COLOR; + } + + @Nullable + @Override + public BakedModel bake(ModelBakery modelBakery, Function spriteGetter, ModelState transform, ResourceLocation location) { + // Build the mesh using the Renderer API + Renderer renderer = RendererAccess.INSTANCE.getRenderer(); + MeshBuilder builder = renderer.meshBuilder(); + QuadEmitter emitter = builder.getEmitter(); + + texture = spriteGetter.apply(BASE_WOOL); + + for(Direction direction : Direction.values()) { + // Add a new face to the mesh + emitter.square(direction, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f); + // Set the sprite of the face, must be called after .square() + // We haven't specified any UV coordinates, so we want to use the whole texture. BAKE_LOCK_UV does exactly that. + emitter.spriteBake(0, texture, MutableQuadView.BAKE_LOCK_UV); + int color = (255 << 24) | (scaleColor(r) << 16) | (scaleColor(g) << 8) | scaleColor(b); + // Enable texture usage + emitter.spriteColor(0, color, color, color, color); + // Add the quad to the mesh + emitter.emit(); + } + mesh = builder.build(); + + return this; + } +} diff --git a/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/client/TestModClient.java b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/client/TestModClient.java new file mode 100644 index 00000000..24f9dbb9 --- /dev/null +++ b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/client/TestModClient.java @@ -0,0 +1,30 @@ +package org.embeddedt.modernfix.testmod.client; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; +import net.minecraft.client.Minecraft; +import org.embeddedt.modernfix.testmod.TestMod; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TestModClient implements ClientModInitializer { + private static final Pattern RGB_PATTERN = Pattern.compile("^wool_([0-9]+)_([0-9]+)_([0-9]+)$"); + @Override + public void onInitializeClient() { + ModelLoadingRegistry.INSTANCE.registerVariantProvider(resourceManager -> (modelId, context) -> { + if(modelId.getNamespace().equals(TestMod.ID)) { + Matcher matcher = RGB_PATTERN.matcher(modelId.getPath()); + if(matcher.matches()) { + int r = Integer.parseInt(matcher.group(1)); + int g = Integer.parseInt(matcher.group(2)); + int b = Integer.parseInt(matcher.group(3)); + return new TestModBlockModel(r, g, b); + } + } + return null; + }); + // needed to make debug level rendering work correctly + Minecraft.getInstance().smartCull = false; + } +} diff --git a/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/mixin/ChunkMixin.java b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/mixin/ChunkMixin.java new file mode 100644 index 00000000..1356aece --- /dev/null +++ b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/mixin/ChunkMixin.java @@ -0,0 +1,25 @@ +package org.embeddedt.modernfix.testmod.mixin; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.LevelChunk; +import org.embeddedt.modernfix.testmod.TestMod; +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; + +@Mixin(LevelChunk.class) +public class ChunkMixin { + @Shadow @Final private Level level; + + @Inject(method = "getBlockState", at = @At("HEAD"), cancellable = true) + private void redirectDebugWorld(BlockPos pos, CallbackInfoReturnable cir) { + if(this.level.isDebug()) { + cir.setReturnValue(TestMod.getColorCubeStateFor(pos.getX(), pos.getY(), pos.getZ())); + } + } +} diff --git a/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/mixin/DebugLevelSourceMixin.java b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/mixin/DebugLevelSourceMixin.java new file mode 100644 index 00000000..d37d0480 --- /dev/null +++ b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/mixin/DebugLevelSourceMixin.java @@ -0,0 +1,40 @@ +package org.embeddedt.modernfix.testmod.mixin; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.levelgen.DebugLevelSource; +import org.embeddedt.modernfix.testmod.TestMod; +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; + +@Mixin(DebugLevelSource.class) +public class DebugLevelSourceMixin { + @Inject(method = "applyBiomeDecoration", at = @At("HEAD"), cancellable = true) + private void showColorCube(WorldGenLevel level, ChunkAccess chunk, StructureManager structureFeatureManager, CallbackInfo ci) { + ci.cancel(); + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + ChunkPos chunkPos = chunk.getPos(); + int i = chunkPos.x; + int j = chunkPos.z; + + for(int k = 0; k < 16; ++k) { + for(int l = 0; l < 16; ++l) { + int m = SectionPos.sectionToBlockCoord(i, k); + int n = SectionPos.sectionToBlockCoord(j, l); + for(int y = 0; y < 255; y++) { + BlockState blockState = TestMod.getColorCubeStateFor(m, y, n); + if (blockState != null) { + level.setBlock(mutableBlockPos.set(m, y, n), blockState, 2); + } + } + } + } + } +} diff --git a/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/mixin/RenderChunkMixin.java b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/mixin/RenderChunkMixin.java new file mode 100644 index 00000000..eaa6d1d2 --- /dev/null +++ b/fabric/testmod/src/main/java/org/embeddedt/modernfix/testmod/mixin/RenderChunkMixin.java @@ -0,0 +1,23 @@ +package org.embeddedt.modernfix.testmod.mixin; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import org.embeddedt.modernfix.testmod.TestMod; +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; + +@Mixin(targets = { "net/minecraft/client/renderer/chunk/RenderChunk" }) +public class RenderChunkMixin { + @Shadow @Final private boolean debug; + + @Inject(method = "getBlockState", at = @At("HEAD"), cancellable = true) + private void redirectDebugWorld(BlockPos pos, CallbackInfoReturnable cir) { + if(this.debug) { + cir.setReturnValue(TestMod.getColorCubeStateFor(pos.getX(), pos.getY(), pos.getZ())); + } + } +} diff --git a/fabric/testmod/src/main/resources/assets/mfix_testmod/textures/block/base_wool.png b/fabric/testmod/src/main/resources/assets/mfix_testmod/textures/block/base_wool.png new file mode 100644 index 00000000..39d6ec76 Binary files /dev/null and b/fabric/testmod/src/main/resources/assets/mfix_testmod/textures/block/base_wool.png differ diff --git a/fabric/testmod/src/main/resources/fabric.mod.json b/fabric/testmod/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..6ebb4d54 --- /dev/null +++ b/fabric/testmod/src/main/resources/fabric.mod.json @@ -0,0 +1,26 @@ +{ + "schemaVersion": 1, + "id": "mfix_testmod", + "version": "${version}", + "name": "ModernFix test mod", + "description": "Test mod used to validate features and behaviors of ModernFix, the essential Minecraft performance mod", + "authors": [ + "embeddedt" + ], + "contact": { + "sources": "https://github.com/embeddedt/ModernFix", + "homepage": "https://modrinth.com/mod/modernfix", + "issues": "https://github.com/embeddedt/ModernFix/issues" + }, + "license": "LGPL-3.0", + "environment": "*", + "mixins": [ "testmod.mixins.json" ], + "entrypoints": { + "main": [ + "org.embeddedt.modernfix.testmod.TestMod" + ], + "client": [ + "org.embeddedt.modernfix.testmod.client.TestModClient" + ] + } +} \ No newline at end of file diff --git a/fabric/testmod/src/main/resources/pack.mcmeta b/fabric/testmod/src/main/resources/pack.mcmeta new file mode 100644 index 00000000..68df7ebf --- /dev/null +++ b/fabric/testmod/src/main/resources/pack.mcmeta @@ -0,0 +1,7 @@ +{ + "pack": { + "description": "testmod resources", + "pack_format": 6, + "_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods." + } +} diff --git a/fabric/testmod/src/main/resources/testmod.mixins.json b/fabric/testmod/src/main/resources/testmod.mixins.json new file mode 100644 index 00000000..46222aa3 --- /dev/null +++ b/fabric/testmod/src/main/resources/testmod.mixins.json @@ -0,0 +1,16 @@ +{ + "required": true, + "package": "org.embeddedt.modernfix.testmod.mixin", + "compatibilityLevel": "JAVA_8", + "minVersion": "0.8", + "mixins": [ + "ChunkMixin", + "DebugLevelSourceMixin" + ], + "client": [ + "RenderChunkMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 739e778f..c5b39d7c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,8 +10,14 @@ pluginManagement { include("test_agent") include("common") -getProperty("enabled_platforms").tokenize(',').each { it -> - include(it.trim()) +def current_platforms = getProperty("enabled_platforms").tokenize(',') +current_platforms.each { it -> + def platform_name = it.trim() + include(platform_name) + def testmodFolder = new File(platform_name + "/" + "testmod") + if(testmodFolder.isDirectory()) { + include(platform_name + ":testmod") + } } rootProject.name = 'modernfix'