Remove Fabric code from 1.21

This commit is contained in:
embeddedt 2025-12-26 19:24:35 -05:00
parent 1b26be735b
commit d0fe9d6002
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
38 changed files with 0 additions and 1424 deletions

View File

@ -1,126 +0,0 @@
plugins {
id "com.github.johnrengelman.shadow"
id 'com.adarshr.test-logger' version '3.2.0'
id "modernfix.mod-common-conventions"
id "modernfix.platform-conventions"
}
architectury {
platformSetupLoomIde()
fabric()
}
configurations {
common
shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files.
compileClasspath.extendsFrom common
runtimeClasspath.extendsFrom common
modIncludeImplementation
include.extendsFrom modIncludeImplementation
modImplementation.extendsFrom modIncludeImplementation
testAgent {
canBeConsumed = false
}
}
dependencies {
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
testImplementation "net.fabricmc:fabric-loader-junit:${rootProject.fabric_loader_version}"
modCompileOnly(fabricApi.module("fabric-api-base", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modCompileOnly(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modCompileOnly(fabricApi.module("fabric-command-api-v2", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modCompileOnly(fabricApi.module("fabric-model-loading-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modCompileOnly(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modCompileOnly(fabricApi.module("fabric-data-generation-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
if(project.use_fabric_api_at_runtime.toBoolean()) {
modImplementation("com.terraformersmc:modmenu:${rootProject.modmenu_version}") { transitive false }
modImplementation "curse.maven:spark-361579:${rootProject.spark_version}"
modRuntimeOnly("net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}") { exclude group: 'net.fabricmc', module: 'fabric-loader' }
} else {
modCompileOnly("com.terraformersmc:modmenu:${rootProject.modmenu_version}") { transitive false }
modCompileOnly "curse.maven:spark-361579:${rootProject.spark_version}"
}
// Remove the next line if you don't want to depend on the API
// modApi "me.shedaniel:architectury-fabric:${rootProject.architectury_version}"
common(project(path: ":common", configuration: "namedElements")) { transitive false }
testImplementation(shadowCommon(project(path: ":common", configuration: "transformProductionFabric"))) { transitive false }
shadowCommon(project(path: ":annotations"))
testImplementation(platform("org.junit:junit-bom:${project.junit_version}"))
testImplementation("org.junit.jupiter:junit-jupiter-api")
testImplementation("org.junit.jupiter:junit-jupiter-params")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("org.junit.platform:junit-platform-launcher")
testImplementation("org.assertj:assertj-core:3.19.0")
testImplementation("com.google.guava:guava-testlib:21.0")
testImplementation("org.mockito:mockito-junit-jupiter:5.3.1")
testAgent(project("path": ":test_agent", "configuration": "agentJar"))
}
tasks.named("test") {
useJUnitPlatform()
def runDir = file('test_run')
doFirst() {
runDir.mkdir()
}
workingDir = runDir
systemProperty 'modernfix.ignoreConfigForTesting', 'true'
// inject our custom agent to fix #817
FileCollection agentFile = configurations.getByName("testAgent")
jvmArgs "-javaagent:${agentFile.singleFile.absolutePath}"
dependsOn(agentFile)
}
processResources {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
shadowJar {
exclude "architectury.common.json"
configurations = [project.configurations.shadowCommon]
archiveClassifier.set("dev-shadow")
}
remapJar {
injectAccessWidener = true
input.set shadowJar.archiveFile
dependsOn shadowJar
archiveClassifier.set(null)
}
jar {
archiveClassifier.set("dev")
}
components.java {
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
skip()
}
}
publishing {
publications {
mavenFabric(MavenPublication) {
artifactId = rootProject.archives_base_name + "-" + project.name
from components.java
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
}
}

View File

@ -1,18 +0,0 @@
package org.embeddedt.modernfix;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import org.embeddedt.modernfix.fabric.datagen.RuntimeDatagen;
public class ModernFixClientFabric implements ClientModInitializer {
public static ModernFixClient commonMod;
@Override
public void onInitializeClient() {
commonMod = new ModernFixClient();
if(FabricLoader.getInstance().isModLoaded("fabric-data-generation-api-v1")) {
RuntimeDatagen.init();
}
}
}

View File

@ -1,19 +0,0 @@
package org.embeddedt.modernfix;
import net.fabricmc.api.ModInitializer;
import net.minecraft.server.MinecraftServer;
import java.lang.ref.WeakReference;
public class ModernFixFabric implements ModInitializer {
public static ModernFix commonMod;
public static WeakReference<MinecraftServer> theServer = new WeakReference<>(null);
@Override
public void onInitialize() {
commonMod = new ModernFix();
// TODO: implement entity ID desync
}
}

View File

@ -1,35 +0,0 @@
package org.embeddedt.modernfix;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
import net.fabricmc.loader.impl.gui.FabricGuiEntry;
import net.fabricmc.loader.impl.gui.FabricStatusTree;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.spark.SparkLaunchProfiler;
import org.embeddedt.modernfix.util.CommonModUtil;
public class ModernFixPreLaunchFabric implements PreLaunchEntrypoint {
@Override
public void onPreLaunch() {
if(ModernFixMixinPlugin.instance == null) {
System.err.println("Mixin plugin not loaded yet");
return;
}
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_launch.OnFabric")) {
CommonModUtil.runWithoutCrash(() -> SparkLaunchProfiler.start("launch"), "Failed to start profiler");
}
// Prevent launching with Continuity when dynamic resources is on
if(false && ModernFixMixinPlugin.instance.isOptionEnabled("perf.dynamic_resources.ContinuityCheck")
&& FabricLoader.getInstance().isModLoaded("continuity")) {
CommonModUtil.runWithoutCrash(() -> {
FabricGuiEntry.displayError("Compatibility warning", null, tree -> {
FabricStatusTree.FabricStatusTab crashTab = tree.addTab("Warning");
crashTab.node.addMessage("Continuity and ModernFix's dynamic resources option are not compatible before Minecraft 1.19.4.", FabricStatusTree.FabricTreeWarningLevel.ERROR);
crashTab.node.addMessage("Remove Continuity or disable dynamic resources in the ModernFix config.", FabricStatusTree.FabricTreeWarningLevel.ERROR);
tree.tabs.removeIf(tab -> tab != crashTab);
}, true);
}, "display Continuity warning");
}
}
}

View File

@ -1,20 +0,0 @@
package org.embeddedt.modernfix.fabric.api.dynresources;
import net.minecraft.resources.ResourceLocation;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class ModelScanController {
public static final List<Predicate<ResourceLocation>> SCAN_PREDICATES = new ArrayList<>();
public static boolean shouldScanAndTestWrapping(ResourceLocation location) {
if(SCAN_PREDICATES.size() > 0) {
for(Predicate<ResourceLocation> predicate : SCAN_PREDICATES) {
if(!predicate.test(location))
return false;
}
}
return true;
}
}

View File

@ -1,40 +0,0 @@
package org.embeddedt.modernfix.fabric.datagen;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.fabricmc.fabric.impl.datagen.FabricDataGenHelper;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.network.chat.Component;
import org.embeddedt.modernfix.ModernFix;
import java.lang.reflect.Method;
public class RuntimeDatagen {
private static final boolean SHOULD_RUNTIME_DATAGEN = System.getProperty("fabric-api.datagen.output-dir") != null;
private static void runRuntimeDatagen() {
// call runInternal directly to avoid exiting immediately
try {
System.setProperty("fabric-api.datagen", "true");
Method method = FabricDataGenHelper.class.getDeclaredMethod("runInternal");
method.setAccessible(true);
method.invoke(null);
} catch(Throwable e) {
ModernFix.LOGGER.error("Error running datagen", e);
} finally {
System.clearProperty("fabric-api.datagen");
}
}
public static void init() {
if(!SHOULD_RUNTIME_DATAGEN)
return;
ScreenEvents.AFTER_INIT.register(((client, s, scaledWidth, scaledHeight) -> {
if(s instanceof TitleScreen screen) {
screen.addRenderableWidget(Button.builder(Component.literal("DG"), (arg) -> {
runRuntimeDatagen();
}).pos(screen.width / 2 - 100 - 50, screen.height / 4 + 48).size(50, 20).build());
}
}));
}
}

View File

@ -1,18 +0,0 @@
package org.embeddedt.modernfix.fabric.mixin.core;
import net.minecraft.client.multiplayer.ClientConfigurationPacketListenerImpl;
import org.embeddedt.modernfix.ModernFixClientFabric;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
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(ClientConfigurationPacketListenerImpl.class)
@ClientOnlyMixin
public class ClientCommonPacketListenerImplMixin {
@Inject(method = "handleUpdateTags", at = @At("RETURN"))
private void signalTags(CallbackInfo ci) {
ModernFixClientFabric.commonMod.onTagsUpdated();
}
}

View File

@ -1,18 +0,0 @@
package org.embeddedt.modernfix.fabric.mixin.core;
import net.minecraft.server.MinecraftServer;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
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(MinecraftServer.class)
@ClientOnlyMixin
public class ClientMinecraftServerMixin {
@Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;getNanos()J", ordinal = 0))
private void markServerStarted(CallbackInfo ci) {
ModernFixClient.INSTANCE.onServerStarted((MinecraftServer)(Object)this);
}
}

View File

@ -1,18 +0,0 @@
package org.embeddedt.modernfix.fabric.mixin.core;
import net.minecraft.client.multiplayer.ClientPacketListener;
import org.embeddedt.modernfix.ModernFixClientFabric;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
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(value = ClientPacketListener.class, priority = 1500)
@ClientOnlyMixin
public class ClientPlayNetHandlerMixin {
@Inject(method = "handleUpdateRecipes", at = @At("RETURN"))
private void signalRecipes(CallbackInfo ci) {
ModernFixClientFabric.commonMod.onRecipesUpdated();
}
}

View File

@ -1,18 +0,0 @@
package org.embeddedt.modernfix.fabric.mixin.core;
import net.minecraft.client.Minecraft;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
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(Minecraft.class)
@ClientOnlyMixin
public class MCMixin_Fabric {
@Inject(method = "tick", at = @At("RETURN"))
private void onRenderTickEnd(CallbackInfo ci) {
ModernFixClient.INSTANCE.onRenderTickEnd();
}
}

View File

@ -1,29 +0,0 @@
package org.embeddedt.modernfix.fabric.mixin.core;
import net.minecraft.server.MinecraftServer;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.ModernFixFabric;
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.lang.ref.WeakReference;
@Mixin(MinecraftServer.class)
public class MinecraftServerMixin {
@Inject(method = "runServer", at = @At("HEAD"))
private void changeServerReference(CallbackInfo ci) {
ModernFixFabric.theServer = new WeakReference<>((MinecraftServer)(Object)this);
}
@Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;getNanos()J", ordinal = 0))
private void hookServerStarted(CallbackInfo ci) {
ModernFix.INSTANCE.onServerStarted();
}
@Inject(method = "stopServer", at = @At("RETURN"))
private void hookServerShutdown(CallbackInfo ci) {
ModernFix.INSTANCE.onServerDead((MinecraftServer)(Object)this);
}
}

View File

@ -1,21 +0,0 @@
package org.embeddedt.modernfix.fabric.mixin.feature.branding;
import net.minecraft.client.gui.components.DebugScreenOverlay;
import org.embeddedt.modernfix.ModernFixClientFabric;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import java.util.List;
@Mixin(DebugScreenOverlay.class)
@ClientOnlyMixin
public class GuiMixin {
@ModifyVariable(method = "getSystemInformation", at = @At("STORE"), ordinal = 0, require = 0)
private List<String> addModernFix(List<String> list) {
list.add("");
list.add(ModernFixClientFabric.commonMod.brandingString);
return list;
}
}

View File

@ -1,18 +0,0 @@
package org.embeddedt.modernfix.fabric.mixin.feature.measure_time;
import net.minecraft.client.Minecraft;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
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(Minecraft.class)
@ClientOnlyMixin
public class MinecraftMixin_Fabric {
@Inject(method = "doWorldLoad", at = @At("HEAD"))
private void recordWorldLoadStart(CallbackInfo ci) {
ModernFixClient.worldLoadStartTime = System.nanoTime();
}
}

View File

@ -1,30 +0,0 @@
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(remap = false) @Final @Mutable
private List<Suggestion> result;
@Redirect(method = "*", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z"), require = 0)
private <T> boolean addIfFits(List<T> list, T entry) {
if(list != result || list.size() < MAX_SUGGESTIONS) {
return list.add(entry);
}
return false;
}
}

View File

@ -1,32 +0,0 @@
package org.embeddedt.modernfix.fabric.mixin.safety;
import com.mojang.blaze3d.platform.NativeImage;
import net.minecraft.client.renderer.texture.DynamicTexture;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.jetbrains.annotations.Nullable;
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.CallbackInfo;
@Mixin(DynamicTexture.class)
@ClientOnlyMixin
public class DynamicTextureMixin {
@Shadow @Nullable private NativeImage pixels;
private Exception closeTrace;
@Inject(method = "method_22793", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/texture/DynamicTexture;pixels:Lcom/mojang/blaze3d/platform/NativeImage;", ordinal = 0))
private void checkNullPixels(CallbackInfo ci) {
if(pixels == null) {
ModernFix.LOGGER.error("Attempted to upload null texture! This is not allowed, closed here", closeTrace);
}
}
@Inject(method = "close", at = @At("HEAD"))
private void storeCloseTrace(CallbackInfo ci) {
closeTrace = new Exception();
}
}

View File

@ -1,13 +0,0 @@
package org.embeddedt.modernfix.fabric.modmenu;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import org.embeddedt.modernfix.screen.ModernFixConfigScreen;
@SuppressWarnings("unused")
public class ModernFixModMenuApiImpl implements ModMenuApi {
@Override
public ConfigScreenFactory<ModernFixConfigScreen> getModConfigScreenFactory() {
return ModernFixConfigScreen::new;
}
}

View File

@ -1,116 +0,0 @@
package org.embeddedt.modernfix.platform.fabric;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.mojang.brigadier.CommandDispatcher;
import net.fabricmc.api.EnvType;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.metadata.CustomValue;
import net.fabricmc.loader.api.metadata.ModMetadata;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import org.embeddedt.modernfix.ModernFixFabric;
import org.embeddedt.modernfix.api.constants.IntegrationConstants;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.embeddedt.modernfix.spark.SparkLaunchProfiler;
import org.embeddedt.modernfix.util.CommonModUtil;
import org.objectweb.asm.tree.ClassNode;
import java.nio.file.Path;
import java.util.Map;
import java.util.function.Consumer;
public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks {
public boolean isClient() {
return FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT;
}
public boolean isDedicatedServer() {
return FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER;
}
private static final String verString = FabricLoader.getInstance().getModContainer("modernfix")
.map(mfModContainer -> mfModContainer.getMetadata().getVersion().getFriendlyString())
.orElse("[unknown]");
public String getVersionString() {
return verString;
}
public boolean modPresent(String modId) {
return FabricLoader.getInstance().getModContainer(modId).isPresent();
}
public boolean isDevEnv() {
return FabricLoader.getInstance().isDevelopmentEnvironment();
}
public MinecraftServer getCurrentServer() {
return ModernFixFabric.theServer.get();
}
public boolean isEarlyLoadingNormally() {
return true;
}
public boolean isLoadingNormally() {
return true;
}
public Path getGameDirectory() {
return FabricLoader.getInstance().getGameDir();
}
public void sendPacket(ServerPlayer player, CustomPacketPayload packet) {
//PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), packet);
}
public void injectPlatformSpecificHacks() {
}
public void applyASMTransformers(String mixinClassName, ClassNode targetClass) {
}
public void onServerCommandRegister(Consumer<CommandDispatcher<CommandSourceStack>> handler) {
if(FabricLoader.getInstance().isModLoaded("fabric-command-api-v2"))
CommandRegistrationCallback.EVENT.register((dispatcher, arg, env) -> handler.accept(dispatcher));
}
private static Multimap<String, String> modOptions;
public Multimap<String, String> getCustomModOptions() {
if(modOptions == null) {
modOptions = ArrayListMultimap.create();
for (ModContainer container : FabricLoader.getInstance().getAllMods()) {
ModMetadata meta = container.getMetadata();
if (meta.containsCustomValue(IntegrationConstants.INTEGRATIONS_KEY)) {
CustomValue integrations = meta.getCustomValue(IntegrationConstants.INTEGRATIONS_KEY);
if (integrations.getType() != CustomValue.CvType.OBJECT) {
continue;
}
for (Map.Entry<String, CustomValue> entry : integrations.getAsObject()) {
if(entry.getValue().getType() != CustomValue.CvType.STRING)
continue;
modOptions.put(entry.getKey(), entry.getValue().getAsString());
}
}
}
}
return modOptions;
}
public void onLaunchComplete() {
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_launch.OnFabric")) {
CommonModUtil.runWithoutCrash(() -> SparkLaunchProfiler.stop("launch"), "Failed to stop profiler");
}
}
public String getPlatformName() {
return "Fabric";
}
}

View File

@ -1,50 +0,0 @@
{
"schemaVersion": 1,
"id": "modernfix",
"version": "${version}",
"name": "ModernFix",
"description": "Egregious, yet effective performance improvements for modern Minecraft",
"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",
"icon": "icon.png",
"custom": {
"modmenu": {
"links": {
"modmenu.kofi": "https://ko-fi.com/embeddedt",
"modmenu.github_releases": "https://github.com/embeddedt/ModernFix/releases",
"modmenu.curseforge": "https://www.curseforge.com/minecraft/mc-mods/modernfix"
}
}
},
"environment": "*",
"entrypoints": {
"main": [
"org.embeddedt.modernfix.ModernFixFabric"
],
"client": [
"org.embeddedt.modernfix.ModernFixClientFabric"
],
"modmenu": [ "org.embeddedt.modernfix.fabric.modmenu.ModernFixModMenuApiImpl" ],
"preLaunch": [
"org.embeddedt.modernfix.ModernFixPreLaunchFabric"
]
},
"mixins": [
"modernfix-fabric.mixins.json",
"modernfix-common.mixins.json"
],
"depends": {
"minecraft": ">=1.16.2",
"fabricloader": ">=0.16.10"
},
"breaks": {
"dashloader": "<5.0.0-beta.1"
}
}

View File

@ -1,97 +0,0 @@
package net.minecraft.world.level.block.state;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import org.embeddedt.modernfix.duck.IBlockState;
import org.embeddedt.modernfix.testing.util.BootstrapMinecraft;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
@BootstrapMinecraft
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlockStateCacheTest {
@BeforeEach
public void rebuildCache() {
Blocks.rebuildCache();
}
/**
* Initially, the cache should be invalid, and null.
*/
@Test
@Order(1)
public void testCacheNullInitially() {
BlockState stoneBlock = Blocks.STONE.defaultBlockState();
assertTrue(((IBlockState)stoneBlock).isCacheInvalid());
assertNull(stoneBlock.cache);
// make sure lazy cache correctly handles solid
assertTrue(stoneBlock.isSolid());
}
/**
* When an API that needs the cache is called, it should be built and the invalid flag
* becomes false.
*/
@Test
@Order(2)
public void testCacheBuiltByRequest() {
BlockState stoneBlock = Blocks.STONE.defaultBlockState();
stoneBlock.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
assertFalse(((IBlockState)stoneBlock).isCacheInvalid());
assertNotNull(stoneBlock.cache);
}
/**
* When a second rebuild occurs, the invalid flag should be set to true, but the old cache
* is not set to null, in order to prevent NPEs if a second thread is accessing the cache
* when this takes place.
*/
@Test
@Order(3)
public void testCacheInvalidatedByLateRebuild() {
BlockState stoneBlock = Blocks.STONE.defaultBlockState();
stoneBlock.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
Blocks.rebuildCache();
assertTrue(((IBlockState)stoneBlock).isCacheInvalid());
assertNotNull(stoneBlock.cache);
}
/**
* Tests that the fluidState and isRandomlyTicking caching fields added by Mojang to blockstates are correctly
* handled by the dynamic cache system.
*/
@Test
@Order(4)
public void testExtraFieldCachingCorrect() {
Block[] blocksToCheck = new Block[] { Blocks.WATER, Blocks.FARMLAND };
for(Block block : blocksToCheck) {
for(BlockState state : block.getStateDefinition().getPossibleStates()) {
// check that the fluid states match
assertEquals(block.getFluidState(state), state.getFluidState(), "mismatched fluid state on " + state);
// check that random ticking flag matches
assertEquals(block.isRandomlyTicking(state), state.isRandomlyTicking(), "mismatched random tick state on " + state);
}
}
}
/*
@Test
@Order(5)
public void checkRecursiveFluidState() {
Block b = new Block(BlockBehaviour.Properties.copy(Blocks.STONE)) {
@Override
public FluidState getFluidState(BlockState state) {
return state.getFluidState();
}
};
BlockState state = b.getStateDefinition().any();
((IBlockState)state).clearCache();
// this should not throw
state.getFluidState();
}
*/
}

View File

@ -1,26 +0,0 @@
package org.embeddedt.modernfix.dynamicresources;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.BuiltInModel;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import org.embeddedt.modernfix.testing.util.BootstrapMinecraft;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
@BootstrapMinecraft
public class DynamicModelCacheTest {
@Test
public void testCacheReturnsNullForNullGetter() {
DynamicModelCache<Item> cache = new DynamicModelCache(k -> null, true);
assertNull(cache.get(Items.STONE));
}
@Test
public void testCacheFunctions() {
BakedModel model = new BuiltInModel(null, null, null, false);
DynamicModelCache<Item> cache = new DynamicModelCache(k -> model, true);
assertEquals(model, cache.get(Items.STONE));
}
}

View File

@ -1,14 +0,0 @@
package org.embeddedt.modernfix.testing.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.extension.ExtendWith;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@ExtendWith({ BootstrapMinecraftExtension.class })
public @interface BootstrapMinecraft {
}

View File

@ -1,38 +0,0 @@
package org.embeddedt.modernfix.testing.util;
import net.minecraft.SharedConstants;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.server.Bootstrap;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.Extension;
import org.junit.jupiter.api.extension.ExtensionContext;
import java.lang.reflect.Field;
import java.util.IdentityHashMap;
/**
* Simple extension to run vanilla bootstrap, inspired by AE2.
*/
public class BootstrapMinecraftExtension implements Extension, BeforeAllCallback, AfterAllCallback {
@Override
public void beforeAll(ExtensionContext context) throws Exception {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
// Allow blocks to be created in tests
Field field = MappedRegistry.class.getDeclaredField("unregisteredIntrusiveHolders");
field.setAccessible(true);
if(field.get(BuiltInRegistries.BLOCK) == null) {
field.set(BuiltInRegistries.BLOCK, new IdentityHashMap<>());
field = MappedRegistry.class.getDeclaredField("frozen");
field.setAccessible(true);
field.setBoolean(BuiltInRegistries.BLOCK, false);
}
}
@Override
public void afterAll(ExtensionContext context) throws Exception {
}
}

View File

@ -1,45 +0,0 @@
plugins {
id 'dev.architectury.loom'
}
loom {
accessWidenerPath = project(":common").loom.accessWidenerPath
runs {
client {
vmArgs "-Xmx8G"
property("modernfix.config.mixin.perf.blast_search_trees", "true")
property("modernfix.config.mixin.perf.dynamic_resources", "true")
property("modernfix.config.mixin.perf.dynamic_block_codecs", "true")
}
}
}
dependencies {
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
mappings loom.layered() {
officialMojangMappings()
}
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", "0.84.0+1.20.1")) { 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' }
modImplementation("net.fabricmc.fabric-api:fabric-rendering-data-attachment-v1:0.3.36+92a0d36777") { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modImplementation(fabricApi.module("fabric-rendering-fluids-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
}
}
// Make genSources do nothing in this project
project.gradle.startParameter.excludedTaskNames.add("genSources")

View File

@ -1,13 +0,0 @@
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.ofFullCopy(Blocks.STONE);
public TestBlock() {
super(PROPERTIES);
}
}

View File

@ -1,12 +0,0 @@
package org.embeddedt.modernfix.testmod;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
public class TestBlockItem extends BlockItem {
private static final Item.Properties PROPERTIES = new Item.Properties();
public TestBlockItem(TestBlock block) {
super(block, PROPERTIES);
}
}

View File

@ -1,68 +0,0 @@
package org.embeddedt.modernfix.testmod;
import com.google.common.base.Stopwatch;
import net.fabricmc.api.ModInitializer;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
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 = 32;
public static final int MAX_COLOR = NUM_COLORS - 1;
public static final List<BlockState> 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(BuiltInRegistries.BLOCK, name, new TestBlock());
WOOL_STATES.add(block.defaultBlockState());
//Registry.register(BuiltInRegistries.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 = null;
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;
}
}

View File

@ -1,143 +0,0 @@
package org.embeddedt.modernfix.testmod.client;
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.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<RandomSource> randomSupplier, RenderContext context) {
context.meshConsumer().accept(mesh);
}
@Override
public void emitItemQuads(ItemStack stack, Supplier<RandomSource> randomSupplier, RenderContext context) {
context.meshConsumer().accept(mesh);
}
@Override
public List<BakedQuad> 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<ResourceLocation> getDependencies() {
return Collections.emptyList();
}
@Override
public void resolveParents(Function<ResourceLocation, UnbakedModel> function) {
}
private static int scaleColor(int c) {
return c * 255 / TestMod.MAX_COLOR;
}
@Nullable
@Override
public BakedModel bake(ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState state, 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;
}
}

View File

@ -1,29 +0,0 @@
package org.embeddedt.modernfix.testmod.client;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import org.embeddedt.modernfix.fabric.api.dynresources.ModelScanController;
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() {
ModelScanController.SCAN_PREDICATES.add(rl -> !rl.getNamespace().equals(TestMod.ID));
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;
});
}
}

View File

@ -1,21 +0,0 @@
package org.embeddedt.modernfix.testmod.mixin;
import net.minecraft.core.BlockPos;
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.Mixin;
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 {
@Inject(method = "getBlockState", at = @At("HEAD"), cancellable = true)
private void redirectDebugWorld(BlockPos pos, CallbackInfoReturnable<BlockState> cir) {
BlockState overrideState = TestMod.getColorCubeStateFor(pos.getX(), pos.getY(), pos.getZ());
if(overrideState != null) {
cir.setReturnValue(overrideState);
}
}
}

View File

@ -1,42 +0,0 @@
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.biome.BiomeSource;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.FlatLevelSource;
import org.embeddedt.modernfix.testmod.TestMod;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(FlatLevelSource.class)
public abstract class DebugLevelSourceMixin extends ChunkGenerator {
public DebugLevelSourceMixin(BiomeSource biomeSource) {
super(biomeSource);
}
@Override
public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureFeatureManager) {
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);
}
}
}
}
}
}

View File

@ -1,23 +0,0 @@
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<BlockState> cir) {
if(this.debug) {
cir.setReturnValue(TestMod.getColorCubeStateFor(pos.getX(), pos.getY(), pos.getZ()));
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 560 B

View File

@ -1,26 +0,0 @@
{
"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"
]
}
}

View File

@ -1,7 +0,0 @@
{
"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."
}
}

View File

@ -1,16 +0,0 @@
{
"required": true,
"package": "org.embeddedt.modernfix.testmod.mixin",
"compatibilityLevel": "JAVA_8",
"minVersion": "0.8",
"mixins": [
"ChunkMixin",
"DebugLevelSourceMixin"
],
"client": [
"RenderChunkMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@ -1,87 +0,0 @@
plugins {
//id 'com.github.johnrengelman.shadow' version '7.1.2'
id 'java'
id 'modernfix.common-conventions'
}
group 'org.embeddedt'
archivesBaseName = 'modernfix-test-agent'
version '1.0'
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
repositories {
mavenCentral()
mavenLocal()
maven {
name = 'forge'
url = 'https://maven.minecraftforge.net/'
}
}
/*
shadowJar {
relocate 'net.bytebuddy.agent', 'org.embeddedt.modernfix.testing.shadow.bytebuddyagent'
relocate 'org.objectweb.asm', 'org.embeddedt.modernfix.testing.shadow.asm'
}
shadowJar {
project.configurations.implementation.canBeResolved = true
configurations = [project.configurations.implementation]
}
*/
dependencies {
compileOnly "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
implementation "org.ow2.asm:asm-tree:9.1"
implementation "org.ow2.asm:asm-commons:9.1"
implementation "org.ow2.asm:asm-util:9.1"
//implementation('net.bytebuddy:byte-buddy-agent:1.12.22')
}
tasks.withType(JavaCompile) {
// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
// If Javadoc is generated, this must be specified in that task too.
options.encoding = "UTF-8"
}
jar {
manifest {
attributes(
"Premain-Class": "org.embeddedt.modernfix.testing.Agent",
"Can-Redefine-Classes": false,
"Can-Set-Native-Method-Prefix": false
)
}
}
/*
shadowJar {
archiveBaseName.set('modernfix-test-agent')
archiveClassifier.set('')
archiveVersion.set('v1')
}
*/
configurations {
agentJar {
canBeConsumed = true
canBeResolved = false
}
}
artifacts {
agentJar(jar)
}
/*
project.tasks.shadowJar.dependsOn build
defaultTasks 'shadowJar'
*/

View File

@ -1,61 +0,0 @@
package org.embeddedt.modernfix.testing;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.ListIterator;
public class Agent {
/**
* Simple agent that transforms Fabric Loader to never mark game JARs as system libraries.
*
* Ugly, but usable workaround for <a href="https://github.com/FabricMC/fabric-loader/issues/817">issue #817</a>
* on the Loader bug tracker.
*/
public static void premain(String args, Instrumentation instrumentation) {
instrumentation.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
if(className.equals("net/fabricmc/loader/impl/game/LibClassifier")) {
ClassNode node = new ClassNode();
ClassReader reader = new ClassReader(classfileBuffer);
reader.accept(node, 0);
for(MethodNode m : node.methods) {
if(m.name.equals("<init>")) {
ListIterator<AbstractInsnNode> iter = m.instructions.iterator();
int addMatches = 0;
while(iter.hasNext()) {
AbstractInsnNode n = iter.next();
if(n instanceof MethodInsnNode) {
MethodInsnNode invokeNode = (MethodInsnNode)n;
if(invokeNode.name.equals("add") && invokeNode.owner.equals("java/util/Set") && invokeNode.desc.equals("(Ljava/lang/Object;)Z")) {
addMatches++;
if(addMatches == 2) {
iter.set(new MethodInsnNode(Opcodes.INVOKESTATIC, "org/embeddedt/modernfix/testing/AgentHooks", "addLibraryWithCheck", "(Ljava/util/Set;Ljava/lang/Object;)Z", false));
break;
}
}
}
}
}
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
node.accept(writer);
byte[] finalArray = writer.toByteArray();
//dumpDebugClass(className, finalArray);
return finalArray;
}
return classfileBuffer;
}
});
}
}

View File

@ -1,17 +0,0 @@
package org.embeddedt.modernfix.testing;
import java.nio.file.Path;
import java.util.Set;
@SuppressWarnings("unused")
public class AgentHooks {
@SuppressWarnings({"unchecked", "rawtypes" })
public static boolean addLibraryWithCheck(Set pathSet, Object path) {
boolean shouldAdd;
if(path instanceof Path) {
shouldAdd = !((Path)path).toString().contains("minecraft-merged");
} else
shouldAdd = true;
return shouldAdd && pathSet.add(path);
}
}