Load mod-provided data packs and DRM entries ()

* Load mod-provided data packs and DRM entries in CreateWorldScreen

Fixes 

* Fix ModifyArg target

* Fix injection failure

* Fix again

* checkstyle

* Fix it once again

* Add data pack load test to biome api testmod

* Also fix this for the dedicated server

* Fix TestServer not loading data packs

* Load dynamic registry in TestServer
This commit is contained in:
apple502j 2022-05-31 20:11:41 +09:00 committed by GitHub
parent d51ff45ef2
commit 14b3ae007b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 181 additions and 33 deletions
fabric-biome-api-v1/src/testmod
java/net/fabricmc/fabric/test/biome
resources/data/fabric-biome-api-v1-testmod/worldgen/placed_feature
fabric-resource-loader-v0/src
client/java/net/fabricmc/fabric/mixin/resource/loader/client
main
java/net/fabricmc/fabric
impl/resource/loader
mixin/resource/loader
resources

View file

@ -111,6 +111,14 @@ public class FabricBiomeTest implements ModInitializer {
.add(ModificationPhase.ADDITIONS,
BiomeSelectors.tag(TagKey.of(Registry.BIOME_KEY, new Identifier(MOD_ID, "tag_selector_test"))),
context -> context.getEffects().setSkyColor(0x770000));
// Make sure data packs can define dynamic registry contents
// See #2225, #2261
BiomeModifications.addFeature(
BiomeSelectors.foundInOverworld(),
GenerationStep.Feature.VEGETAL_DECORATION,
RegistryKey.of(Registry.PLACED_FEATURE_KEY, new Identifier(MOD_ID, "concrete_pile"))
);
}
// These are used for testing the spacing of custom end biomes.

View file

@ -0,0 +1,26 @@
{
"feature": {
"type": "minecraft:block_pile",
"config": {
"state_provider": {
"type": "minecraft:simple_state_provider",
"state": {
"Name": "minecraft:red_concrete"
}
}
}
},
"placement": [
{
"type": "minecraft:count",
"count": 2
},
{
"type": "minecraft:in_square"
},
{
"type": "minecraft:heightmap",
"heightmap": "WORLD_SURFACE"
}
]
}

View file

