Merge remote-tracking branch 'origin/1.18' into 1.19.2
This commit is contained in:
commit
c9a48eb832
|
|
@ -62,6 +62,7 @@ repositories {
|
||||||
maven { // CTM
|
maven { // CTM
|
||||||
url "https://maven.tterrag.com/"
|
url "https://maven.tterrag.com/"
|
||||||
}
|
}
|
||||||
|
maven { url "https://maven.shedaniel.me" }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
@ -91,6 +92,7 @@ dependencies {
|
||||||
modRuntimeOnly("curse.maven:jei-238222:4405346")
|
modRuntimeOnly("curse.maven:jei-238222:4405346")
|
||||||
|
|
||||||
modCompileOnly("curse.maven:jeresources-240630:3951643")
|
modCompileOnly("curse.maven:jeresources-240630:3951643")
|
||||||
|
modCompileOnly "me.shedaniel:RoughlyEnoughItems-forge:${rei_version}"
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile) {
|
||||||
|
|
@ -156,7 +158,7 @@ curseforge {
|
||||||
id = "790626"
|
id = "790626"
|
||||||
changelog = '[Changelog is not currently available]'
|
changelog = '[Changelog is not currently available]'
|
||||||
changelogType = "markdown"
|
changelogType = "markdown"
|
||||||
releaseType = "beta"
|
releaseType = "release"
|
||||||
addGameVersion "Forge"
|
addGameVersion "Forge"
|
||||||
addGameVersion minecraft_version
|
addGameVersion minecraft_version
|
||||||
mainArtifact remapJar
|
mainArtifact remapJar
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,4 @@ forge_version=1.19.2-43.2.0
|
||||||
parchment_version=2022.11.27
|
parchment_version=2022.11.27
|
||||||
refined_storage_version=4392788
|
refined_storage_version=4392788
|
||||||
jei_version=11.6.0.1011
|
jei_version=11.6.0.1011
|
||||||
|
rei_version=9.1.591
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,10 @@ public class ModernFixClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||||
public void onMultiplayerConnect(ScreenEvent.Opening event) {
|
public void onMultiplayerConnect(ScreenEvent.Init.Pre event) {
|
||||||
if(event.getNewScreen() instanceof ConnectScreen && !event.isCanceled()) {
|
if(event.getScreen() instanceof ConnectScreen && !event.isCanceled()) {
|
||||||
worldLoadStartTime = System.nanoTime();
|
worldLoadStartTime = System.nanoTime();
|
||||||
} else if (event.getNewScreen() instanceof TitleScreen && gameStartTimeSeconds < 0) {
|
} else if (event.getScreen() instanceof TitleScreen && gameStartTimeSeconds < 0) {
|
||||||
gameStartTimeSeconds = ManagementFactory.getRuntimeMXBean().getUptime() / 1000f;
|
gameStartTimeSeconds = ManagementFactory.getRuntimeMXBean().getUptime() / 1000f;
|
||||||
ModernFix.LOGGER.warn("Game took " + gameStartTimeSeconds + " seconds to start");
|
ModernFix.LOGGER.warn("Game took " + gameStartTimeSeconds + " seconds to start");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ public class ModernFixEarlyConfig {
|
||||||
this.addMixinRule("feature.branding", true);
|
this.addMixinRule("feature.branding", true);
|
||||||
this.addMixinRule("feature.measure_time", true);
|
this.addMixinRule("feature.measure_time", true);
|
||||||
this.addMixinRule("feature.reduce_loading_screen_freezes", false);
|
this.addMixinRule("feature.reduce_loading_screen_freezes", false);
|
||||||
|
this.addMixinRule("feature.direct_stack_trace", false);
|
||||||
this.addMixinRule("perf.fast_registry_validation", true);
|
this.addMixinRule("perf.fast_registry_validation", true);
|
||||||
this.addMixinRule("perf.use_integrated_resources", true);
|
this.addMixinRule("perf.use_integrated_resources", true);
|
||||||
this.addMixinRule("perf.remove_biome_temperature_cache", true);
|
this.addMixinRule("perf.remove_biome_temperature_cache", true);
|
||||||
|
|
@ -45,9 +46,9 @@ public class ModernFixEarlyConfig {
|
||||||
this.addMixinRule("perf.faster_texture_stitching", true);
|
this.addMixinRule("perf.faster_texture_stitching", true);
|
||||||
/* off by default in 1.18 because it doesn't work as well */
|
/* off by default in 1.18 because it doesn't work as well */
|
||||||
this.addMixinRule("perf.faster_singleplayer_load", false);
|
this.addMixinRule("perf.faster_singleplayer_load", false);
|
||||||
/* Keep this off if JEI isn't installed to prevent breaking vanilla gameplay */
|
/* Keep this off if JEI/REI isn't installed to prevent breaking vanilla gameplay */
|
||||||
Optional<ModInfo> jeiMod = FMLLoader.getLoadingModList().getMods().stream().filter(mod -> mod.getModId().equals("jei")).findFirst();
|
Optional<ModInfo> jeiMod = FMLLoader.getLoadingModList().getMods().stream().filter(mod -> mod.getModId().equals("jei")).findFirst();
|
||||||
this.addMixinRule("perf.blast_search_trees", jeiMod.isPresent() && jeiMod.get().getVersion().getMajorVersion() >= 10);
|
this.addMixinRule("perf.blast_search_trees", (jeiMod.isPresent() && jeiMod.get().getVersion().getMajorVersion() >= 10) || FMLLoader.getLoadingModList().getModFileById("roughlyenoughitems") != null);
|
||||||
this.addMixinRule("safety", true);
|
this.addMixinRule("safety", true);
|
||||||
this.addMixinRule("launch.transformer_cache", false);
|
this.addMixinRule("launch.transformer_cache", false);
|
||||||
this.addMixinRule("launch.class_search_cache", true);
|
this.addMixinRule("launch.class_search_cache", true);
|
||||||
|
|
@ -55,8 +56,9 @@ public class ModernFixEarlyConfig {
|
||||||
/* Mod compat */
|
/* Mod compat */
|
||||||
disableIfModPresent("mixin.perf.thread_priorities", "smoothboot");
|
disableIfModPresent("mixin.perf.thread_priorities", "smoothboot");
|
||||||
disableIfModPresent("mixin.perf.async_jei", "modernui");
|
disableIfModPresent("mixin.perf.async_jei", "modernui");
|
||||||
disableIfModPresent("mixin.perf.compress_biome_container", "chocolate");
|
disableIfModPresent("mixin.perf.compress_biome_container", "chocolate", "betterendforge");
|
||||||
disableIfModPresent("mixin.bugfix.mc218112", "performant");
|
disableIfModPresent("mixin.bugfix.mc218112", "performant");
|
||||||
|
disableIfModPresent("mixin.perf.faster_baking", "touhou_little_maid");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disableIfModPresent(String configName, String... ids) {
|
private void disableIfModPresent(String configName, String... ids) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package org.embeddedt.modernfix.mixin.feature.direct_stack_trace;
|
||||||
|
|
||||||
|
import net.minecraft.CrashReport;
|
||||||
|
import net.minecraft.CrashReportCategory;
|
||||||
|
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(CrashReport.class)
|
||||||
|
public class CrashReportMixin {
|
||||||
|
@Shadow @Final private Throwable exception;
|
||||||
|
|
||||||
|
@Inject(method = "addCategory(Ljava/lang/String;I)Lnet/minecraft/CrashReportCategory;", at = @At(value = "INVOKE", target = "Ljava/io/PrintStream;println(Ljava/lang/String;)V"))
|
||||||
|
private void dumpStacktrace(String s, int i, CallbackInfoReturnable<CrashReportCategory> cir) {
|
||||||
|
new Exception("ModernFix crash stacktrace").printStackTrace();
|
||||||
|
if(this.exception != null)
|
||||||
|
this.exception.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import net.minecraftforge.fml.ModList;
|
||||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||||
import org.embeddedt.modernfix.searchtree.DummySearchTree;
|
import org.embeddedt.modernfix.searchtree.DummySearchTree;
|
||||||
import org.embeddedt.modernfix.searchtree.JEIBackedSearchTree;
|
import org.embeddedt.modernfix.searchtree.JEIBackedSearchTree;
|
||||||
|
import org.embeddedt.modernfix.searchtree.REIBackedSearchTree;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
@ -24,7 +25,10 @@ public class MinecraftMixin {
|
||||||
private void replaceSearchTrees(CallbackInfo ci) {
|
private void replaceSearchTrees(CallbackInfo ci) {
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
Optional<? extends ModContainer> jeiContainer = ModList.get().getModContainerById("jei");
|
Optional<? extends ModContainer> jeiContainer = ModList.get().getModContainerById("jei");
|
||||||
if(jeiContainer.isPresent() && jeiContainer.get().getModInfo().getVersion().getMajorVersion() >= 10) {
|
if(ModList.get().isLoaded("roughlyenoughitems")) {
|
||||||
|
this.searchRegistry.register(SearchRegistry.CREATIVE_NAMES, list -> new REIBackedSearchTree(false));
|
||||||
|
this.searchRegistry.register(SearchRegistry.CREATIVE_TAGS, list -> new REIBackedSearchTree(true));
|
||||||
|
} else if(jeiContainer.isPresent() && jeiContainer.get().getModInfo().getVersion().getMajorVersion() >= 10) {
|
||||||
this.searchRegistry.register(SearchRegistry.CREATIVE_NAMES, list -> new JEIBackedSearchTree(false));
|
this.searchRegistry.register(SearchRegistry.CREATIVE_NAMES, list -> new JEIBackedSearchTree(false));
|
||||||
this.searchRegistry.register(SearchRegistry.CREATIVE_TAGS, list -> new JEIBackedSearchTree(true));
|
this.searchRegistry.register(SearchRegistry.CREATIVE_TAGS, list -> new JEIBackedSearchTree(true));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,77 +1,20 @@
|
||||||
package org.embeddedt.modernfix.mixin.perf.faster_baking;
|
package org.embeddedt.modernfix.mixin.perf.faster_baking;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.renderer.block.BlockModelShaper;
|
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
|
||||||
import net.minecraft.client.resources.model.ModelBakery;
|
import net.minecraft.client.resources.model.ModelBakery;
|
||||||
import net.minecraft.client.resources.model.ModelManager;
|
import net.minecraft.client.resources.model.ModelManager;
|
||||||
import net.minecraft.client.renderer.texture.AtlasSet;
|
|
||||||
import net.minecraft.client.renderer.texture.TextureManager;
|
|
||||||
import net.minecraft.util.profiling.ProfilerFiller;
|
import net.minecraft.util.profiling.ProfilerFiller;
|
||||||
import net.minecraft.server.packs.resources.ResourceManager;
|
import net.minecraft.server.packs.resources.ResourceManager;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import org.embeddedt.modernfix.duck.IExtendedModelBakery;
|
|
||||||
import org.embeddedt.modernfix.models.LazyBakedModel;
|
import org.embeddedt.modernfix.models.LazyBakedModel;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Overwrite;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Mixin(ModelManager.class)
|
@Mixin(ModelManager.class)
|
||||||
public class ModelManagerMixin {
|
public class ModelManagerMixin {
|
||||||
@Shadow @Nullable private AtlasSet atlases;
|
@Inject(method = "apply(Lnet/minecraft/client/resources/model/ModelBakery;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V",
|
||||||
|
at = @At(value = "RETURN"))
|
||||||
@Shadow private Map<ResourceLocation, BakedModel> bakedRegistry;
|
private void allowBake(ModelBakery pObject, ResourceManager pResourceManager, ProfilerFiller pProfiler, CallbackInfo ci) {
|
||||||
|
|
||||||
@Shadow private Object2IntMap<BlockState> modelGroups;
|
|
||||||
|
|
||||||
@Shadow @Final private TextureManager textureManager;
|
|
||||||
|
|
||||||
@Shadow private BakedModel missingModel;
|
|
||||||
|
|
||||||
@Shadow @Final private BlockModelShaper blockModelShaper;
|
|
||||||
|
|
||||||
@Shadow private ModelBakery modelBakery;
|
|
||||||
|
|
||||||
@Inject(method = "prepare(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)Lnet/minecraft/client/resources/model/ModelBakery;", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiling/ProfilerFiller;endTick()V"), locals = LocalCapture.CAPTURE_FAILHARD)
|
|
||||||
private void fireModelBakeEvent(ResourceManager pResourceManager, ProfilerFiller pProfiler, CallbackInfoReturnable<ModelBakery> cir, ModelBakery pObject) {
|
|
||||||
pProfiler.push("modelevent");
|
|
||||||
if (this.atlases != null) {
|
|
||||||
Minecraft.getInstance().executeBlocking(() -> {
|
|
||||||
this.atlases.close();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.atlases = ((IExtendedModelBakery)(Object)pObject).getUnfinishedAtlasSet();
|
|
||||||
this.bakedRegistry = pObject.getBakedTopLevelModels();
|
|
||||||
this.modelGroups = pObject.getModelGroups();
|
|
||||||
this.missingModel = this.bakedRegistry.get(ModelBakery.MISSING_MODEL_LOCATION);
|
|
||||||
this.modelBakery = pObject;
|
|
||||||
net.minecraftforge.client.ForgeHooksClient.onModelBake((ModelManager)(Object)this, this.bakedRegistry, pObject);
|
|
||||||
pProfiler.popPush("cache");
|
|
||||||
this.blockModelShaper.rebuildCache();
|
|
||||||
pProfiler.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author embeddedt
|
|
||||||
* @reason most of the code is moved to prepare()
|
|
||||||
*/
|
|
||||||
@Overwrite
|
|
||||||
protected void apply(ModelBakery pObject, ResourceManager pResourceManager, ProfilerFiller pProfiler) {
|
|
||||||
pProfiler.startTick();
|
|
||||||
pProfiler.push("upload");
|
|
||||||
this.atlases = pObject.uploadTextures(this.textureManager, pProfiler);
|
|
||||||
pProfiler.pop();
|
|
||||||
LazyBakedModel.allowBakeForFlags = true;
|
LazyBakedModel.allowBakeForFlags = true;
|
||||||
pProfiler.endTick();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.embeddedt.modernfix.mixin.perf.parallelize_model_loading;
|
||||||
|
|
||||||
|
import com.google.common.collect.Interner;
|
||||||
|
import com.google.common.collect.Interners;
|
||||||
|
import net.minecraft.client.renderer.block.BlockModelShaper;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.block.state.properties.Property;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@Mixin(BlockModelShaper.class)
|
||||||
|
public class BlockModelShaperMixin {
|
||||||
|
private static Map<BlockState, String> stateToPropertiesCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Redirect(method = "stateToModelLocation(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/resources/model/ModelResourceLocation;",
|
||||||
|
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/block/BlockModelShaper;statePropertiesToString(Ljava/util/Map;)Ljava/lang/String;"))
|
||||||
|
private static String getCachedProperty(Map<Property<?>, Comparable<?>> values, ResourceLocation location, BlockState state) {
|
||||||
|
/* We intentionally don't use the values parameter inside the lambda to avoid an allocation */
|
||||||
|
return stateToPropertiesCache.computeIfAbsent(state, s -> BlockModelShaper.statePropertiesToString(s.getValues()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package org.embeddedt.modernfix.searchtree;
|
||||||
|
|
||||||
|
import me.shedaniel.rei.api.client.registry.entry.EntryRegistry;
|
||||||
|
import me.shedaniel.rei.api.common.entry.EntryStack;
|
||||||
|
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes;
|
||||||
|
import me.shedaniel.rei.impl.client.search.AsyncSearchManager;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class REIBackedSearchTree extends DummySearchTree<ItemStack> {
|
||||||
|
private final AsyncSearchManager searchManager = new AsyncSearchManager(EntryRegistry.getInstance()::getPreFilteredList, () -> {
|
||||||
|
return stack -> true;
|
||||||
|
}, EntryStack::normalize);
|
||||||
|
|
||||||
|
private final boolean filteringByTag;
|
||||||
|
private String lastSearchText = "";
|
||||||
|
private final List<ItemStack> listCache = new ArrayList<>();
|
||||||
|
|
||||||
|
public REIBackedSearchTree(boolean filteringByTag) {
|
||||||
|
this.filteringByTag = filteringByTag;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public List<ItemStack> search(String pSearchText) {
|
||||||
|
if(true) {
|
||||||
|
return this.searchREI(pSearchText);
|
||||||
|
} else {
|
||||||
|
/* Use the default, dummy implementation */
|
||||||
|
return super.search(pSearchText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ItemStack> searchREI(String pSearchText) {
|
||||||
|
if(!pSearchText.equals(lastSearchText)) {
|
||||||
|
listCache.clear();
|
||||||
|
this.searchManager.updateFilter(pSearchText);
|
||||||
|
List<EntryStack<?>> stacks = this.searchManager.getNow();
|
||||||
|
for(EntryStack<?> stack : stacks) {
|
||||||
|
if(stack.getType() == VanillaEntryTypes.ITEM) {
|
||||||
|
listCache.add(stack.cheatsAs().getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastSearchText = pSearchText;
|
||||||
|
}
|
||||||
|
return listCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import net.minecraft.client.renderer.texture.Stitcher;
|
||||||
import net.minecraft.client.renderer.texture.StitcherException;
|
import net.minecraft.client.renderer.texture.StitcherException;
|
||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
|
import org.embeddedt.modernfix.ModernFix;
|
||||||
import org.lwjgl.stb.STBRPContext;
|
import org.lwjgl.stb.STBRPContext;
|
||||||
import org.lwjgl.stb.STBRPNode;
|
import org.lwjgl.stb.STBRPNode;
|
||||||
import org.lwjgl.stb.STBRPRect;
|
import org.lwjgl.stb.STBRPRect;
|
||||||
|
|
@ -135,7 +136,8 @@ public class StbStitcher {
|
||||||
|
|
||||||
// Initialize the rectangles that we'll be using in the calculation
|
// Initialize the rectangles that we'll be using in the calculation
|
||||||
// While that's happening, sum up the area needed to fit all of the images
|
// While that's happening, sum up the area needed to fit all of the images
|
||||||
int sqSize = 0;
|
int totalArea = 0;
|
||||||
|
int longestWidth = 0, longestHeight = 0;
|
||||||
for (int j = 0; j < holderSize; ++j) {
|
for (int j = 0; j < holderSize; ++j) {
|
||||||
Stitcher.Holder holder = holders[j];
|
Stitcher.Holder holder = holders[j];
|
||||||
|
|
||||||
|
|
@ -147,36 +149,71 @@ public class StbStitcher {
|
||||||
|
|
||||||
setWrapper(rect, j, width, height, 0, 0, false);
|
setWrapper(rect, j, width, height, 0, 0, false);
|
||||||
|
|
||||||
sqSize += (width * height);
|
totalArea += (width * height);
|
||||||
|
longestWidth = Math.max(longestWidth, width);
|
||||||
|
longestHeight = Math.max(longestHeight, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
int size = Mth.smallestEncompassingPowerOfTwo((int) Math.sqrt(sqSize));
|
longestWidth = Mth.smallestEncompassingPowerOfTwo(longestWidth);
|
||||||
int width = size * 2; // needed to fix weirdness in 1.16
|
longestHeight = Mth.smallestEncompassingPowerOfTwo(longestHeight);
|
||||||
int height = size;
|
|
||||||
|
|
||||||
// Internal node structure needed for STB
|
/*
|
||||||
try (STBRPNode.Buffer nodes = STBRPNode.malloc(width + 10)) {
|
* The atlas needs to be at least this wide and tall to accommodate oddly shaped sprites. If this is
|
||||||
// Initialize the rect packer
|
* not enough, keep doubling the smaller of the two values until it's big enough.
|
||||||
STBRectPack.stbrp_init_target(ctx, width, height, nodes);
|
*/
|
||||||
|
while((longestWidth*longestHeight) < totalArea) {
|
||||||
|
if(longestWidth <= longestHeight)
|
||||||
|
longestWidth *= 2;
|
||||||
|
else
|
||||||
|
longestHeight *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
// Perform rectangle packing
|
/*
|
||||||
STBRectPack.stbrp_pack_rects(ctx, rectBuf);
|
* Sometimes our guess is off and we actually need a bigger atlas. We will try up to 4 times to double
|
||||||
|
* the atlas size, if that fails then give up.
|
||||||
|
*/
|
||||||
|
int numTries = 0;
|
||||||
|
while(true) {
|
||||||
|
numTries++;
|
||||||
|
// Internal node structure needed for STB
|
||||||
|
try (STBRPNode.Buffer nodes = STBRPNode.malloc(longestWidth + 10)) {
|
||||||
|
// Initialize the rect packer
|
||||||
|
STBRectPack.stbrp_init_target(ctx, longestWidth, longestHeight, nodes);
|
||||||
|
|
||||||
for (STBRPRect rect : rectBuf) {
|
// Perform rectangle packing
|
||||||
Stitcher.Holder holder = holders[rect.id()];
|
STBRectPack.stbrp_pack_rects(ctx, rectBuf);
|
||||||
|
|
||||||
// Ensure that everything is properly packed!
|
for (STBRPRect rect : rectBuf) {
|
||||||
if (!rect.was_packed()) {
|
Stitcher.Holder holder = holders[rect.id()];
|
||||||
throw new StitcherException(holder.spriteInfo,
|
|
||||||
Stream.of(holders).map(arg -> arg.spriteInfo).collect(ImmutableList.toImmutableList()));
|
// Ensure that everything is properly packed!
|
||||||
|
if (!rect.was_packed()) {
|
||||||
|
throw new StitcherException(holder.spriteInfo,
|
||||||
|
Stream.of(holders).map(arg -> arg.spriteInfo).collect(ImmutableList.toImmutableList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the sprite now with the position and size that we've calculated so far
|
||||||
|
infoList.add(new LoadableSpriteInfo(holder.spriteInfo, longestWidth, longestHeight, getX(rect), getY(rect)));
|
||||||
|
//holder.spriteInfo.initSprite(size, size, rect.x(), rect.y(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the sprite now with the position and size that we've calculated so far
|
return Pair.of(Pair.of(longestWidth, longestHeight), infoList);
|
||||||
infoList.add(new LoadableSpriteInfo(holder.spriteInfo, width, height, getX(rect), getY(rect)));
|
} catch (StitcherException e) {
|
||||||
//holder.spriteInfo.initSprite(size, size, rect.x(), rect.y(), false);
|
if(numTries >= 4) {
|
||||||
|
// If we get here, we weren't able to stitch. Throw an error.
|
||||||
|
ModernFix.LOGGER.error("Stitcher ran out of space with target atlas size " + longestWidth + "x" + longestHeight + ":");
|
||||||
|
for(Stitcher.Holder h : holders) {
|
||||||
|
ModernFix.LOGGER.error(" - " + h.spriteInfo.name() + ", " + h.spriteInfo.width() + "x" + h.spriteInfo.height());
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
} else {
|
||||||
|
// double the atlas size and try again
|
||||||
|
if(longestWidth <= longestHeight)
|
||||||
|
longestWidth *= 2;
|
||||||
|
else
|
||||||
|
longestHeight *= 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Pair.of(Pair.of(width, height), infoList);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
"feature.measure_time.ProfiledReloadInstanceMixin",
|
"feature.measure_time.ProfiledReloadInstanceMixin",
|
||||||
"feature.measure_time.ReloadableServerResourcesMixin",
|
"feature.measure_time.ReloadableServerResourcesMixin",
|
||||||
"feature.branding.BrandingControlMixin",
|
"feature.branding.BrandingControlMixin",
|
||||||
|
"feature.direct_stack_trace.CrashReportMixin",
|
||||||
"perf.fast_registry_validation.ForgeRegistryMixin",
|
"perf.fast_registry_validation.ForgeRegistryMixin",
|
||||||
"perf.cache_strongholds.ChunkGeneratorMixin",
|
"perf.cache_strongholds.ChunkGeneratorMixin",
|
||||||
"perf.cache_upgraded_structures.StructureManagerMixin",
|
"perf.cache_upgraded_structures.StructureManagerMixin",
|
||||||
|
|
@ -36,6 +37,7 @@
|
||||||
"feature.measure_time.MinecraftMixin",
|
"feature.measure_time.MinecraftMixin",
|
||||||
"feature.reduce_loading_screen_freezes.ModelBakeryMixin",
|
"feature.reduce_loading_screen_freezes.ModelBakeryMixin",
|
||||||
"bugfix.concurrency.MinecraftMixin",
|
"bugfix.concurrency.MinecraftMixin",
|
||||||
|
"perf.parallelize_model_loading.BlockModelShaperMixin",
|
||||||
"perf.parallelize_model_loading.ModelBakeryMixin",
|
"perf.parallelize_model_loading.ModelBakeryMixin",
|
||||||
"perf.parallelize_model_loading.OBJLoaderMixin",
|
"perf.parallelize_model_loading.OBJLoaderMixin",
|
||||||
"perf.parallelize_model_loading.multipart.MultipartMixin",
|
"perf.parallelize_model_loading.multipart.MultipartMixin",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user