Merge remote-tracking branch 'origin/1.20' into 1.21.1
This commit is contained in:
commit
49a88c8bba
|
|
@ -0,0 +1,30 @@
|
||||||
|
package org.embeddedt.modernfix.common.mixin.perf.attribute_supplier_dedup;
|
||||||
|
|
||||||
|
import net.minecraft.world.entity.ai.attributes.Attribute;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||||
|
import org.embeddedt.modernfix.entity.AttributeInstanceTemplates;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Mixin(AttributeSupplier.Builder.class)
|
||||||
|
public class AttributeSupplierBuilderMixin {
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private Map<Attribute, AttributeInstance> builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author embeddedt
|
||||||
|
* @reason canonicalize identical AttributeInstance templates, many entities are created with the same values
|
||||||
|
*/
|
||||||
|
@Inject(method = "build", at = @At(value = "NEW", target = "(Ljava/util/Map;)Lnet/minecraft/world/entity/ai/attributes/AttributeSupplier;"))
|
||||||
|
private void deduplicateInstances(CallbackInfoReturnable<AttributeSupplier> cir) {
|
||||||
|
this.builder.replaceAll((a, i) -> AttributeInstanceTemplates.intern(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package org.embeddedt.modernfix.common.mixin.perf.attribute_supplier_dedup;
|
||||||
|
|
||||||
|
import net.minecraft.world.entity.ai.attributes.Attribute;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||||
|
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(AttributeSupplier.class)
|
||||||
|
public class AttributeSupplierMixin {
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
@Mutable
|
||||||
|
private Map<Attribute, AttributeInstance> instances;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author embeddedt
|
||||||
|
* @reason Java 9's Map.of() implementation is significantly more compact than ImmutableMap, and we do not
|
||||||
|
* care about insertion order in this context
|
||||||
|
*/
|
||||||
|
@Inject(method = "<init>", at = @At("RETURN"))
|
||||||
|
private void useCompactJavaMap(Map<Attribute, AttributeInstance> instances, CallbackInfo ci) {
|
||||||
|
this.instances = Map.copyOf(this.instances);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -35,7 +35,7 @@ public class BlockStateDataMixin {
|
||||||
t = compactTag(ct);
|
t = compactTag(ct);
|
||||||
}
|
}
|
||||||
t = TAG_INTERNER.addOrGet(t);
|
t = TAG_INTERNER.addOrGet(t);
|
||||||
entries[i++] = Map.entry(key, t);
|
entries[i++] = Map.entry(key.intern(), t);
|
||||||
}
|
}
|
||||||
return new CompoundTag(Map.ofEntries(entries));
|
return new CompoundTag(Map.ofEntries(entries));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,8 @@ public class ModelManagerMixin implements IExtendedModelManager {
|
||||||
@ModifyArg(method = "loadBlockModels", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;thenCompose(Ljava/util/function/Function;)Ljava/util/concurrent/CompletableFuture;", ordinal = 0), index = 0)
|
@ModifyArg(method = "loadBlockModels", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;thenCompose(Ljava/util/function/Function;)Ljava/util/concurrent/CompletableFuture;", ordinal = 0), index = 0)
|
||||||
private static Function<Map<ResourceLocation, Resource>, ? extends CompletionStage<Map<ResourceLocation, BlockModel>>> deferBlockModelLoad(Function<Map<ResourceLocation, Resource>, ? extends CompletionStage<Map<ResourceLocation, BlockModel>>> fn, @Local(ordinal = 0, argsOnly = true) ResourceManager manager) {
|
private static Function<Map<ResourceLocation, Resource>, ? extends CompletionStage<Map<ResourceLocation, BlockModel>>> deferBlockModelLoad(Function<Map<ResourceLocation, Resource>, ? extends CompletionStage<Map<ResourceLocation, BlockModel>>> fn, @Local(ordinal = 0, argsOnly = true) ResourceManager manager) {
|
||||||
return resourceMap -> {
|
return resourceMap -> {
|
||||||
var cache = CacheUtil.<ResourceLocation, BlockModel>simpleCacheForLambda(location -> loadSingleBlockModel(manager, location), 100L);
|
var fallbackModel = BlockModel.fromString(ModelBakery.MISSING_MODEL_MESH);
|
||||||
|
var cache = CacheUtil.<ResourceLocation, BlockModel>simpleCacheForLambda(location -> loadSingleBlockModel(manager, location, fallbackModel), 100L);
|
||||||
return CompletableFuture.completedFuture(Maps.asMap(Set.copyOf(resourceMap.keySet()), location -> cache.getUnchecked(location)));
|
return CompletableFuture.completedFuture(Maps.asMap(Set.copyOf(resourceMap.keySet()), location -> cache.getUnchecked(location)));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -81,13 +82,15 @@ public class ModelManagerMixin implements IExtendedModelManager {
|
||||||
return ImmutableList.of();
|
return ImmutableList.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BlockModel loadSingleBlockModel(ResourceManager manager, ResourceLocation location) {
|
private static BlockModel loadSingleBlockModel(ResourceManager manager, ResourceLocation location, BlockModel fallbackModel) {
|
||||||
return manager.getResource(location).map(resource -> {
|
return manager.getResource(location).map(resource -> {
|
||||||
try (BufferedReader reader = resource.openAsReader()) {
|
try (BufferedReader reader = resource.openAsReader()) {
|
||||||
return BlockModel.fromStream(reader);
|
return BlockModel.fromStream(reader);
|
||||||
} catch(IOException e) {
|
} catch (Exception e) {
|
||||||
ModernFix.LOGGER.error("Couldn't load model", e);
|
// We must return some nonnull value to avoid breaking the map convention. The easiest solution
|
||||||
return null;
|
// is to just return a missing model template.
|
||||||
|
ModernFix.LOGGER.error("Couldn't load model {}, substituting missing", location, e);
|
||||||
|
return fallbackModel;
|
||||||
}
|
}
|
||||||
}).orElse(null);
|
}).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package org.embeddedt.modernfix.entity;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.Hash;
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class AttributeInstanceTemplates {
|
||||||
|
private static final ObjectOpenCustomHashSet<AttributeInstance> INTERNER = new ObjectOpenCustomHashSet<>(new Hash.Strategy<>() {
|
||||||
|
@Override
|
||||||
|
public int hashCode(AttributeInstance o) {
|
||||||
|
if (o == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int h = o.getAttribute().hashCode();
|
||||||
|
h = 31 * h + Double.hashCode(o.getBaseValue());
|
||||||
|
h = 31 * h + o.getModifiers().hashCode();
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(AttributeInstance a, AttributeInstance b) {
|
||||||
|
if (a == b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (a == null || b == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return a.getAttribute() == b.getAttribute()
|
||||||
|
&& a.getBaseValue() == b.getBaseValue()
|
||||||
|
&& a.getModifiers().equals(b.getModifiers());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static AttributeInstance intern(AttributeInstance a) {
|
||||||
|
if (a == null || a.getClass() != AttributeInstance.class) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
synchronized (INTERNER) {
|
||||||
|
return INTERNER.addOrGet(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user