@ -17,31 +17,36 @@
package net.fabricmc.fabric.mixin.resource.loader.client;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.JsonOps;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.client.gui.screen.world.CreateWorldScreen;
import net.minecraft.resource.DataPackSettings;
import net.minecraft.resource.ResourcePack;
import net.minecraft.resource.ResourceManager;
import net.minecraft.resource.ResourcePackManager;
import net.minecraft.resource.ResourcePackProfile;
import net.minecraft.resource.ResourceType;
import net.minecraft.util.dynamic.RegistryOps;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.fabricmc.fabric.impl.resource.loader.ModNioResourcePack;
import net.fabricmc.fabric.impl.resource.loader.ModResourcePackCreator;
import net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil;
import net.fabricmc.fabric.mixin.resource.loader.ResourcePackManagerAccessor;
@Mixin(CreateWorldScreen.class)
public class CreateWorldScreenMixin {
@Unique
private static DataPackSettings defaultDataPackSettings;
@Shadow
private ResourcePackManager packManager;
@ -53,35 +58,27 @@ public class CreateWorldScreenMixin {
return manager;
}
@Redirect(method = "create(Lnet/minecraft/client/MinecraftClient;Lnet/minecraft/client/gui/screen/Screen;)V", at = @At(value = "FIELD", target = "Lnet/minecraft/resource/DataPackSettings;SAFE_MODE:Lnet/minecraft/resource/DataPackSettings;", ordinal = 0))
private static DataPackSettings replaceDefaultSettings() {
return (defaultDataPackSettings = ModResourcePackUtil.createDefaultDataPackSettings());
}
@ModifyArg(method = "create(Lnet/minecraft/client/MinecraftClient;Lnet/minecraft/client/gui/screen/Screen;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/world/CreateWorldScreen;<init>(Lnet/minecraft/client/gui/screen/Screen;Lnet/minecraft/resource/DataPackSettings;Lnet/minecraft/client/gui/screen/world/MoreOptionsDialog;)V"), index = 1)
private static DataPackSettings useReplacedDefaultSettings(DataPackSettings dataPackSettings) {
return defaultDataPackSettings;
}
@Redirect(method = "method_41854", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/registry/DynamicRegistryManager$Mutable;toImmutable()Lnet/minecraft/util/registry/DynamicRegistryManager$Immutable;"))
private static DynamicRegistryManager.Immutable loadDynamicRegistry(DynamicRegistryManager.Mutable mutableRegistryManager, ResourceManager dataPackManager) {
// This loads the dynamic registry from the data pack
RegistryOps.ofLoaded(JsonOps.INSTANCE, mutableRegistryManager, dataPackManager);
return mutableRegistryManager.toImmutable();
}
@Inject(method = "getScannedPack",
at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourcePackManager;scanPacks()V", shift = At.Shift.BEFORE))
private void onScanPacks(CallbackInfoReturnable<Pair<File, ResourcePackManager>> cir) {
// Allow to display built-in data packs in the data pack selection screen at world creation.
((ResourcePackManagerAccessor) this.packManager).getProviders().add(new ModResourcePackCreator(ResourceType.SERVER_DATA));
}
@ModifyArg(method = "create",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/world/CreateWorldScreen;<init>(Lnet/minecraft/client/gui/screen/Screen;Lnet/minecraft/resource/DataPackSettings;Lnet/minecraft/client/gui/screen/world/MoreOptionsDialog;)V"), index = 1)
private static DataPackSettings onNew(DataPackSettings settings) {
ModResourcePackCreator modResourcePackCreator = new ModResourcePackCreator(ResourceType.SERVER_DATA);
List<ResourcePackProfile> moddedResourcePacks = new ArrayList<>();
modResourcePackCreator.register(moddedResourcePacks::add);
List<String> enabled = new ArrayList<>(settings.getEnabled());
List<String> disabled = new ArrayList<>(settings.getDisabled());
// This ensure that any built-in registered data packs by mods which needs to be enabled by default are
// as the data pack screen automatically put any data pack as disabled except the Default data pack.
for (ResourcePackProfile profile : moddedResourcePacks) {
ResourcePack pack = profile.createResourcePack();
if (pack instanceof ModNioResourcePack && ((ModNioResourcePack) pack).getActivationType().isEnabledByDefault()) {
enabled.add(profile.getName());
} else {
disabled.add(profile.getName());
}
}
return new DataPackSettings(enabled, disabled);
}
}

View file

@ -17,6 +17,7 @@
package net.fabricmc.fabric.impl.resource.loader;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Charsets;
@ -24,6 +25,9 @@ import org.apache.commons.io.IOUtils;
import org.jetbrains.annotations.Nullable;
import net.minecraft.SharedConstants;
import net.minecraft.resource.DataPackSettings;
import net.minecraft.resource.ResourcePack;
import net.minecraft.resource.ResourcePackProfile;
import net.minecraft.resource.ResourceType;
import net.fabricmc.fabric.api.resource.ModResourcePack;
@ -89,4 +93,32 @@ public final class ModResourcePackUtil {
return "Fabric Mod \"" + info.getId() + "\"";
}
}
/**
* Creates the default data pack settings that replaces
* {@code DataPackSettings.SAFE_MODE} used in vanilla.
* @return the default data pack settings
*/
public static DataPackSettings createDefaultDataPackSettings() {
ModResourcePackCreator modResourcePackCreator = new ModResourcePackCreator(ResourceType.SERVER_DATA);
List<ResourcePackProfile> moddedResourcePacks = new ArrayList<>();
modResourcePackCreator.register(moddedResourcePacks::add);
List<String> enabled = new ArrayList<>(DataPackSettings.SAFE_MODE.getEnabled());
List<String> disabled = new ArrayList<>(DataPackSettings.SAFE_MODE.getDisabled());
// This ensures that any built-in registered data packs by mods which needs to be enabled by default are
// as the data pack screen automatically put any data pack as disabled except the Default data pack.
for (ResourcePackProfile profile : moddedResourcePacks) {
try (ResourcePack pack = profile.createResourcePack()) {
if (pack instanceof FabricModResourcePack || (pack instanceof ModNioResourcePack && ((ModNioResourcePack) pack).getActivationType().isEnabledByDefault())) {
enabled.add(profile.getName());
} else {
disabled.add(profile.getName());
}
}
}
return new DataPackSettings(enabled, disabled);
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.mixin.resource.loader;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import net.minecraft.resource.DataPackSettings;
import net.minecraft.server.Main;
import net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil;
@Mixin(Main.class)
public class MainMixin {
@Redirect(method = "main", at = @At(value = "FIELD", target = "Lnet/minecraft/resource/DataPackSettings;SAFE_MODE:Lnet/minecraft/resource/DataPackSettings;"))
private static DataPackSettings replaceDefaultDataPackSettings() {
return ModResourcePackUtil.createDefaultDataPackSettings();
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.mixin.resource.loader;
import java.util.function.Supplier;
import com.mojang.serialization.JsonOps;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import net.minecraft.resource.DataPackSettings;
import net.minecraft.resource.ResourceManager;
import net.minecraft.test.TestServer;
import net.minecraft.util.dynamic.RegistryOps;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil;
@Mixin(TestServer.class)
public class TestServerMixin {
@Redirect(method = "create", at = @At(value = "FIELD", target = "Lnet/minecraft/resource/DataPackSettings;SAFE_MODE:Lnet/minecraft/resource/DataPackSettings;"))
private static DataPackSettings replaceDefaultDataPackSettings() {
return ModResourcePackUtil.createDefaultDataPackSettings();
}
@SuppressWarnings("unchecked")
@Redirect(method = "method_40377", at = @At(value = "INVOKE", target = "Ljava/util/function/Supplier;get()Ljava/lang/Object;"))
private static <T> T loadRegistry(Supplier<T> unused, ResourceManager resourceManager) {
DynamicRegistryManager.Mutable mutableRegistryManager = DynamicRegistryManager.createAndLoad();
// This loads the dynamic registry manager
RegistryOps.ofLoaded(JsonOps.INSTANCE, mutableRegistryManager, resourceManager);
return (T) mutableRegistryManager.toImmutable();
}
}

View file

@ -3,17 +3,19 @@
"package": "net.fabricmc.fabric.mixin.resource.loader",
"compatibilityLevel": "JAVA_16",
"mixins": [
"FileResourcePackProviderAccessor",
"DefaultResourcePackMixin",
"FileResourcePackProviderAccessor",
"KeyedResourceReloadListenerMixin",
"LifecycledResourceManagerImplMixin",
"MainMixin",
"MinecraftServerMixin",
"NamespaceResourceManagerAccessor",
"NamespaceResourceManagerMixin",
"ReloadableResourceManagerImplMixin",
"ResourcePackManagerMixin",
"ResourcePackManagerAccessor",
"SimpleResourceReloadMixin"
"ResourcePackManagerMixin",
"SimpleResourceReloadMixin",
"TestServerMixin"
],
"injectors": {
"defaultRequire": 1