Skip to content

Commit 51f273f

Browse files
committed
Merge 1.20 into 1.21.1
2 parents 334a91f + a73dd5e commit 51f273f

8 files changed

Lines changed: 296 additions & 56 deletions

File tree

.github/ISSUE_TEMPLATE/bug_report.yml

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,51 +4,75 @@ body:
44
- type: markdown
55
attributes:
66
value: >-
7-
**Note: This issue tracker is not intended for support requests!** If you need help with crashes or other issues, then
8-
you should [ask on our Discord server](https://discord.gg/rN9Y7caguP) instead. Unless you are certain that you
9-
have found a defect, and you are able to point to where the problem is, you should not open an issue.
10-
<br><br>
11-
Additionally, please make sure you have done the following:
7+
**Need help?** Ask on [Discord](https://discord.gg/rN9Y7caguP) instead of opening an issue.
128
13-
- **Have you ensured that all of your mods (including ModernFix) are up-to-date?** The latest version of ModernFix
14-
can always be found [on Modrinth](https://modrinth.com/mod/modernfix).
15-
16-
- **Have you used the [search tool](https://github.com/embeddedt/ModernFix/issues) to check whether your issue
17-
has already been reported?** If it has been, then consider adding more information to the existing issue instead.
18-
19-
- **Have you determined the minimum set of instructions to reproduce the issue?** If your problem only occurs
20-
with other mods installed, then you should narrow down exactly which mods are causing the issue. Please do not
21-
provide your entire list of mods to us and expect that we will be able to figure out the problem.
9+
**Issues that do not meet the requirements below (or are otherwise impossible to address with the given info) will be closed without investigation.**
10+
- type: checkboxes
11+
id: confirmations
12+
attributes:
13+
label: Checklist
14+
options:
15+
- label: I am reporting a defect, not asking for help
16+
required: true
17+
- label: I have searched existing issues and this has not been reported
18+
required: true
19+
- label: I have reduced my mod list to the minimum required to reproduce this issue (see below)
20+
required: true
2221
- type: textarea
2322
id: description
2423
attributes:
2524
label: Bug Description
2625
description: >-
27-
Use this section to describe the issue you are experiencing in as much depth as possible. The description should
28-
explain what behavior you were expecting, and why you believe the issue to be a bug. If the issue you are reporting
29-
only occurs with specific mods installed, then provide the name and version of each mod.
26+
Describe the issue in detail. Be sure to include what you expected to happen and what actually happened.
27+
validations:
28+
required: true
29+
- type: textarea
30+
id: minimal-mods
31+
attributes:
32+
label: Minimal Mod List
33+
description: >-
34+
List ONLY the mods required to reproduce this issue. Maintainers have debugging tools that help them
35+
locate problems quickly, but these generally don't work well in modpacks or large mod sets.
36+
A minimal list should typically contain fewer than 10 mods.
37+
38+
Reports with large mod lists will likely be closed without investigation, unless the problem is very clear.
39+
40+
If you don't know which mods are causing your problem, use binary search:
3041
31-
**Hint:** If you have any screenshots, videos, or other information that you feel is necessary to
32-
explain the issue, you can attach them here.
42+
1. Remove half your mods
43+
44+
2. Test if the issue still occurs
45+
46+
3. If yes, remove half again. If no, restore the last removed half and repeat from step 1.
47+
48+
4. Repeat until only the necessary mods remain
49+
placeholder: "- ModernFix 5.x.x\n- SomeMod 1.2.3"
50+
validations:
51+
required: true
3352
- type: textarea
3453
id: description-reproduction-steps
3554
attributes:
3655
label: Reproduction Steps
3756
description: >-
38-
Provide as much information as possible on how to reproduce this bug. Make sure your instructions are as clear and
39-
concise as possible, because other people will need to be able to follow your guide in order to re-create the issue.
40-
41-
**Hint:** A common way to fill this section out is to write a step-by-step guide.
57+
Provide clear steps to reproduce the bug. Each step should be a single concrete action.
58+
59+
Maintainers are busy and need to be able to quickly replicate your problem. Your reproduction steps should be
60+
clear enough for someone who is unfamiliar with your mods to follow in 5 minutes or less (not counting time
61+
to launch the game).
62+
63+
Providing vague steps is likely to result in the issue being closed.
64+
65+
placeholder: "1. \n2. \n3. "
4266
validations:
4367
required: true
4468
- type: textarea
45-
id: log-file
69+
id: diagnostic-info
4670
attributes:
47-
label: Log File
71+
label: Diagnostic Info
4872
description: >-
49-
**Hint:** You can usually find the log files within the folder `.minecraft/logs`. Most often, you will want the `latest.log`
50-
file, since that file belongs to the last played session of the game.
51-
placeholder: >-
52-
Drag-and-drop the log file here.
73+
Drag and drop `latest.log` from `.minecraft/logs/` for the session where the issue occurred.
74+
Do not paste log text inline. Issues without a valid `latest.log` will be closed.
75+
76+
If a crash occurred, also attach the relevant file from `.minecraft/crash-reports/`.
5377
validations:
5478
required: true

src/main/java/org/embeddedt/modernfix/ModernFix.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import net.minecraft.SharedConstants;
44
import net.minecraft.Util;
5+
import net.minecraft.client.Minecraft;
56
import net.minecraft.server.MinecraftServer;
67
import net.minecraft.server.level.ChunkMap;
78
import net.minecraft.server.level.ServerLevel;
@@ -51,6 +52,8 @@ public static void runAuditIfRequested() {
5152
if (auditAndExit || Boolean.getBoolean("modernfix.auditMixinsAtStart")) {
5253
MixinEnvironment.getCurrentEnvironment().audit();
5354
if (auditAndExit) {
55+
// Prevents Crash Assistant from treating mixin audit as a crash
56+
Minecraft.getInstance().stop();
5457
System.exit(0);
5558
}
5659
}

src/main/java/org/embeddedt/modernfix/common/mixin/perf/attribute_supplier_dedup/AttributeSupplierMixin.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.embeddedt.modernfix.common.mixin.perf.attribute_supplier_dedup;
22

3+
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
34
import net.minecraft.core.Holder;
45
import net.minecraft.world.entity.ai.attributes.Attribute;
56
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
@@ -23,11 +24,11 @@ public class AttributeSupplierMixin {
2324

2425
/**
2526
* @author embeddedt
26-
* @reason Java 9's Map.of() implementation is significantly more compact than ImmutableMap, and we do not
27+
* @reason more compact than ImmutableMap due to less wrapper objects, and we do not
2728
* care about insertion order in this context
2829
*/
2930
@Inject(method = "<init>", at = @At("RETURN"))
3031
private void useCompactJavaMap(Map<Holder<Attribute>, AttributeInstance> instances, CallbackInfo ci) {
31-
this.instances = Map.copyOf(this.instances);
32+
this.instances = new Object2ObjectOpenHashMap<>(this.instances);
3233
}
33-
}
34+
}

src/main/java/org/embeddedt/modernfix/common/mixin/perf/optimize_surface_rules/SequenceRuleSourceMixin.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,25 @@
33
import net.minecraft.world.level.levelgen.SurfaceRules;
44
import org.embeddedt.modernfix.world.gen.SurfaceRuleOptimizer;
55
import org.spongepowered.asm.mixin.Mixin;
6+
import org.spongepowered.asm.mixin.Unique;
67
import org.spongepowered.asm.mixin.injection.At;
78
import org.spongepowered.asm.mixin.injection.Inject;
89
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
910

1011
@Mixin(targets = {"net/minecraft/world/level/levelgen/SurfaceRules$SequenceRuleSource"})
1112
public class SequenceRuleSourceMixin {
13+
@Unique
14+
private transient SurfaceRules.RuleSource mfix$optimizedSource;
15+
1216
@Inject(method = "apply(Lnet/minecraft/world/level/levelgen/SurfaceRules$Context;)Lnet/minecraft/world/level/levelgen/SurfaceRules$SurfaceRule;", at = @At("HEAD"), cancellable = true)
1317
private void optimizeApply(SurfaceRules.Context context, CallbackInfoReturnable<SurfaceRules.SurfaceRule> cir) {
14-
var optimized = SurfaceRuleOptimizer.optimizeSequenceRule((SurfaceRules.SequenceRuleSource)(Object) this, context);
15-
if (optimized != null) {
16-
cir.setReturnValue(optimized);
18+
var optimizedSource = mfix$optimizedSource;
19+
if (optimizedSource == null) {
20+
mfix$optimizedSource = optimizedSource = SurfaceRuleOptimizer.optimizeSequenceRuleSource((SurfaceRules.SequenceRuleSource)(Object) this);
21+
}
22+
// Must check for it not being ourselves, to avoid infinite reentrance
23+
if (optimizedSource != (Object)this) {
24+
cir.setReturnValue(optimizedSource.apply(context));
1725
}
1826
}
1927
}

src/main/java/org/embeddedt/modernfix/core/ModernFixMixinPlugin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.apache.logging.log4j.Logger;
66
import org.embeddedt.modernfix.core.config.ModernFixEarlyConfig;
77
import org.embeddedt.modernfix.core.config.Option;
8+
import org.embeddedt.modernfix.core.launchplugin.CoreLaunchPluginService;
89
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
910
import org.embeddedt.modernfix.world.ThreadDumper;
1011
import org.objectweb.asm.Opcodes;
@@ -109,7 +110,7 @@ private void computeBetterThreadCount() {
109110

110111
@Override
111112
public void onLoad(String mixinPackage) {
112-
113+
CoreLaunchPluginService.install();
113114
}
114115

115116
@Override
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package org.embeddedt.modernfix.core.launchplugin;
2+
3+
import cpw.mods.modlauncher.LaunchPluginHandler;
4+
import cpw.mods.modlauncher.Launcher;
5+
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
6+
import org.embeddedt.modernfix.core.launchplugin.transformer.CapabilityProviderTransformer;
7+
import org.objectweb.asm.Type;
8+
import org.objectweb.asm.tree.ClassNode;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
12+
import java.lang.reflect.Field;
13+
import java.util.EnumSet;
14+
import java.util.LinkedHashMap;
15+
import java.util.Map;
16+
17+
public class CoreLaunchPluginService implements ILaunchPluginService {
18+
private static final Logger LOGGER = LoggerFactory.getLogger("ModernFixLaunchPlugin");
19+
20+
public static void install() {
21+
try {
22+
Field launchPluginsField = Launcher.class.getDeclaredField("launchPlugins");
23+
launchPluginsField.setAccessible(true);
24+
LaunchPluginHandler launchPluginHandler = (LaunchPluginHandler) launchPluginsField.get(Launcher.INSTANCE);
25+
Field pluginsField = LaunchPluginHandler.class.getDeclaredField("plugins");
26+
pluginsField.setAccessible(true);
27+
Map<String, ILaunchPluginService> plugins = (Map<String, ILaunchPluginService>)pluginsField.get(launchPluginHandler);
28+
var service = new CoreLaunchPluginService();
29+
try {
30+
plugins.put(service.name(), service);
31+
} catch (Exception e) {
32+
var newMap = new LinkedHashMap<>(plugins);
33+
newMap.put(service.name(), service);
34+
pluginsField.set(launchPluginHandler, newMap);
35+
}
36+
} catch(Exception e) {
37+
LOGGER.error("Error installing launch plugin service", e);
38+
}
39+
}
40+
41+
@Override
42+
public String name() {
43+
return "modernfix";
44+
}
45+
46+
private static final EnumSet<Phase> GO = EnumSet.of(Phase.AFTER);
47+
private static final EnumSet<Phase> NOGO = EnumSet.noneOf(Phase.class);
48+
49+
private static final Map<String, Transformer> TRANSFORMERS = Map.of(
50+
"net.minecraftforge.common.capabilities.CapabilityProvider", new CapabilityProviderTransformer()
51+
);
52+
53+
@Override
54+
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty) {
55+
return !isEmpty && TRANSFORMERS.containsKey(classType.getClassName()) ? GO : NOGO;
56+
}
57+
58+
@Override
59+
public int processClassWithFlags(Phase phase, ClassNode classNode, Type classType, String reason) {
60+
if (classNode == null) {
61+
return 0;
62+
}
63+
var transformer = TRANSFORMERS.get(classType.getClassName());
64+
if (transformer == null) {
65+
return 0;
66+
}
67+
return transformer.transform(classNode);
68+
}
69+
70+
public interface Transformer {
71+
int transform(ClassNode node);
72+
}
73+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package org.embeddedt.modernfix.core.launchplugin.transformer;
2+
3+
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
4+
import org.embeddedt.modernfix.core.launchplugin.CoreLaunchPluginService;
5+
import org.objectweb.asm.Opcodes;
6+
import org.objectweb.asm.tree.*;
7+
8+
/**
9+
* Injects an early-return into {@code CapabilityProvider#areCapsCompatible} that skips lazy
10+
* initialization when both providers are lazy, uninitialized, of the same class, and carry equal
11+
* {@code lazyData}. In that case the capabilities are trivially compatible and the full init can
12+
* be avoided.
13+
* @author embeddedt
14+
*/
15+
public class CapabilityProviderTransformer implements CoreLaunchPluginService.Transformer {
16+
private static final String OWNER = "net/minecraftforge/common/capabilities/CapabilityProvider";
17+
private static final String COMPOUND_TAG = "net/minecraft/nbt/CompoundTag";
18+
private static final String HELPER_NAME = "mfix$skipLazyInit";
19+
private static final String HELPER_DESC = "(L" + OWNER + ";L" + OWNER + ";)Z";
20+
21+
@Override
22+
public int transform(ClassNode node) {
23+
String targetDesc = "(L" + OWNER + ";)Z";
24+
for (MethodNode method : node.methods) {
25+
if (method.name.equals("areCapsCompatible") && method.desc.equals(targetDesc)) {
26+
injectCall(method);
27+
node.methods.add(buildHelper());
28+
break;
29+
}
30+
}
31+
return ILaunchPluginService.ComputeFlags.COMPUTE_FRAMES;
32+
}
33+
34+
private MethodNode buildHelper() {
35+
MethodNode mn = new MethodNode(
36+
Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
37+
HELPER_NAME, HELPER_DESC, null, null);
38+
InsnList il = mn.instructions;
39+
LabelNode returnFalse = new LabelNode();
40+
41+
// if (!self.isLazy) goto returnFalse
42+
il.add(new VarInsnNode(Opcodes.ALOAD, 0));
43+
il.add(new FieldInsnNode(Opcodes.GETFIELD, OWNER, "isLazy", "Z"));
44+
il.add(new JumpInsnNode(Opcodes.IFEQ, returnFalse));
45+
46+
// if (self.initialized) goto returnFalse
47+
il.add(new VarInsnNode(Opcodes.ALOAD, 0));
48+
il.add(new FieldInsnNode(Opcodes.GETFIELD, OWNER, "initialized", "Z"));
49+
il.add(new JumpInsnNode(Opcodes.IFNE, returnFalse));
50+
51+
// if (!other.isLazy) goto returnFalse
52+
il.add(new VarInsnNode(Opcodes.ALOAD, 1));
53+
il.add(new FieldInsnNode(Opcodes.GETFIELD, OWNER, "isLazy", "Z"));
54+
il.add(new JumpInsnNode(Opcodes.IFEQ, returnFalse));
55+
56+
// if (other.initialized) goto returnFalse
57+
il.add(new VarInsnNode(Opcodes.ALOAD, 1));
58+
il.add(new FieldInsnNode(Opcodes.GETFIELD, OWNER, "initialized", "Z"));
59+
il.add(new JumpInsnNode(Opcodes.IFNE, returnFalse));
60+
61+
// if (other.getClass() != self.getClass()) goto returnFalse
62+
il.add(new VarInsnNode(Opcodes.ALOAD, 1));
63+
il.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false));
64+
il.add(new VarInsnNode(Opcodes.ALOAD, 0));
65+
il.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false));
66+
il.add(new JumpInsnNode(Opcodes.IF_ACMPNE, returnFalse));
67+
68+
// if (!Objects.equals(self.lazyData, other.lazyData)) goto returnFalse
69+
il.add(new VarInsnNode(Opcodes.ALOAD, 0));
70+
il.add(new FieldInsnNode(Opcodes.GETFIELD, OWNER, "lazyData", "L" + COMPOUND_TAG + ";"));
71+
il.add(new VarInsnNode(Opcodes.ALOAD, 1));
72+
il.add(new FieldInsnNode(Opcodes.GETFIELD, OWNER, "lazyData", "L" + COMPOUND_TAG + ";"));
73+
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/util/Objects", "equals", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false));
74+
il.add(new JumpInsnNode(Opcodes.IFEQ, returnFalse));
75+
76+
il.add(new InsnNode(Opcodes.ICONST_1));
77+
il.add(new InsnNode(Opcodes.IRETURN));
78+
79+
il.add(returnFalse);
80+
il.add(new InsnNode(Opcodes.ICONST_0));
81+
il.add(new InsnNode(Opcodes.IRETURN));
82+
83+
mn.maxLocals = 2;
84+
mn.maxStack = 2;
85+
return mn;
86+
}
87+
88+
private void injectCall(MethodNode method) {
89+
InsnList il = new InsnList();
90+
LabelNode skip = new LabelNode();
91+
92+
il.add(new VarInsnNode(Opcodes.ALOAD, 0));
93+
il.add(new VarInsnNode(Opcodes.ALOAD, 1));
94+
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, OWNER, HELPER_NAME, HELPER_DESC, false));
95+
il.add(new JumpInsnNode(Opcodes.IFEQ, skip));
96+
il.add(new InsnNode(Opcodes.ICONST_1));
97+
il.add(new InsnNode(Opcodes.IRETURN));
98+
il.add(skip);
99+
100+
method.instructions.insert(il);
101+
}
102+
}

0 commit comments

Comments
 (0)