Skip to content

Commit

Permalink
[1.20.6] Add KnownPacks for mods (#901)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukebemish authored May 15, 2024
1 parent a28986f commit c888a68
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
public static void openFresh(Minecraft p_232897_, @Nullable Screen p_232898_) {
queueLoadScreen(p_232897_, PREPARING_WORLD_DATA);
PackRepository packrepository = new PackRepository(new ServerPacksSource(p_232897_.directoryValidator()));
+ net.neoforged.neoforge.resource.ResourcePackLoader.populatePackRepository(packrepository, net.minecraft.server.packs.PackType.SERVER_DATA);
+ net.neoforged.neoforge.resource.ResourcePackLoader.populatePackRepository(packrepository, net.minecraft.server.packs.PackType.SERVER_DATA, false);
WorldLoader.InitConfig worldloader$initconfig = createDefaultLoadConfig(packrepository, WorldDataConfiguration.DEFAULT);
CompletableFuture<WorldCreationContext> completablefuture = WorldLoader.load(
worldloader$initconfig,
Expand Down Expand Up @@ -32,7 +32,7 @@
if (path != null) {
if (this.tempDataPackRepository == null) {
this.tempDataPackRepository = ServerPacksSource.createPackRepository(path, this.packValidator);
+ net.neoforged.neoforge.resource.ResourcePackLoader.populatePackRepository(this.tempDataPackRepository, net.minecraft.server.packs.PackType.SERVER_DATA);
+ net.neoforged.neoforge.resource.ResourcePackLoader.populatePackRepository(this.tempDataPackRepository, net.minecraft.server.packs.PackType.SERVER_DATA, false);
this.tempDataPackRepository.reload();
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--- a/net/minecraft/client/multiplayer/KnownPacksManager.java
+++ b/net/minecraft/client/multiplayer/KnownPacksManager.java
@@ -44,6 +_,12 @@
}
}

+ if (list.size() > 1024) {
+ list = list.subList(0, 1024);
+ list1 = list1.subList(0, 1024);
+ com.mojang.logging.LogUtils.getLogger().warn("NeoForge: too many KnownPacks requested; only the first 1024 will be sent via KnownPack, the rest will be synced normally");
+ }
+
this.repository.setSelected(list1);
return list;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--- a/net/minecraft/network/protocol/configuration/ServerboundSelectKnownPacks.java
+++ b/net/minecraft/network/protocol/configuration/ServerboundSelectKnownPacks.java
@@ -10,7 +_,8 @@

public record ServerboundSelectKnownPacks(List<KnownPack> knownPacks) implements Packet<ServerConfigurationPacketListener> {
public static final StreamCodec<ByteBuf, ServerboundSelectKnownPacks> STREAM_CODEC = StreamCodec.composite(
- KnownPack.STREAM_CODEC.apply(ByteBufCodecs.list(64)), ServerboundSelectKnownPacks::knownPacks, ServerboundSelectKnownPacks::new
+ // Neo: increase cap on number of KnownPacks to sync back to the server. This is safe even on vanilla connections, as no more packs will be synced here than were received in the S2C packet
+ KnownPack.STREAM_CODEC.apply(ByteBufCodecs.list(1024)), ServerboundSelectKnownPacks::knownPacks, ServerboundSelectKnownPacks::new
);

@Override
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--- a/net/minecraft/server/network/config/SynchronizeRegistriesTask.java
+++ b/net/minecraft/server/network/config/SynchronizeRegistriesTask.java
@@ -45,11 +_,10 @@
}

public void handleResponse(List<KnownPack> p_326076_, Consumer<Packet<?>> p_326167_) {
- if (p_326076_.equals(this.requestedPacks)) {
- this.sendRegistries(p_326167_, Set.copyOf(this.requestedPacks));
- } else {
- this.sendRegistries(p_326167_, Set.of());
- }
+ // Neo: instead of using either all available KnownPacks or none, allow partial fallback to normal syncing
+ Set<KnownPack> requested = new java.util.HashSet<>(this.requestedPacks);
+ requested.retainAll(p_326076_);
+ this.sendRegistries(p_326167_, requested);
}

@Override
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
--- a/net/minecraft/server/packs/repository/ServerPacksSource.java
+++ b/net/minecraft/server/packs/repository/ServerPacksSource.java
@@ -72,7 +_,9 @@
@@ -72,11 +_,15 @@
}

public static PackRepository createPackRepository(Path p_251569_, DirectoryValidator p_295336_) {
- return new PackRepository(new ServerPacksSource(p_295336_), new FolderRepositorySource(p_251569_, PackType.SERVER_DATA, PackSource.WORLD, p_295336_));
+ final PackRepository packRepository = new PackRepository(new ServerPacksSource(p_295336_), new FolderRepositorySource(p_251569_, PackType.SERVER_DATA, PackSource.WORLD, p_295336_));
+ net.neoforged.neoforge.resource.ResourcePackLoader.populatePackRepository(packRepository, PackType.SERVER_DATA);
+ net.neoforged.neoforge.resource.ResourcePackLoader.populatePackRepository(packRepository, PackType.SERVER_DATA, false);
+ return packRepository;
}

public static PackRepository createVanillaTrustedRepository() {
- return new PackRepository(new ServerPacksSource(new DirectoryValidator(p_293813_ -> true)));
+ final PackRepository packRepository = new PackRepository(new ServerPacksSource(new DirectoryValidator(p_293813_ -> true)));
+ net.neoforged.neoforge.resource.ResourcePackLoader.populatePackRepository(packRepository, PackType.SERVER_DATA, true);
+ return packRepository;
}

public static PackRepository createPackRepository(LevelStorageSource.LevelStorageAccess p_250213_) {
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public static void begin(final Minecraft minecraft, final PackRepository default
error = e;
}
if (error == null) {
ResourcePackLoader.populatePackRepository(defaultResourcePacks, PackType.CLIENT_RESOURCES);
ResourcePackLoader.populatePackRepository(defaultResourcePacks, PackType.CLIENT_RESOURCES, false);
DataPackConfig.DEFAULT.addModPacks(ResourcePackLoader.getPackNames(PackType.SERVER_DATA));
mcResourceManager.registerReloadListener(ClientModLoader::onResourceReload);
mcResourceManager.registerReloadListener(BrandingControl.resourceManagerReloadListener());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,28 @@
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.PathPackResources;
import net.minecraft.server.packs.repository.BuiltInPackSource;
import net.minecraft.server.packs.repository.KnownPack;
import net.minecraft.server.packs.repository.Pack;
import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.server.packs.repository.PackSource;
import net.minecraft.server.packs.repository.RepositorySource;
import net.neoforged.bus.api.Event;
import net.neoforged.fml.ModList;
import net.neoforged.fml.event.IModBusEvent;
import net.neoforged.neoforgespi.language.IModInfo;

/**
* Fired on {@link PackRepository} creation to allow mods to add new pack finders.
*/
public class AddPackFindersEvent extends Event implements IModBusEvent {
private final PackType packType;
private final Consumer<RepositorySource> sources;
private final boolean trusted;

public AddPackFindersEvent(PackType packType, Consumer<RepositorySource> sources) {
public AddPackFindersEvent(PackType packType, Consumer<RepositorySource> sources, boolean trusted) {
this.packType = packType;
this.sources = sources;
this.trusted = trusted;
}

/**
Expand Down Expand Up @@ -66,15 +70,26 @@ public PackType getPackType() {
*/
public void addPackFinders(ResourceLocation packLocation, PackType packType, Component packNameDisplay, PackSource packSource, boolean alwaysActive, Pack.Position packPosition) {
if (getPackType() == packType) {
var resourcePath = ModList.get().getModFileById(packLocation.getNamespace()).getFile().findResource(packLocation.getPath());
IModInfo modInfo = ModList.get().getModContainerById(packLocation.getNamespace()).orElseThrow(() -> new IllegalArgumentException("Mod not found: " + packLocation.getNamespace())).getModInfo();

var resourcePath = modInfo.getOwningFile().getFile().findResource(packLocation.getPath());

var version = modInfo.getVersion();

var pack = Pack.readMetaAndCreate(
new PackLocationInfo("mod/" + packLocation, packNameDisplay, packSource, Optional.empty()),
new PackLocationInfo("mod/" + packLocation, packNameDisplay, packSource, Optional.of(new KnownPack("neoforge", "mod/" + packLocation, version.toString()))),
BuiltInPackSource.fromName((path) -> new PathPackResources(path, resourcePath)),
packType,
new PackSelectionConfig(alwaysActive, packPosition, false));

addRepositorySource((packConsumer) -> packConsumer.accept(pack));
}
}

/**
* {@return whether or not the pack repository being assembled is the one used to provide known packs to the client to avoid syncing from the server}
*/
public boolean isTrusted() {
return trusted;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import net.minecraft.server.packs.PathPackResources;
import net.minecraft.server.packs.metadata.MetadataSectionType;
import net.minecraft.server.packs.metadata.pack.PackMetadataSection;
import net.minecraft.server.packs.repository.KnownPack;
import net.minecraft.server.packs.repository.Pack;
import net.minecraft.server.packs.repository.PackCompatibility;
import net.minecraft.server.packs.repository.PackRepository;
Expand All @@ -51,6 +52,7 @@
import net.neoforged.neoforgespi.locating.IModFile;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.jetbrains.annotations.ApiStatus;

public class ResourcePackLoader {
Expand All @@ -64,12 +66,12 @@ public static Optional<Pack.ResourcesSupplier> getPackFor(String modId) {
return Optional.ofNullable(ModList.get().getModFileById(modId)).map(IModFileInfo::getFile).map(mf -> modResourcePacks.get(mf));
}

public static void populatePackRepository(PackRepository resourcePacks, PackType packType) {
public static void populatePackRepository(PackRepository resourcePacks, PackType packType, boolean trusted) {
findResourcePacks();
// First add the mod's builtin packs
resourcePacks.addPackFinder(buildPackFinder(modResourcePacks, packType));
// Then fire the event to add more packs
ModLoader.postEvent(new AddPackFindersEvent(packType, resourcePacks::addPackFinder));
ModLoader.postEvent(new AddPackFindersEvent(packType, resourcePacks::addPackFinder, trusted));
}

private synchronized static void findResourcePacks() {
Expand All @@ -92,15 +94,16 @@ private static void packFinder(Map<IModFile, Pack.ResourcesSupplier> modResource
for (Map.Entry<IModFile, Pack.ResourcesSupplier> e : modResourcePacks.entrySet()) {
IModInfo mod = e.getKey().getModInfos().get(0);
if ("minecraft".equals(mod.getModId())) continue; // skip the minecraft "mod"
final String name = "mod/" + mod.getModId();
final String packName = mod.getOwningFile().getFile().getFileName();
final String name = "mod/" + e.getKey().getModInfos().stream().map(IModInfo::getModId).collect(Collectors.joining(","));
final String version = e.getKey().getModInfos().stream().map(IModInfo::getVersion).map(ArtifactVersion::toString).collect(Collectors.joining(","));
final String packName = e.getKey().getFileName();

try {
var locationInfo = new PackLocationInfo(
name,
Component.literal(packName.isEmpty() ? "[unnamed]" : packName),
PackSource.DEFAULT,
Optional.empty());
Optional.of(new KnownPack("neoforge", name, version)));

final boolean isRequired = (packType == PackType.CLIENT_RESOURCES && mod.getOwningFile().showAsResourcePack()) || (packType == PackType.SERVER_DATA && mod.getOwningFile().showAsDataPack());
final Pack modPack;
Expand Down Expand Up @@ -202,7 +205,7 @@ public static List<String> getPackNames(PackType packType) {
ids.addAll(ModList.get().getModFiles().stream().filter(packType == PackType.CLIENT_RESOURCES ? IModFileInfo::showAsResourcePack : IModFileInfo::showAsDataPack)
.filter(mf -> mf.requiredLanguageLoaders().stream().noneMatch(ls -> ls.languageName().equals("minecraft")))
.map(IModFileInfo::getFile)
.map(mf -> "mod/" + mf.getModInfos().get(0).getModId())
.map(mf -> "mod/" + mf.getModInfos().stream().map(IModInfo::getModId).collect(Collectors.joining()))
.toList());
ids.add(packType == PackType.CLIENT_RESOURCES ? MOD_RESOURCES_ID : MOD_DATA_ID);
return ids;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.neoforge.debug.resources;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.util.Optional;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackLocationInfo;
import net.minecraft.server.packs.PackSelectionConfig;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.repository.BuiltInPackSource;
import net.minecraft.server.packs.repository.KnownPack;
import net.minecraft.server.packs.repository.Pack;
import net.minecraft.server.packs.repository.PackSource;
import net.minecraft.world.entity.Entity;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.neoforge.event.AddPackFindersEvent;
import net.neoforged.neoforge.oldtest.world.LoginPacketSplitTest;
import net.neoforged.testframework.DynamicTest;
import net.neoforged.testframework.Test;
import net.neoforged.testframework.TestFramework;
import net.neoforged.testframework.TestListener;
import net.neoforged.testframework.annotation.ForEachTest;
import net.neoforged.testframework.annotation.TestHolder;
import net.neoforged.testframework.annotation.WithListener;
import org.jetbrains.annotations.Nullable;

@ForEachTest(groups = BulkKnownPackTest.GROUP, side = Dist.CLIENT)
public class BulkKnownPackTest {
public static final String GROUP = "resources";
private static final String NAMESPACE = "bulk_known_pack_test";

@TestHolder(description = "Tests that KnownPacks are correctly synced even when more than the vanilla 64 are present", enabledByDefault = true)
@WithListener(BulkKnownPackTest.Listener.class)
static void bulkKnownPackTest(final DynamicTest test) {
test.framework().modEventBus().addListener(AddPackFindersEvent.class, event -> {
if (event.getPackType() == PackType.SERVER_DATA) {
for (int i = 0; i < 128; i++) {
var id = "bulk_known_pack_test/" + i;
PackLocationInfo info = new PackLocationInfo(id, Component.literal(i + "th containing single entry"), PackSource.BUILT_IN, Optional.of(new KnownPack(NAMESPACE, id, "1.0.0")));
final LoginPacketSplitTest.InMemoryResourcePack pack = new LoginPacketSplitTest.InMemoryResourcePack(info);
generateEntry(pack, i);
event.addRepositorySource(packs -> packs.accept(Pack.readMetaAndCreate(
pack.location(),
BuiltInPackSource.fixedResources(pack),
PackType.SERVER_DATA,
new PackSelectionConfig(true, Pack.Position.TOP, false))));
}
}
});
}

public static class Listener implements TestListener {
@Override
public void onEnabled(TestFramework framework, Test test, @Nullable Entity changer) {
if (changer == null) {
return;
}
RegistryAccess access = changer.registryAccess();
access.registry(Registries.BIOME).ifPresentOrElse(biomes -> {
for (int i = 0; i < 128; i++) {
var id = new ResourceLocation(NAMESPACE, "entry_" + i);
if (biomes.getHolder(id).isEmpty()) {
framework.changeStatus(test, Test.Status.failed("Entry " + id + " that should be synced by KnownPack not found"), changer);
return;
}
framework.changeStatus(test, Test.Status.passed(), changer);
}
}, () -> {
framework.changeStatus(test, Test.Status.failed("Failed to get biome registry"), changer);
});
}
}

private static void generateEntry(LoginPacketSplitTest.InMemoryResourcePack pack, int i) {
JsonObject json = new JsonObject();
json.addProperty("temperature", 1.0);
json.addProperty("downfall", 1.0);
json.addProperty("has_precipitation", false);
JsonObject effects = new JsonObject();
effects.addProperty("sky_color", 0.0);
effects.addProperty("fog_color", 0.0);
effects.addProperty("water_color", 0.0);
effects.addProperty("water_fog_color", 0.0);
json.add("effects", effects);
json.add("spawners", new JsonObject());
json.add("spawn_costs", new JsonObject());
json.add("carvers", new JsonObject());
json.add("features", new JsonArray());
pack.putData(new ResourceLocation(NAMESPACE, "worldgen/biome/entry_" + i + ".json"), json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public LoginPacketSplitTest(IEventBus bus) {
if (ENABLED) {
bus.addListener((final AddPackFindersEvent event) -> {
if (event.getPackType() == PackType.SERVER_DATA) {
// This pack info has no KnownPack, so it is actually synced
PackLocationInfo info = new PackLocationInfo("virtual_bigdata", Component.literal("Pack containing big datapack registries"), PackSource.BUILT_IN, Optional.empty());
final InMemoryResourcePack pack = new InMemoryResourcePack(info);
generateEntries(pack);
Expand Down Expand Up @@ -191,7 +192,7 @@ public IoSupplier<InputStream> getResource(PackType type, ResourceLocation loc)
public void listResources(PackType type, String namespace, String startingPath, ResourceOutput out) {
if (type != PackType.SERVER_DATA) return;
data.forEach((key, data) -> {
if (key.getNamespace().equals(namespace) && key.getPath().startsWith(startingPath)) {
if (key.getNamespace().equals(namespace) && key.getPath().startsWith(startingPath + "/")) {
final byte[] bytes = data.get();
if (bytes != null) {
out.accept(key, () -> new ByteArrayInputStream(bytes));
Expand Down

0 comments on commit c888a68

Please sign in to comment.