mirror of
https://github.com/MinecraftForge/MinecraftForge
synced 2026-08-22 04:26:10 -04:00
Support pack overlay system. Closes #9818
This commit is contained in:
parent
6d7fda6a9b
commit
d44d0b8edc
11 changed files with 265 additions and 365 deletions
|
|
@ -12,8 +12,7 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ModLoadingWarning
|
||||
{
|
||||
public class ModLoadingWarning {
|
||||
/**
|
||||
* Mod Info for mod with warning
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
if (path != null) {
|
||||
if (this.tempDataPackRepository == null) {
|
||||
this.tempDataPackRepository = ServerPacksSource.createPackRepository(path, this.packValidator);
|
||||
+ net.minecraftforge.resource.ResourcePackLoader.loadResourcePacks(this.tempDataPackRepository, net.minecraftforge.server.ServerLifecycleHooks::buildPackFinder);
|
||||
+ net.minecraftforge.resource.ResourcePackLoader.loadResourcePacks(this.tempDataPackRepository, false);
|
||||
this.tempDataPackRepository.reload();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
--- a/net/minecraft/resources/RegistryDataLoader.java
|
||||
+++ b/net/minecraft/resources/RegistryDataLoader.java
|
||||
@@ -75,7 +_,9 @@
|
||||
});
|
||||
if (!map.isEmpty()) {
|
||||
logErrors(map);
|
||||
- throw new IllegalStateException("Failed to load registries due to above errors");
|
||||
+ var buf = new StringBuilder("Failed to load registries, see debug.log for more details:");
|
||||
+ map.forEach((k,v) -> buf.append("\n\t").append(k.toString()).append(": ").append(v.getMessage()));
|
||||
+ throw new IllegalStateException(buf.toString());
|
||||
} else {
|
||||
return (new RegistryAccess.ImmutableRegistryAccess(list.stream().map(Pair::getFirst).toList())).freeze();
|
||||
}
|
||||
@@ -124,13 +_,16 @@
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@
|
|||
}
|
||||
|
||||
public static WorldDataConfiguration configurePackRepository(PackRepository p_248681_, DataPackConfig p_248920_, boolean p_249869_, FeatureFlagSet p_251243_) {
|
||||
+ net.minecraftforge.resource.ResourcePackLoader.loadResourcePacks(p_248681_, net.minecraftforge.server.ServerLifecycleHooks::buildPackFinder);
|
||||
+ net.minecraftforge.resource.ResourcePackLoader.loadResourcePacks(p_248681_, false);
|
||||
p_248681_.reload();
|
||||
+ DataPackConfig.DEFAULT.addModPacks(net.minecraftforge.common.ForgeHooks.getModPacks());
|
||||
+ p_248920_.addModPacks(net.minecraftforge.common.ForgeHooks.getModPacks());
|
||||
|
|
|
|||
|
|
@ -1,21 +1,5 @@
|
|||
--- a/net/minecraft/world/level/Explosion.java
|
||||
+++ b/net/minecraft/world/level/Explosion.java
|
||||
@@ -57,6 +_,7 @@
|
||||
private final SoundEvent explosionSound;
|
||||
private final ObjectArrayList<BlockPos> toBlow = new ObjectArrayList<>();
|
||||
private final Map<Player, Vec3> hitPlayers = Maps.newHashMap();
|
||||
+ private final Vec3 position;
|
||||
|
||||
public static DamageSource getDefaultDamageSource(Level p_309890_, @Nullable Entity p_311046_) {
|
||||
return p_309890_.damageSources().explosion(p_311046_, getIndirectSourceEntityInternal(p_311046_));
|
||||
@@ -90,6 +_,7 @@
|
||||
this.smallExplosionParticles = p_312175_;
|
||||
this.largeExplosionParticles = p_310459_;
|
||||
this.explosionSound = p_311795_;
|
||||
+ this.position = new Vec3(this.x, this.y, this.z);
|
||||
}
|
||||
|
||||
private ExplosionDamageCalculator makeDamageCalculator(@Nullable Entity p_46063_) {
|
||||
@@ -193,6 +_,7 @@
|
||||
int j2 = Mth.floor(this.z - (double)f2 - 1.0D);
|
||||
int j1 = Mth.floor(this.z + (double)f2 + 1.0D);
|
||||
|
|
@ -24,14 +8,15 @@
|
|||
Vec3 vec3 = new Vec3(this.x, this.y, this.z);
|
||||
|
||||
for(Entity entity : list) {
|
||||
@@ -345,6 +_,15 @@
|
||||
@@ -345,6 +_,16 @@
|
||||
|
||||
public List<BlockPos> getToBlow() {
|
||||
return this.toBlow;
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated(forRemoval = true, since = "1.20.4")
|
||||
+ public Vec3 getPosition() {
|
||||
+ return this.position;
|
||||
+ return this.center();
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
package net.minecraftforge.client.gui;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
|
@ -17,12 +17,10 @@ import java.util.function.Function;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
||||
import net.minecraft.server.packs.resources.IoSupplier;
|
||||
import net.minecraftforge.client.ConfigScreenHandler;
|
||||
import net.minecraftforge.client.gui.widget.ModListWidget;
|
||||
import net.minecraftforge.client.gui.widget.ScrollPanel;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
||||
import net.minecraftforge.resource.PathPackResources;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
|
@ -53,19 +51,16 @@ import net.minecraftforge.fml.ModList;
|
|||
import net.minecraftforge.fml.VersionChecker;
|
||||
import net.minecraftforge.fml.loading.FMLPaths;
|
||||
import net.minecraftforge.fml.loading.StringUtils;
|
||||
import net.minecraftforge.resource.ResourcePackLoader;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
|
||||
import net.minecraft.locale.Language;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.Style;
|
||||
|
||||
public class ModListScreen extends Screen
|
||||
{
|
||||
public class ModListScreen extends Screen {
|
||||
private static String stripControlCodes(String value) { return net.minecraft.util.StringUtil.stripColor(value); }
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private enum SortType implements Comparator<IModInfo>
|
||||
{
|
||||
private enum SortType implements Comparator<IModInfo> {
|
||||
NORMAL,
|
||||
A_TO_Z{ @Override protected int compare(String name1, String name2){ return name1.compareTo(name2); }},
|
||||
Z_TO_A{ @Override protected int compare(String name1, String name2){ return name2.compareTo(name1); }};
|
||||
|
|
@ -105,8 +100,7 @@ public class ModListScreen extends Screen
|
|||
private boolean sorted = false;
|
||||
private SortType sortType = SortType.NORMAL;
|
||||
|
||||
public ModListScreen(Screen parentScreen)
|
||||
{
|
||||
public ModListScreen(Screen parentScreen) {
|
||||
super(Component.translatable("fml.menu.mods.title"));
|
||||
this.parentScreen = parentScreen;
|
||||
this.mods = Collections.unmodifiableList(ModList.get().getMods());
|
||||
|
|
@ -118,32 +112,26 @@ public class ModListScreen extends Screen
|
|||
private Size2i logoDims = new Size2i(0, 0);
|
||||
private List<FormattedCharSequence> lines = Collections.emptyList();
|
||||
|
||||
InfoPanel(Minecraft mcIn, int widthIn, int heightIn, int topIn)
|
||||
{
|
||||
InfoPanel(Minecraft mcIn, int widthIn, int heightIn, int topIn) {
|
||||
super(mcIn, widthIn, heightIn, topIn, modList.getRight() + PADDING);
|
||||
}
|
||||
|
||||
void setInfo(List<String> lines, ResourceLocation logoPath, Size2i logoDims)
|
||||
{
|
||||
void setInfo(List<String> lines, ResourceLocation logoPath, Size2i logoDims) {
|
||||
this.logoPath = logoPath;
|
||||
this.logoDims = logoDims;
|
||||
this.lines = resizeContent(lines);
|
||||
}
|
||||
|
||||
void clearInfo()
|
||||
{
|
||||
void clearInfo() {
|
||||
this.logoPath = null;
|
||||
this.logoDims = new Size2i(0, 0);
|
||||
this.lines = Collections.emptyList();
|
||||
}
|
||||
|
||||
private List<FormattedCharSequence> resizeContent(List<String> lines)
|
||||
{
|
||||
private List<FormattedCharSequence> resizeContent(List<String> lines) {
|
||||
List<FormattedCharSequence> ret = new ArrayList<>();
|
||||
for (String line : lines)
|
||||
{
|
||||
if (line == null)
|
||||
{
|
||||
for (String line : lines) {
|
||||
if (line == null) {
|
||||
ret.add(null);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -151,16 +139,13 @@ public class ModListScreen extends Screen
|
|||
Component chat = ForgeHooks.newChatWithLinks(line, false);
|
||||
int maxTextLength = this.width - 12;
|
||||
if (maxTextLength >= 0)
|
||||
{
|
||||
ret.addAll(Language.getInstance().getVisualOrder(font.getSplitter().splitLines(chat, maxTextLength, Style.EMPTY)));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight()
|
||||
{
|
||||
public int getContentHeight() {
|
||||
int height = 50;
|
||||
height += (lines.size() * font.lineHeight);
|
||||
if (height < this.bottom - this.top - 8)
|
||||
|
|
@ -169,14 +154,12 @@ public class ModListScreen extends Screen
|
|||
}
|
||||
|
||||
@Override
|
||||
protected int getScrollAmount()
|
||||
{
|
||||
protected int getScrollAmount() {
|
||||
return font.lineHeight * 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawPanel(GuiGraphics guiGraphics, int entryRight, int relativeY, Tesselator tess, int mouseX, int mouseY)
|
||||
{
|
||||
protected void drawPanel(GuiGraphics guiGraphics, int entryRight, int relativeY, Tesselator tess, int mouseX, int mouseY) {
|
||||
if (logoPath != null) {
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
|
@ -186,10 +169,8 @@ public class ModListScreen extends Screen
|
|||
relativeY += headerHeight + PADDING;
|
||||
}
|
||||
|
||||
for (FormattedCharSequence line : lines)
|
||||
{
|
||||
if (line != null)
|
||||
{
|
||||
for (FormattedCharSequence line : lines) {
|
||||
if (line != null) {
|
||||
RenderSystem.enableBlend();
|
||||
guiGraphics.drawString(ModListScreen.this.font, line, left + PADDING, relativeY, 0xFFFFFF);
|
||||
RenderSystem.disableBlend();
|
||||
|
|
@ -198,9 +179,8 @@ public class ModListScreen extends Screen
|
|||
}
|
||||
|
||||
final Style component = findTextLine(mouseX, mouseY);
|
||||
if (component!=null) {
|
||||
if (component!=null)
|
||||
guiGraphics.renderComponentHoverEffect(ModListScreen.this.font, component, mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
private Style findTextLine(final int mouseX, final int mouseY) {
|
||||
|
|
@ -208,9 +188,8 @@ public class ModListScreen extends Screen
|
|||
return null;
|
||||
|
||||
double offset = (mouseY - top) + border + scrollDistance + 1;
|
||||
if (logoPath != null) {
|
||||
if (logoPath != null)
|
||||
offset -= 50;
|
||||
}
|
||||
if (offset <= 0)
|
||||
return null;
|
||||
|
||||
|
|
@ -220,9 +199,7 @@ public class ModListScreen extends Screen
|
|||
|
||||
FormattedCharSequence line = lines.get(lineIdx-1);
|
||||
if (line != null)
|
||||
{
|
||||
return font.getSplitter().componentStyleAtWidth(line, mouseX - left - border);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -247,10 +224,8 @@ public class ModListScreen extends Screen
|
|||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
for (IModInfo mod : mods)
|
||||
{
|
||||
public void init() {
|
||||
for (IModInfo mod : mods) {
|
||||
listWidth = Math.max(listWidth,getFontRenderer().width(mod.getDisplayName()) + 10);
|
||||
listWidth = Math.max(listWidth,getFontRenderer().width(MavenVersionStringHelper.artifactVersionToString(mod.getVersion())) + 5);
|
||||
}
|
||||
|
|
@ -295,37 +270,31 @@ public class ModListScreen extends Screen
|
|||
updateCache();
|
||||
}
|
||||
|
||||
private void displayModConfig()
|
||||
{
|
||||
if (selected == null) return;
|
||||
try
|
||||
{
|
||||
private void displayModConfig() {
|
||||
if (selected == null)
|
||||
return;
|
||||
|
||||
try {
|
||||
ConfigScreenHandler.getScreenFactoryFor(selected.getInfo()).map(f->f.apply(this.minecraft, this)).ifPresent(newScreen -> this.minecraft.setScreen(newScreen));
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
} catch (final Exception e) {
|
||||
LOGGER.error("There was a critical issue trying to build the config GUI for {}", selected.getInfo().getModId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
public void tick() {
|
||||
modList.setSelected(selected);
|
||||
|
||||
if (!search.getValue().equals(lastFilterText))
|
||||
{
|
||||
if (!search.getValue().equals(lastFilterText)) {
|
||||
reloadMods();
|
||||
sorted = false;
|
||||
}
|
||||
|
||||
if (!sorted)
|
||||
{
|
||||
if (!sorted) {
|
||||
reloadMods();
|
||||
mods.sort(sortType);
|
||||
modList.refreshList();
|
||||
if (selected != null)
|
||||
{
|
||||
if (selected != null) {
|
||||
selected = modList.children().stream().filter(e -> e.getInfo() == selected.getInfo()).findFirst().orElse(null);
|
||||
updateCache();
|
||||
}
|
||||
|
|
@ -333,33 +302,33 @@ public class ModListScreen extends Screen
|
|||
}
|
||||
}
|
||||
|
||||
public <T extends ObjectSelectionList.Entry<T>> void buildModList(Consumer<T> modListViewConsumer, Function<IModInfo, T> newEntry)
|
||||
{
|
||||
public <T extends ObjectSelectionList.Entry<T>> void buildModList(Consumer<T> modListViewConsumer, Function<IModInfo, T> newEntry) {
|
||||
mods.forEach(mod->modListViewConsumer.accept(newEntry.apply(mod)));
|
||||
}
|
||||
|
||||
private void reloadMods()
|
||||
{
|
||||
this.mods = this.unsortedMods.stream().
|
||||
filter(mi->StringUtils.toLowerCase(stripControlCodes(mi.getDisplayName())).contains(StringUtils.toLowerCase(search.getValue()))).collect(Collectors.toList());
|
||||
private void reloadMods() {
|
||||
this.mods = this.unsortedMods
|
||||
.stream()
|
||||
.filter(mi ->
|
||||
StringUtils.toLowerCase(stripControlCodes(mi.getDisplayName()))
|
||||
.contains(StringUtils.toLowerCase(search.getValue()))
|
||||
).collect(Collectors.toList());
|
||||
lastFilterText = search.getValue();
|
||||
}
|
||||
|
||||
private void resortMods(SortType newSort)
|
||||
{
|
||||
private void resortMods(SortType newSort) {
|
||||
this.sortType = newSort;
|
||||
|
||||
for (SortType sort : SortType.values())
|
||||
{
|
||||
for (SortType sort : SortType.values()) {
|
||||
if (sort.button != null)
|
||||
sort.button.active = sortType != sort;
|
||||
}
|
||||
|
||||
sorted = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick)
|
||||
{
|
||||
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
||||
this.modList.render(guiGraphics, mouseX, mouseY, partialTick);
|
||||
if (this.modInfo != null)
|
||||
this.modInfo.render(guiGraphics, mouseX, mouseY, partialTick);
|
||||
|
|
@ -371,52 +340,46 @@ public class ModListScreen extends Screen
|
|||
guiGraphics.drawString(getFontRenderer(), text.getVisualOrderText(), x, search.getY() - getFontRenderer().lineHeight, 0xFFFFFF, false);
|
||||
}
|
||||
|
||||
public Minecraft getMinecraftInstance()
|
||||
{
|
||||
public Minecraft getMinecraftInstance() {
|
||||
return minecraft;
|
||||
}
|
||||
|
||||
public Font getFontRenderer()
|
||||
{
|
||||
public Font getFontRenderer() {
|
||||
return font;
|
||||
}
|
||||
|
||||
public void setSelected(ModListWidget.ModEntry entry)
|
||||
{
|
||||
public void setSelected(ModListWidget.ModEntry entry) {
|
||||
this.selected = entry == this.selected ? null : entry;
|
||||
updateCache();
|
||||
}
|
||||
|
||||
private void updateCache()
|
||||
{
|
||||
private void updateCache() {
|
||||
if (selected == null) {
|
||||
this.configButton.active = false;
|
||||
this.modInfo.clearInfo();
|
||||
return;
|
||||
}
|
||||
|
||||
IModInfo selectedMod = selected.getInfo();
|
||||
this.configButton.active = ConfigScreenHandler.getScreenFactoryFor(selectedMod).isPresent();
|
||||
List<String> lines = new ArrayList<>();
|
||||
VersionChecker.CheckResult vercheck = VersionChecker.getResult(selectedMod);
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
Pair<ResourceLocation, Size2i> logoData = selectedMod.getLogoFile().map(logoFile->
|
||||
{
|
||||
Pair<ResourceLocation, Size2i> logoData = selectedMod.getLogoFile().map(logoFile -> {
|
||||
TextureManager tm = this.minecraft.getTextureManager();
|
||||
final PathPackResources resourcePack = ResourcePackLoader.getPackFor(selectedMod.getModId())
|
||||
.orElse(ResourcePackLoader.getPackFor("forge").
|
||||
orElseThrow(()->new RuntimeException("Can't find forge, WHAT!")));
|
||||
try
|
||||
{
|
||||
|
||||
try {
|
||||
NativeImage logo = null;
|
||||
IoSupplier<InputStream> logoResource = resourcePack.getRootResource(logoFile);
|
||||
if (logoResource != null)
|
||||
logo = NativeImage.read(logoResource.get());
|
||||
if (logo != null)
|
||||
{
|
||||
var modfile = ModList.get().getModFileById(selectedMod.getModId());
|
||||
if (modfile != null) {
|
||||
var path = modfile.getFile().findResource(logoFile);
|
||||
if (Files.exists(path))
|
||||
logo = NativeImage.read(Files.newInputStream(path));
|
||||
}
|
||||
|
||||
if (logo != null) {
|
||||
return Pair.of(tm.register("modlogo", new DynamicTexture(logo) {
|
||||
|
||||
@Override
|
||||
public void upload() {
|
||||
this.bind();
|
||||
|
|
@ -426,8 +389,8 @@ public class ModListScreen extends Screen
|
|||
}
|
||||
}), new Size2i(logo.getWidth(), logo.getHeight()));
|
||||
}
|
||||
}
|
||||
catch (IOException e) { }
|
||||
} catch (IOException e) { }
|
||||
|
||||
return Pair.<ResourceLocation, Size2i>of(null, new Size2i(0, 0));
|
||||
}).orElse(Pair.of(null, new Size2i(0, 0)));
|
||||
|
||||
|
|
@ -463,12 +426,10 @@ public class ModListScreen extends Screen
|
|||
}
|
||||
*/
|
||||
|
||||
if ((vercheck.status() == VersionChecker.Status.OUTDATED || vercheck.status() == VersionChecker.Status.BETA_OUTDATED) && vercheck.changes().size() > 0)
|
||||
{
|
||||
if ((vercheck.status() == VersionChecker.Status.OUTDATED || vercheck.status() == VersionChecker.Status.BETA_OUTDATED) && vercheck.changes().size() > 0) {
|
||||
lines.add(null);
|
||||
lines.add(ForgeI18n.parseMessage("fml.menu.mods.info.changelogheader"));
|
||||
for (Entry<ComparableVersion, String> entry : vercheck.changes().entrySet())
|
||||
{
|
||||
for (Entry<ComparableVersion, String> entry : vercheck.changes().entrySet()) {
|
||||
lines.add(" " + entry.getKey() + ":");
|
||||
lines.add(entry.getValue());
|
||||
lines.add(null);
|
||||
|
|
@ -479,24 +440,25 @@ public class ModListScreen extends Screen
|
|||
}
|
||||
|
||||
@Override
|
||||
public void resize(Minecraft mc, int width, int height)
|
||||
{
|
||||
public void resize(Minecraft mc, int width, int height) {
|
||||
String s = this.search.getValue();
|
||||
SortType sort = this.sortType;
|
||||
ModListWidget.ModEntry selected = this.selected;
|
||||
this.init(mc, width, height);
|
||||
this.search.setValue(s);
|
||||
this.selected = selected;
|
||||
|
||||
if (!this.search.getValue().isEmpty())
|
||||
reloadMods();
|
||||
|
||||
if (sort != SortType.NORMAL)
|
||||
resortMods(sort);
|
||||
|
||||
updateCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose()
|
||||
{
|
||||
public void onClose() {
|
||||
this.minecraft.setScreen(this.parentScreen);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,16 +53,14 @@ import net.minecraftforge.server.LanguageHook;
|
|||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class ClientModLoader
|
||||
{
|
||||
public class ClientModLoader {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static boolean loading;
|
||||
private static Minecraft mc;
|
||||
private static boolean loadingComplete;
|
||||
private static LoadingFailedException error;
|
||||
|
||||
public static void begin(final Minecraft minecraft, final PackRepository defaultResourcePacks, final ReloadableResourceManager mcResourceManager)
|
||||
{
|
||||
public static void begin(final Minecraft minecraft, final PackRepository defaultResourcePacks, final ReloadableResourceManager mcResourceManager) {
|
||||
// force log4j to shutdown logging in a shutdown hook. This is because we disable default shutdown hook so the server properly logs it's shutdown
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(LogManager::shutdown));
|
||||
ImmediateWindowHandler.updateProgress("Loading mods");
|
||||
|
|
@ -72,7 +70,7 @@ public class ClientModLoader
|
|||
LanguageHook.loadForgeAndMCLangs();
|
||||
createRunnableWithCatch(()->ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), ImmediateWindowHandler::renderTick)).run();
|
||||
if (error == null) {
|
||||
ResourcePackLoader.loadResourcePacks(defaultResourcePacks, ClientModLoader::buildPackFinder);
|
||||
ResourcePackLoader.loadResourcePacks(defaultResourcePacks, true);
|
||||
ModLoader.get().postEvent(new AddPackFindersEvent(PackType.CLIENT_RESOURCES, defaultResourcePacks::addPackFinder));
|
||||
DataPackConfig.DEFAULT.addModPacks(ResourcePackLoader.getPackNames());
|
||||
mcResourceManager.registerReloadListener(ClientModLoader::onResourceReload);
|
||||
|
|
@ -101,8 +99,7 @@ public class ClientModLoader
|
|||
createRunnableWithCatch(() -> ModLoader.get().loadMods(syncExecutor, parallelExecutor, ImmediateWindowHandler::renderTick)).run();
|
||||
}
|
||||
|
||||
private static void finishModLoading(ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor)
|
||||
{
|
||||
private static void finishModLoading(ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor) {
|
||||
createRunnableWithCatch(() -> ModLoader.get().finishMods(syncExecutor, parallelExecutor, ImmediateWindowHandler::renderTick)).run();
|
||||
loading = false;
|
||||
loadingComplete = true;
|
||||
|
|
@ -110,8 +107,7 @@ public class ClientModLoader
|
|||
syncExecutor.execute(()->mc.options.load(true));
|
||||
}
|
||||
|
||||
public static VersionChecker.Status checkForUpdates()
|
||||
{
|
||||
public static VersionChecker.Status checkForUpdates() {
|
||||
boolean anyOutdated = ModList.get().getMods().stream()
|
||||
.map(VersionChecker::getResult)
|
||||
.map(result -> result.status())
|
||||
|
|
@ -119,8 +115,7 @@ public class ClientModLoader
|
|||
return anyOutdated ? VersionChecker.Status.OUTDATED : null;
|
||||
}
|
||||
|
||||
public static boolean completeModLoading()
|
||||
{
|
||||
public static boolean completeModLoading() {
|
||||
var warnings = ModLoader.get().getWarnings();
|
||||
boolean showWarnings = true;
|
||||
try {
|
||||
|
|
@ -128,6 +123,7 @@ public class ClientModLoader
|
|||
} catch (NullPointerException | IllegalStateException e) {
|
||||
// We're in an early error state, config is not available. Assume true.
|
||||
}
|
||||
|
||||
if (!showWarnings) {
|
||||
//User disabled warning screen, as least log them
|
||||
if (!warnings.isEmpty()) {
|
||||
|
|
@ -136,6 +132,7 @@ public class ClientModLoader
|
|||
}
|
||||
warnings = Collections.emptyList(); //Clear warnings, as the user does not want to see them
|
||||
}
|
||||
|
||||
File dumpedLocation = null;
|
||||
if (error == null) {
|
||||
// We can finally start the forge eventbus up
|
||||
|
|
@ -145,81 +142,16 @@ public class ClientModLoader
|
|||
LanguageHook.loadForgeAndMCLangs();
|
||||
dumpedLocation = CrashReportExtender.dumpModLoadingCrashReport(LOGGER, error, mc.gameDirectory);
|
||||
}
|
||||
|
||||
if (error != null || !warnings.isEmpty()) {
|
||||
mc.setScreen(new LoadingErrorScreen(error, warnings, dumpedLocation));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isLoading()
|
||||
{
|
||||
public static boolean isLoading() {
|
||||
return loading;
|
||||
}
|
||||
|
||||
private static RepositorySource buildPackFinder(Map<IModFile, ? extends PathPackResources> modResourcePacks) {
|
||||
return packAcceptor -> clientPackFinder(modResourcePacks, packAcceptor);
|
||||
}
|
||||
|
||||
private static void clientPackFinder(Map<IModFile, ? extends PathPackResources> modResourcePacks, Consumer<Pack> packAcceptor) {
|
||||
var hiddenPacks = new ArrayList<PathPackResources>();
|
||||
for (Entry<IModFile, ? extends PathPackResources> e : modResourcePacks.entrySet())
|
||||
{
|
||||
|
||||
var supplier = new Pack.ResourcesSupplier() {
|
||||
@Override
|
||||
public PackResources openPrimary(String path) {
|
||||
return e.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackResources openFull(String path, Info info) {
|
||||
return e.getValue(); // TODO: composite
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
IModInfo mod = e.getKey().getModInfos().get(0);
|
||||
final String name = "mod:" + mod.getModId();
|
||||
final Pack modPack = Pack.readMetaAndCreate(name, Component.literal(e.getValue().packId()), false, supplier, PackType.CLIENT_RESOURCES, Pack.Position.BOTTOM, PackSource.DEFAULT);
|
||||
if (modPack == null) {
|
||||
// Vanilla only logs an error, instead of propagating, so handle null and warn that something went wrong
|
||||
ModLoader.get().addWarning(new ModLoadingWarning(mod, ModLoadingStage.ERROR, "fml.modloading.brokenresources", e.getKey()));
|
||||
continue;
|
||||
}
|
||||
LOGGER.debug(Logging.CORE, "Generating PackInfo named {} for mod file {}", name, e.getKey().getFilePath());
|
||||
if (mod.getOwningFile().showAsResourcePack()) {
|
||||
packAcceptor.accept(modPack);
|
||||
} else {
|
||||
hiddenPacks.add(e.getValue());
|
||||
}
|
||||
}
|
||||
var delegating = new DelegatingPackResources("mod_resources", false,
|
||||
new PackMetadataSection(
|
||||
Component.translatable("fml.resources.modresources", hiddenPacks.size()),
|
||||
SharedConstants.getCurrentVersion().getPackVersion(PackType.CLIENT_RESOURCES),
|
||||
Optional.empty()
|
||||
),
|
||||
hiddenPacks
|
||||
);
|
||||
|
||||
var supplier = new Pack.ResourcesSupplier() {
|
||||
@Override
|
||||
public PackResources openPrimary(String path) {
|
||||
return delegating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackResources openFull(String path, Info info) {
|
||||
return delegating; // TODO: composite
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Create a resource pack merging all mod resources that should be hidden
|
||||
final Pack modResourcesPack = Pack.readMetaAndCreate("mod_resources", Component.literal("Mod Resources"), true, supplier,
|
||||
PackType.CLIENT_RESOURCES, Pack.Position.BOTTOM, PackSource.DEFAULT);
|
||||
packAcceptor.accept(modResourcesPack);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,18 +22,21 @@ import net.minecraft.server.packs.PackResources;
|
|||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.server.packs.metadata.MetadataSectionSerializer;
|
||||
import net.minecraft.server.packs.metadata.pack.PackMetadataSection;
|
||||
import net.minecraft.server.packs.repository.Pack;
|
||||
import net.minecraft.server.packs.repository.Pack.Info;
|
||||
import net.minecraft.server.packs.resources.IoSupplier;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class DelegatingPackResources extends AbstractPackResources
|
||||
{
|
||||
@ApiStatus.Internal
|
||||
public class DelegatingPackResources extends AbstractPackResources {
|
||||
private final PackMetadataSection packMeta;
|
||||
private final List<PackResources> delegates;
|
||||
private final Map<String, List<PackResources>> namespacesAssets;
|
||||
private final Map<String, List<PackResources>> namespacesData;
|
||||
|
||||
public DelegatingPackResources(String packId, boolean isBuiltin, PackMetadataSection packMeta, List<? extends PackResources> packs)
|
||||
{
|
||||
public DelegatingPackResources(String packId, boolean isBuiltin, PackMetadataSection packMeta, List<? extends PackResources> packs) {
|
||||
super(packId, isBuiltin);
|
||||
this.packMeta = packMeta;
|
||||
this.delegates = ImmutableList.copyOf(packs);
|
||||
|
|
@ -41,15 +44,11 @@ public class DelegatingPackResources extends AbstractPackResources
|
|||
this.namespacesData = this.buildNamespaceMap(PackType.SERVER_DATA, delegates);
|
||||
}
|
||||
|
||||
private Map<String, List<PackResources>> buildNamespaceMap(PackType type, List<PackResources> packList)
|
||||
{
|
||||
private Map<String, List<PackResources>> buildNamespaceMap(PackType type, List<PackResources> packList) {
|
||||
Map<String, List<PackResources>> map = new HashMap<>();
|
||||
for (PackResources pack : packList)
|
||||
{
|
||||
for (PackResources pack : packList) {
|
||||
for (String namespace : pack.getNamespaces(type))
|
||||
{
|
||||
map.computeIfAbsent(namespace, k -> new ArrayList<>()).add(pack);
|
||||
}
|
||||
}
|
||||
map.replaceAll((k, list) -> ImmutableList.copyOf(list));
|
||||
return ImmutableMap.copyOf(map);
|
||||
|
|
@ -58,49 +57,38 @@ public class DelegatingPackResources extends AbstractPackResources
|
|||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getMetadataSection(MetadataSectionSerializer<T> deserializer) throws IOException
|
||||
{
|
||||
public <T> T getMetadataSection(MetadataSectionSerializer<T> deserializer) throws IOException {
|
||||
return deserializer.getMetadataSectionName().equals("pack") ? (T) this.packMeta : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listResources(PackType type, String resourceNamespace, String paths, ResourceOutput resourceOutput)
|
||||
{
|
||||
public void listResources(PackType type, String resourceNamespace, String paths, ResourceOutput resourceOutput) {
|
||||
for (PackResources delegate : this.delegates)
|
||||
{
|
||||
delegate.listResources(type, resourceNamespace, paths, resourceOutput);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getNamespaces(PackType type)
|
||||
{
|
||||
public Set<String> getNamespaces(PackType type) {
|
||||
return type == PackType.CLIENT_RESOURCES ? namespacesAssets.keySet() : namespacesData.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
public void close() {
|
||||
for (PackResources pack : delegates)
|
||||
{
|
||||
pack.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IoSupplier<InputStream> getRootResource(String... paths)
|
||||
{
|
||||
public IoSupplier<InputStream> getRootResource(String... paths) {
|
||||
// Root resources do not make sense here
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IoSupplier<InputStream> getResource(PackType type, ResourceLocation location)
|
||||
{
|
||||
for (PackResources pack : getCandidatePacks(type, location))
|
||||
{
|
||||
public IoSupplier<InputStream> getResource(PackType type, ResourceLocation location) {
|
||||
for (PackResources pack : getCandidatePacks(type, location)) {
|
||||
IoSupplier<InputStream> ioSupplier = pack.getResource(type, location);
|
||||
if (ioSupplier != null)
|
||||
return ioSupplier;
|
||||
|
|
@ -110,15 +98,29 @@ public class DelegatingPackResources extends AbstractPackResources
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public Collection<PackResources> getChildren()
|
||||
{
|
||||
public Collection<PackResources> getChildren() {
|
||||
return delegates;
|
||||
}
|
||||
|
||||
private List<PackResources> getCandidatePacks(PackType type, ResourceLocation location)
|
||||
{
|
||||
private List<PackResources> getCandidatePacks(PackType type, ResourceLocation location) {
|
||||
Map<String, List<PackResources>> map = type == PackType.CLIENT_RESOURCES ? namespacesAssets : namespacesData;
|
||||
List<PackResources> packsWithNamespace = map.get(location.getNamespace());
|
||||
return packsWithNamespace == null ? Collections.emptyList() : packsWithNamespace;
|
||||
}
|
||||
|
||||
public Pack.ResourcesSupplier supplier() {
|
||||
return new Supplier();
|
||||
}
|
||||
|
||||
private class Supplier implements Pack.ResourcesSupplier {
|
||||
@Override
|
||||
public PackResources openPrimary(String path) {
|
||||
return DelegatingPackResources.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackResources openFull(String path, Info info) {
|
||||
return DelegatingPackResources.this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,14 +5,12 @@
|
|||
|
||||
package net.minecraftforge.resource;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
|
@ -31,10 +29,9 @@ import org.slf4j.Logger;
|
|||
* <p>
|
||||
* This is primarily intended to support including optional resource packs inside a mod,
|
||||
* such as to have alternative textures to use along with Programmer Art, or optional
|
||||
* alternative recipes for compatibility ot to replace vanilla recipes.
|
||||
* alternative recipes for compatibility to to replace vanilla recipes.
|
||||
*/
|
||||
public class PathPackResources extends AbstractPackResources
|
||||
{
|
||||
public class PathPackResources extends AbstractPackResources {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final Path source;
|
||||
|
||||
|
|
@ -46,8 +43,7 @@ public class PathPackResources extends AbstractPackResources
|
|||
* @param isBuiltin whether this pack resources should be considered builtin
|
||||
* @param source the root path of the pack. This needs to point to the folder that contains "assets" and/or "data", not the asset folder itself!
|
||||
*/
|
||||
public PathPackResources(String packId, boolean isBuiltin, final Path source)
|
||||
{
|
||||
public PathPackResources(String packId, boolean isBuiltin, final Path source) {
|
||||
super(packId, isBuiltin);
|
||||
this.source = source;
|
||||
}
|
||||
|
|
@ -58,8 +54,7 @@ public class PathPackResources extends AbstractPackResources
|
|||
*
|
||||
* @return the root path of the resources.
|
||||
*/
|
||||
public Path getSource()
|
||||
{
|
||||
public Path getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
|
|
@ -69,8 +64,7 @@ public class PathPackResources extends AbstractPackResources
|
|||
* @param paths One or more path strings to resolve. Can include slash-separated paths.
|
||||
* @return the resulting path, which may not exist.
|
||||
*/
|
||||
protected Path resolve(String... paths)
|
||||
{
|
||||
protected Path resolve(String... paths) {
|
||||
Path path = getSource();
|
||||
for (String name : paths)
|
||||
path = path.resolve(name);
|
||||
|
|
@ -79,8 +73,7 @@ public class PathPackResources extends AbstractPackResources
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public IoSupplier<InputStream> getRootResource(String... paths)
|
||||
{
|
||||
public IoSupplier<InputStream> getRootResource(String... paths) {
|
||||
final Path path = resolve(paths);
|
||||
if (!Files.exists(path))
|
||||
return null;
|
||||
|
|
@ -89,27 +82,22 @@ public class PathPackResources extends AbstractPackResources
|
|||
}
|
||||
|
||||
@Override
|
||||
public void listResources(PackType type, String namespace, String path, ResourceOutput resourceOutput)
|
||||
{
|
||||
public void listResources(PackType type, String namespace, String path, ResourceOutput resourceOutput) {
|
||||
FileUtil.decomposePath(path).get()
|
||||
.ifLeft(parts -> net.minecraft.server.packs.PathPackResources.listPath(namespace, resolve(type.getDirectory(), namespace).toAbsolutePath(), parts, resourceOutput))
|
||||
.ifRight(dataResult -> LOGGER.error("Invalid path {}: {}", path, dataResult.message()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getNamespaces(PackType type)
|
||||
{
|
||||
public Set<String> getNamespaces(PackType type) {
|
||||
return getNamespacesFromDisk(type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Set<String> getNamespacesFromDisk(final PackType type)
|
||||
{
|
||||
try
|
||||
{
|
||||
private Set<String> getNamespacesFromDisk(final PackType type) {
|
||||
try {
|
||||
Path root = resolve(type.getDirectory());
|
||||
try (Stream<Path> walker = Files.walk(root, 1))
|
||||
{
|
||||
try (Stream<Path> walker = Files.walk(root, 1)) {
|
||||
return walker
|
||||
.filter(Files::isDirectory)
|
||||
.map(root::relativize)
|
||||
|
|
@ -118,28 +106,20 @@ public class PathPackResources extends AbstractPackResources
|
|||
.filter(s -> !s.isEmpty()) // Filter empty strings, otherwise empty strings default to minecraft namespace in ResourceLocations
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
} catch (IOException e) {
|
||||
if (type == PackType.SERVER_DATA) // We still have to add the resource namespace if client resources exist, as we load langs (which are in assets) on server
|
||||
{
|
||||
return this.getNamespaces(PackType.CLIENT_RESOURCES);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IoSupplier<InputStream> getResource(PackType type, ResourceLocation location)
|
||||
{
|
||||
public IoSupplier<InputStream> getResource(PackType type, ResourceLocation location) {
|
||||
return this.getRootResource(getPathFromLocation(location.getPath().startsWith("lang/") ? PackType.CLIENT_RESOURCES : type, location));
|
||||
}
|
||||
|
||||
private static String[] getPathFromLocation(PackType type, ResourceLocation location)
|
||||
{
|
||||
private static String[] getPathFromLocation(PackType type, ResourceLocation location) {
|
||||
String[] parts = location.getPath().split("/");
|
||||
String[] result = new String[parts.length + 2];
|
||||
result[0] = type.getDirectory();
|
||||
|
|
@ -149,13 +129,10 @@ public class PathPackResources extends AbstractPackResources
|
|||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
}
|
||||
public void close() { }
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
public String toString() {
|
||||
return String.format(Locale.ROOT, "%s: %s (%s)", getClass().getName(), this.packId(), getSource());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,62 +8,97 @@ package net.minecraftforge.resource;
|
|||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import net.minecraft.server.packs.repository.RepositorySource;
|
||||
import net.minecraft.server.packs.repository.Pack.Info;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.packs.CompositePackResources;
|
||||
import net.minecraft.server.packs.PackResources;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.server.packs.metadata.pack.PackMetadataSection;
|
||||
import net.minecraft.server.packs.repository.Pack;
|
||||
import net.minecraft.server.packs.repository.PackRepository;
|
||||
import net.minecraft.server.packs.repository.PackSource;
|
||||
import net.minecraftforge.fml.Logging;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.ModLoadingStage;
|
||||
import net.minecraftforge.fml.ModLoadingWarning;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class ResourcePackLoader {
|
||||
private static Map<IModFile, PathPackResources> modResourcePacks;
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
public static Optional<PathPackResources> getPackFor(String modId) {
|
||||
return Optional.ofNullable(ModList.get().getModFileById(modId)).
|
||||
map(IModFileInfo::getFile).map(mf->modResourcePacks.get(mf));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void loadResourcePacks(PackRepository resourcePacks, BiFunction<Map<IModFile, ? extends PathPackResources>, BiConsumer<? super PathPackResources, Pack>, ? extends RepositorySource> packFinder) {
|
||||
loadResourcePacks(resourcePacks, (map) -> packFinder.apply(map, (rp,p) -> {}));
|
||||
}
|
||||
|
||||
public static void loadResourcePacks(PackRepository resourcePacks, Function<Map<IModFile, ? extends PathPackResources>, ? extends RepositorySource> packFinder) {
|
||||
modResourcePacks = ModList.get().getModFiles().stream()
|
||||
.filter(mf->mf.requiredLanguageLoaders().stream().noneMatch(ls->ls.languageName().equals("minecraft")))
|
||||
.map(mf -> Pair.of(mf, createPackForMod(mf)))
|
||||
.collect(Collectors.toMap(p -> p.getFirst().getFile(), Pair::getSecond, (u,v) -> { throw new IllegalStateException(String.format(Locale.ENGLISH, "Duplicate key %s", u)); }, LinkedHashMap::new));
|
||||
resourcePacks.addPackFinder(packFinder.apply(modResourcePacks));
|
||||
public static void loadResourcePacks(PackRepository resourcePacks, boolean client) {
|
||||
resourcePacks.addPackFinder(repo -> findPacks(repo, client));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PathPackResources createPackForMod(IModFileInfo mf)
|
||||
{
|
||||
return new PathPackResources(mf.getFile().getFileName(), true, mf.getFile().getFilePath())
|
||||
{
|
||||
private final IModFile modFile = mf.getFile();
|
||||
public static PathPackResources createPackForMod(IModFileInfo mf) {
|
||||
return new ModPathPackResources(mf.getFile());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Path resolve(@NotNull String... paths)
|
||||
{
|
||||
return this.modFile.findResource(paths);
|
||||
private static class ModPathPackResources extends PathPackResources {
|
||||
private final IModFile mod;
|
||||
private final String[] prefix;
|
||||
|
||||
private ModPathPackResources(IModFile mod, String... prefix) {
|
||||
super(mod.getFileName(), true, mod.getFilePath());
|
||||
this.mod = mod;
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Path resolve(@NotNull String... paths) {
|
||||
if (prefix != null && prefix.length > 0) {
|
||||
var tmp = new String[prefix.length + paths.length];
|
||||
System.arraycopy(prefix, 0, tmp, 0, prefix.length);
|
||||
System.arraycopy(paths, 0, tmp, prefix.length, paths.length);
|
||||
return this.mod.findResource(tmp);
|
||||
}
|
||||
};
|
||||
return this.mod.findResource(paths);
|
||||
}
|
||||
|
||||
private static class Supplier implements Pack.ResourcesSupplier {
|
||||
private final IModFile mod;
|
||||
|
||||
private Supplier(IModFile mod) {
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackResources openPrimary(String packId) {
|
||||
return new ModPathPackResources(mod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackResources openFull(String packId, Info info) {
|
||||
var primary = openPrimary(packId);
|
||||
if (info.overlays().isEmpty())
|
||||
return primary;
|
||||
|
||||
var lst = new ArrayList<PackResources>(info.overlays().size());
|
||||
for (var overlay : info.overlays())
|
||||
lst.add(new ModPathPackResources(mod, overlay));
|
||||
|
||||
return new CompositePackResources(primary, lst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getPackNames() {
|
||||
|
|
@ -99,4 +134,55 @@ public class ResourcePackLoader {
|
|||
};
|
||||
}
|
||||
|
||||
private static void findPacks(Consumer<Pack> packAcceptor, boolean client) {
|
||||
var type = client ? PackType.CLIENT_RESOURCES : PackType.SERVER_DATA;
|
||||
var version = SharedConstants.getCurrentVersion().getPackVersion(type);
|
||||
var hiddenPacks = new ArrayList<PackResources>();
|
||||
|
||||
for (var mod : ModList.get().getModFiles()) {
|
||||
if (mod.requiredLanguageLoaders().stream().anyMatch(ls -> ls.languageName().equals("minecraft")))
|
||||
continue;
|
||||
|
||||
var file = mod.getFile();
|
||||
|
||||
var supplier = new ModPathPackResources.Supplier(file);
|
||||
|
||||
var modinfo = file.getModInfos().get(0);
|
||||
var name = "mod:" + modinfo.getModId();
|
||||
var meta = Pack.readPackInfo(name, supplier, version);
|
||||
Pack pack = null;
|
||||
if (meta != null)
|
||||
pack = Pack.create(name, Component.literal(file.getFileName()), false, supplier, meta, Pack.Position.BOTTOM, false, PackSource.DEFAULT);
|
||||
|
||||
if (pack == null) {
|
||||
// Vanilla only logs an error, instead of propagating, so handle null and warn that something went wrong
|
||||
ModLoader.get().addWarning(new ModLoadingWarning(modinfo, ModLoadingStage.ERROR, "fml.modloading.brokenresources", file));
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGGER.debug(Logging.CORE, "Generating PackInfo named {} for mod file {}", name, file.getFilePath());
|
||||
if (!client || mod.showAsResourcePack())
|
||||
packAcceptor.accept(pack);
|
||||
else
|
||||
hiddenPacks.add(pack.open());
|
||||
}
|
||||
|
||||
if (!hiddenPacks.isEmpty()) {
|
||||
@SuppressWarnings("resource")
|
||||
var delegating = new DelegatingPackResources("mod_resources", false,
|
||||
new PackMetadataSection(
|
||||
Component.translatable("fml.resources.modresources", hiddenPacks.size()),
|
||||
version,
|
||||
Optional.empty()
|
||||
),
|
||||
hiddenPacks
|
||||
);
|
||||
|
||||
var supplier = delegating.supplier();
|
||||
|
||||
// Create a resource pack merging all mod resources that should be hidden
|
||||
var modResourcesPack = Pack.readMetaAndCreate("mod_resources", Component.literal("Mod Resources"), true, supplier, type, Pack.Position.BOTTOM, PackSource.DEFAULT);
|
||||
packAcceptor.accept(modResourcesPack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,8 @@ import java.io.IOException;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
|
|
@ -23,37 +18,24 @@ import net.minecraft.gametest.framework.GameTestServer;
|
|||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.ConnectionProtocol;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.protocol.handshake.ClientIntent;
|
||||
import net.minecraft.network.protocol.handshake.ClientIntentionPacket;
|
||||
import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket;
|
||||
import net.minecraft.server.packs.PackResources;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.server.packs.repository.PackSource;
|
||||
import net.minecraft.server.packs.repository.RepositorySource;
|
||||
import net.minecraft.world.level.storage.LevelResource;
|
||||
import net.minecraftforge.common.world.StructureModifier;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.Logging;
|
||||
import net.minecraftforge.common.util.LogicalSidedProvider;
|
||||
import net.minecraftforge.common.world.BiomeModifier;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.ModLoadingStage;
|
||||
import net.minecraftforge.fml.ModLoadingWarning;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
import net.minecraftforge.network.ConnectionType;
|
||||
import net.minecraftforge.network.NetworkContext;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.registries.ForgeRegistries.Keys;
|
||||
import net.minecraftforge.resource.PathPackResources;
|
||||
import net.minecraftforge.server.permission.PermissionAPI;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
import org.apache.logging.log4j.MarkerManager;
|
||||
|
||||
import net.minecraft.server.packs.repository.Pack;
|
||||
import net.minecraft.server.packs.repository.Pack.Info;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
|
@ -64,7 +46,6 @@ import net.minecraftforge.event.server.ServerStartedEvent;
|
|||
import net.minecraftforge.event.server.ServerStartingEvent;
|
||||
import net.minecraftforge.event.server.ServerStoppedEvent;
|
||||
import net.minecraftforge.event.server.ServerStoppingEvent;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.GameData;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
|
@ -134,41 +115,6 @@ public class ServerLifecycleHooks {
|
|||
return currentServer;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static RepositorySource buildPackFinder(Map<IModFile, ? extends PathPackResources> modResourcePacks) {
|
||||
return packAcceptor -> serverPackFinder(modResourcePacks, packAcceptor);
|
||||
}
|
||||
|
||||
private static void serverPackFinder(Map<IModFile, ? extends PathPackResources> modResourcePacks, Consumer<Pack> packAcceptor) {
|
||||
for (Entry<IModFile, ? extends PathPackResources> e : modResourcePacks.entrySet()) {
|
||||
IModInfo mod = e.getKey().getModInfos().get(0);
|
||||
if (Objects.equals(mod.getModId(), "minecraft")) continue; // skip the minecraft "mod"
|
||||
final String name = "mod:" + mod.getModId();
|
||||
|
||||
var supplier = new Pack.ResourcesSupplier() {
|
||||
@Override
|
||||
public PackResources openPrimary(String path) {
|
||||
return e.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackResources openFull(String path, Info info) {
|
||||
return e.getValue(); // TODO: composite
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
final Pack modPack = Pack.readMetaAndCreate(name, Component.literal(e.getValue().packId()), false, supplier, PackType.SERVER_DATA, Pack.Position.BOTTOM, PackSource.DEFAULT);
|
||||
if (modPack == null) {
|
||||
// Vanilla only logs an error, instead of propagating, so handle null and warn that something went wrong
|
||||
ModLoader.get().addWarning(new ModLoadingWarning(mod, ModLoadingStage.ERROR, "fml.modloading.brokenresources", e.getKey()));
|
||||
continue;
|
||||
}
|
||||
LOGGER.debug(Logging.CORE, "Generating PackInfo named {} for mod file {}", name, e.getKey().getFilePath());
|
||||
packAcceptor.accept(modPack);
|
||||
}
|
||||
}
|
||||
|
||||
private static void runModifiers(final MinecraftServer server) {
|
||||
final RegistryAccess registries = server.registryAccess();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue