Merge remote-tracking branch 'origin/1.21.1' into 1.21.4
This commit is contained in:
commit
717d2f6b88
|
|
@ -1,6 +1,6 @@
|
||||||
plugins {
|
plugins {
|
||||||
id "architectury-plugin" version "3.4-SNAPSHOT"
|
id "architectury-plugin" version "3.4-SNAPSHOT"
|
||||||
id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false
|
id "dev.architectury.loom" version "1.9-SNAPSHOT" apply false
|
||||||
id "maven-publish"
|
id "maven-publish"
|
||||||
id 'com.matthewprenger.cursegradle' version '1.4.0' apply false
|
id 'com.matthewprenger.cursegradle' version '1.4.0' apply false
|
||||||
id 'com.palantir.git-version' version '1.0.0'
|
id 'com.palantir.git-version' version '1.0.0'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package org.embeddedt.modernfix.common.mixin.bugfix.chunk_deadlock;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.level.gameevent.GameEvent;
|
||||||
|
import org.embeddedt.modernfix.ModernFix;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
|
||||||
|
@Mixin(Entity.class)
|
||||||
|
public class EntityMixin {
|
||||||
|
/**
|
||||||
|
* @author embeddedt
|
||||||
|
* @reason When an entity is added to the world via the worldgen load path (ChunkMap#postLoadProtoChunk calling
|
||||||
|
* ServerLevel#addWorldGenChunkEntities), attempts to add a passenger result in a deadlock when the sculk event
|
||||||
|
* tries to raytrace blocks. To fix this, we skip firing the sculk event if the chunk the entity is within is not
|
||||||
|
* loaded.
|
||||||
|
*/
|
||||||
|
@WrapWithCondition(method = "addPassenger", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;gameEvent(Lnet/minecraft/core/Holder;Lnet/minecraft/world/entity/Entity;)V"))
|
||||||
|
private boolean onlyAddIfSelfChunkLoaded(Entity instance, Holder<GameEvent> gameEvent, Entity entity) {
|
||||||
|
var chunkPos = instance.chunkPosition();
|
||||||
|
if (instance.level() instanceof ServerLevel serverLevel && serverLevel.getChunkSource().getChunkNow(chunkPos.x, chunkPos.z) == null) {
|
||||||
|
ModernFix.LOGGER.warn("Skipped emitting ENTITY_MOUNT game event for entity {} as it would cause deadlock", instance.toString());
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package org.embeddedt.modernfix.common.mixin.feature.blockentity_incorrect_thread;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.LevelHeightAccessor;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
|
import net.minecraft.world.level.chunk.UpgradeData;
|
||||||
|
import net.minecraft.world.level.levelgen.blending.BlendingData;
|
||||||
|
import org.embeddedt.modernfix.util.ConcurrencySanitizingMap;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Mutable;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Mixin(ChunkAccess.class)
|
||||||
|
public class ChunkAccessMixin {
|
||||||
|
@Shadow @Final @Mutable protected Map<BlockPos, BlockEntity> blockEntities;
|
||||||
|
|
||||||
|
@Inject(method = "<init>", at = @At("RETURN"))
|
||||||
|
private void wrapInConcurrencyDetector(ChunkPos chunkPos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor, Registry biomeRegistry, long inhabitedTime, LevelChunkSection[] sections, BlendingData blendingData, CallbackInfo ci) {
|
||||||
|
if (levelHeightAccessor instanceof Level level) {
|
||||||
|
this.blockEntities = new ConcurrencySanitizingMap<>(this.blockEntities, ((LevelThreadAccessor)level).getThread());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.embeddedt.modernfix.common.mixin.feature.blockentity_incorrect_thread;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(Level.class)
|
||||||
|
public interface LevelThreadAccessor {
|
||||||
|
@Accessor
|
||||||
|
Thread getThread();
|
||||||
|
}
|
||||||
|
|
@ -167,6 +167,7 @@ public class ModernFixEarlyConfig {
|
||||||
.put("mixin.perf.worldgen_allocation", false) // experimental
|
.put("mixin.perf.worldgen_allocation", false) // experimental
|
||||||
.put("mixin.feature.cause_lag_by_disabling_threads", false)
|
.put("mixin.feature.cause_lag_by_disabling_threads", false)
|
||||||
.put("mixin.bugfix.missing_block_entities", false)
|
.put("mixin.bugfix.missing_block_entities", false)
|
||||||
|
.put("mixin.feature.blockentity_incorrect_thread", false)
|
||||||
.put("mixin.perf.clear_mixin_classinfo", false)
|
.put("mixin.perf.clear_mixin_classinfo", false)
|
||||||
.put("mixin.perf.deduplicate_climate_parameters", false)
|
.put("mixin.perf.deduplicate_climate_parameters", false)
|
||||||
.put("mixin.bugfix.packet_leak", false)
|
.put("mixin.bugfix.packet_leak", false)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
package org.embeddedt.modernfix.util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map wrapper that throws if the map is ever accessed on the wrong thread.
|
||||||
|
*/
|
||||||
|
public class ConcurrencySanitizingMap<K, V> implements Map<K, V> {
|
||||||
|
private final Map<K, V> map;
|
||||||
|
private final Thread owner;
|
||||||
|
|
||||||
|
public ConcurrencySanitizingMap(Map<K, V> map, Thread owner) {
|
||||||
|
this.map = map;
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkThread() {
|
||||||
|
var current = Thread.currentThread();
|
||||||
|
if (current != owner) {
|
||||||
|
throw new IllegalStateException("Map is being accessed on thread " + current + " while owned by " + owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
checkThread();
|
||||||
|
return map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
checkThread();
|
||||||
|
return map.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
checkThread();
|
||||||
|
return map.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsValue(Object value) {
|
||||||
|
checkThread();
|
||||||
|
return map.containsValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(Object key) {
|
||||||
|
checkThread();
|
||||||
|
return map.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable V put(K key, V value) {
|
||||||
|
checkThread();
|
||||||
|
return map.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V remove(Object key) {
|
||||||
|
checkThread();
|
||||||
|
return map.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putAll(@NotNull Map<? extends K, ? extends V> m) {
|
||||||
|
checkThread();
|
||||||
|
map.putAll(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
checkThread();
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Set<K> keySet() {
|
||||||
|
checkThread();
|
||||||
|
return map.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Collection<V> values() {
|
||||||
|
checkThread();
|
||||||
|
return map.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Set<Entry<K, V>> entrySet() {
|
||||||
|
checkThread();
|
||||||
|
return map.entrySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,6 @@ import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
|
||||||
import net.fabricmc.loader.impl.gui.FabricGuiEntry;
|
import net.fabricmc.loader.impl.gui.FabricGuiEntry;
|
||||||
import net.fabricmc.loader.impl.gui.FabricStatusTree;
|
import net.fabricmc.loader.impl.gui.FabricStatusTree;
|
||||||
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
||||||
import org.embeddedt.modernfix.fabric.mappings.MappingsClearer;
|
|
||||||
import org.embeddedt.modernfix.spark.SparkLaunchProfiler;
|
import org.embeddedt.modernfix.spark.SparkLaunchProfiler;
|
||||||
import org.embeddedt.modernfix.util.CommonModUtil;
|
import org.embeddedt.modernfix.util.CommonModUtil;
|
||||||
|
|
||||||
|
|
@ -19,9 +18,6 @@ public class ModernFixPreLaunchFabric implements PreLaunchEntrypoint {
|
||||||
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_launch.OnFabric")) {
|
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_launch.OnFabric")) {
|
||||||
CommonModUtil.runWithoutCrash(() -> SparkLaunchProfiler.start("launch"), "Failed to start profiler");
|
CommonModUtil.runWithoutCrash(() -> SparkLaunchProfiler.start("launch"), "Failed to start profiler");
|
||||||
}
|
}
|
||||||
if(ModernFixMixinPlugin.instance.isOptionEnabled("perf.clear_fabric_mapping_tables.MappingsClearer")) {
|
|
||||||
MappingsClearer.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent launching with Continuity when dynamic resources is on
|
// Prevent launching with Continuity when dynamic resources is on
|
||||||
if(false && ModernFixMixinPlugin.instance.isOptionEnabled("perf.dynamic_resources.ContinuityCheck")
|
if(false && ModernFixMixinPlugin.instance.isOptionEnabled("perf.dynamic_resources.ContinuityCheck")
|
||||||
|
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
package org.embeddedt.modernfix.fabric.mappings;
|
|
||||||
|
|
||||||
import net.fabricmc.loader.api.*;
|
|
||||||
import net.fabricmc.loader.impl.launch.FabricLauncherBase;
|
|
||||||
import net.fabricmc.loader.impl.launch.MappingConfiguration;
|
|
||||||
import org.embeddedt.modernfix.util.CommonModUtil;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Designed for Fabric Loader 0.14.x, probably has issues on other versions. The entire thing is wrapped in a try-catch
|
|
||||||
* so it should never cause crashes, just fail to work.
|
|
||||||
*/
|
|
||||||
public class MappingsClearer {
|
|
||||||
private static final Version LOADER_015;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
LOADER_015 = Version.parse("0.15.0");
|
|
||||||
} catch (VersionParsingException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static void clear() {
|
|
||||||
// TODO: Port this to Fabric Loader 0.15
|
|
||||||
|
|
||||||
if(true) //FabricLoader.getInstance().isDevelopmentEnvironment())
|
|
||||||
return; // never do this in dev
|
|
||||||
|
|
||||||
Optional<Version> loaderVersion = FabricLoader.getInstance().getModContainer("fabricloader").map(m -> m.getMetadata().getVersion());
|
|
||||||
if(!loaderVersion.isPresent() || LOADER_015.compareTo(loaderVersion.get()) < 0) {
|
|
||||||
// Fabric Loader is probably too new, abort
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonModUtil.runWithoutCrash(() -> {
|
|
||||||
// For now, force the mapping resolver to be initialized. Fabric Loader 0.14.23 stops initializing it early,
|
|
||||||
// which means that we actually need to keep the TinyMappingFactory tree around for initialization to work
|
|
||||||
// later. We force init it now because then we can store less in memory.
|
|
||||||
// Comparing heap dumps on 0.14.23 suggests a savings of 20MB by doing it our way, since many mods will
|
|
||||||
// end up needing the mapping resolver.
|
|
||||||
// This will need to be revisited when https://github.com/FabricMC/fabric-loader/pull/812 is merged.
|
|
||||||
FabricLoader.getInstance().getMappingResolver();
|
|
||||||
|
|
||||||
// clear notch->intermediary mappings
|
|
||||||
MappingConfiguration config = FabricLauncherBase.getLauncher().getMappingConfiguration();
|
|
||||||
Field mappingsField = MappingConfiguration.class.getDeclaredField("mappings");
|
|
||||||
mappingsField.setAccessible(true);
|
|
||||||
//mappingsField.set(config, TinyMappingFactory.EMPTY_TREE);
|
|
||||||
|
|
||||||
// clear useless intermediary->intermediary mappings
|
|
||||||
MappingResolver resolver = FabricLoader.getInstance().getMappingResolver();
|
|
||||||
Class<?> targetResolverClz = Class.forName("net.fabricmc.loader.impl.MappingResolverImpl");
|
|
||||||
if(targetResolverClz.isAssignableFrom(resolver.getClass())) {
|
|
||||||
// hopefully still Loader 0.14.x, proceed
|
|
||||||
Class<?> namespaceDataClz = Class.forName("net.fabricmc.loader.impl.MappingResolverImpl$NamespaceData");
|
|
||||||
Constructor<?> constructor = namespaceDataClz.getDeclaredConstructor();
|
|
||||||
constructor.setAccessible(true);
|
|
||||||
Object theData = constructor.newInstance();
|
|
||||||
Field mapField = resolver.getClass().getDeclaredField("namespaceDataMap");
|
|
||||||
mapField.setAccessible(true);
|
|
||||||
Map<String, Object> theMap = (Map<String, Object>)mapField.get(resolver);
|
|
||||||
theMap.replace("intermediary", theData);
|
|
||||||
}
|
|
||||||
}, "Failed to clear mappings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
],
|
],
|
||||||
"depends": {
|
"depends": {
|
||||||
"minecraft": ">=1.16.2",
|
"minecraft": ">=1.16.2",
|
||||||
"fabricloader": ">=0.15.0"
|
"fabricloader": ">=0.16.10"
|
||||||
},
|
},
|
||||||
"breaks": {
|
"breaks": {
|
||||||
"dashloader": "<5.0.0-beta.1"
|
"dashloader": "<5.0.0-beta.1"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
org.gradle.jvmargs=-Xmx2G
|
org.gradle.jvmargs=-Xmx2G
|
||||||
|
|
||||||
junit_version=5.10.0-M1
|
junit_version=5.10.0-M1
|
||||||
mixinextras_version=0.3.2
|
mixinextras_version=0.4.1
|
||||||
|
|
||||||
mod_id=modernfix
|
mod_id=modernfix
|
||||||
minecraft_version=1.21.4
|
minecraft_version=1.21.4
|
||||||
|
|
@ -19,7 +19,7 @@ kubejs_version=1902.6.0-build.142
|
||||||
rhino_version=1902.2.2-build.268
|
rhino_version=1902.2.2-build.268
|
||||||
supported_minecraft_versions=1.21.4
|
supported_minecraft_versions=1.21.4
|
||||||
|
|
||||||
fabric_loader_version=0.16.9
|
fabric_loader_version=0.16.10
|
||||||
fabric_api_version=0.113.0+1.21.4
|
fabric_api_version=0.113.0+1.21.4
|
||||||
|
|
||||||
continuity_version=3.0.0-beta.4+1.20.2
|
continuity_version=3.0.0-beta.4+1.20.2
|
||||||
|
|
@ -29,7 +29,7 @@ diagonal_fences_version=4558828
|
||||||
|
|
||||||
spark_version=5759671
|
spark_version=5759671
|
||||||
|
|
||||||
use_fabric_api_at_runtime=false
|
use_fabric_api_at_runtime=true
|
||||||
|
|
||||||
# Look up maven coordinates when changing shadow_version
|
# Look up maven coordinates when changing shadow_version
|
||||||
shadow_version=7.1.2
|
shadow_version=7.1.2
|
||||||
|
|
|
||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user