mirror of
https://github.com/FabricMC/fabric.git
synced 2025-04-21 11:20:55 -04:00
Add Support for Custom ColorResolvers (#3503)
* Add support for custom color resolvers
* Add ColorResolverRegistry
* Fix checkstyle
* Statically initialize all BiomeColorCaches
(cherry picked from commit 6fd945a052
)
This commit is contained in:
parent
1dcf7c2a51
commit
7e4ca3e18b
10 changed files with 341 additions and 0 deletions
fabric-rendering-v1/src
client
java/net/fabricmc/fabric
api/client/rendering/v1
impl/client/rendering
mixin/client/rendering
resources
testmod
testmodClient
java/net/fabricmc/fabric/test/rendering/client
resources/assets/fabric-rendering-v1-testmod
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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.api.client.rendering.v1;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.UnmodifiableView;
|
||||
|
||||
import net.minecraft.client.color.world.BiomeColors;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.minecraft.world.biome.ColorResolver;
|
||||
|
||||
import net.fabricmc.fabric.impl.client.rendering.ColorResolverRegistryImpl;
|
||||
|
||||
/**
|
||||
* The registry for custom {@link ColorResolver}s. Custom resolvers must be registered during client initialization for
|
||||
* them to be usable in {@link BlockRenderView#getColor}. Calling this method may throw an exception if the passed
|
||||
* resolver is not registered with this class. Vanilla resolvers found in {@link BiomeColors} are automatically
|
||||
* registered.
|
||||
*
|
||||
* <p>Other mods may also require custom resolvers to be registered if they provide additional functionality related to
|
||||
* color resolvers.
|
||||
*/
|
||||
public final class ColorResolverRegistry {
|
||||
private ColorResolverRegistry() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a custom {@link ColorResolver} for use in {@link BlockRenderView#getColor}. This method should be
|
||||
* called during client initialization.
|
||||
*
|
||||
* @param resolver the resolver to register
|
||||
*/
|
||||
public static void register(ColorResolver resolver) {
|
||||
ColorResolverRegistryImpl.register(resolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a view of all registered {@link ColorResolver}s, including all vanilla resolvers.
|
||||
*
|
||||
* @return a view of all registered resolvers
|
||||
*/
|
||||
@UnmodifiableView
|
||||
public static Set<ColorResolver> getAllResolvers() {
|
||||
return ColorResolverRegistryImpl.getAllResolvers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a view of all registered {@link ColorResolver}s, not including vanilla resolvers.
|
||||
*
|
||||
* @return a view of all registered custom resolvers
|
||||
*/
|
||||
@UnmodifiableView
|
||||
public static Set<ColorResolver> getCustomResolvers() {
|
||||
return ColorResolverRegistryImpl.getCustomResolvers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given {@link ColorResolver} is registered. Vanilla resolvers are always registered.
|
||||
*
|
||||
* @param resolver the resolver
|
||||
* @return whether the given resolver is registered
|
||||
*/
|
||||
public static boolean isRegistered(ColorResolver resolver) {
|
||||
return getAllResolvers().contains(resolver);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.impl.client.rendering;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
|
||||
import org.jetbrains.annotations.UnmodifiableView;
|
||||
|
||||
import net.minecraft.client.color.world.BiomeColors;
|
||||
import net.minecraft.client.world.BiomeColorCache;
|
||||
import net.minecraft.world.biome.ColorResolver;
|
||||
|
||||
public final class ColorResolverRegistryImpl {
|
||||
// Includes vanilla resolvers
|
||||
private static final Set<ColorResolver> ALL_RESOLVERS = new HashSet<>();
|
||||
// Does not include vanilla resolvers
|
||||
private static final Set<ColorResolver> CUSTOM_RESOLVERS = new HashSet<>();
|
||||
private static final Set<ColorResolver> ALL_RESOLVERS_VIEW = Collections.unmodifiableSet(ALL_RESOLVERS);
|
||||
private static final Set<ColorResolver> CUSTOM_RESOLVERS_VIEW = Collections.unmodifiableSet(CUSTOM_RESOLVERS);
|
||||
|
||||
static {
|
||||
ALL_RESOLVERS.add(BiomeColors.GRASS_COLOR);
|
||||
ALL_RESOLVERS.add(BiomeColors.FOLIAGE_COLOR);
|
||||
ALL_RESOLVERS.add(BiomeColors.WATER_COLOR);
|
||||
}
|
||||
|
||||
private ColorResolverRegistryImpl() {
|
||||
}
|
||||
|
||||
public static void register(ColorResolver resolver) {
|
||||
ALL_RESOLVERS.add(resolver);
|
||||
CUSTOM_RESOLVERS.add(resolver);
|
||||
}
|
||||
|
||||
@UnmodifiableView
|
||||
public static Set<ColorResolver> getAllResolvers() {
|
||||
return ALL_RESOLVERS_VIEW;
|
||||
}
|
||||
|
||||
@UnmodifiableView
|
||||
public static Set<ColorResolver> getCustomResolvers() {
|
||||
return CUSTOM_RESOLVERS_VIEW;
|
||||
}
|
||||
|
||||
public static Reference2ReferenceMap<ColorResolver, BiomeColorCache> createCustomCacheMap(Function<ColorResolver, BiomeColorCache> cacheFactory) {
|
||||
Reference2ReferenceOpenHashMap<ColorResolver, BiomeColorCache> map = new Reference2ReferenceOpenHashMap<>();
|
||||
|
||||
for (ColorResolver resolver : CUSTOM_RESOLVERS) {
|
||||
map.put(resolver, cacheFactory.apply(resolver));
|
||||
}
|
||||
|
||||
map.trim();
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.client.rendering;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap;
|
||||
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.callback.CallbackInfo;
|
||||
|
||||
import net.minecraft.client.world.BiomeColorCache;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.biome.ColorResolver;
|
||||
|
||||
import net.fabricmc.fabric.impl.client.rendering.ColorResolverRegistryImpl;
|
||||
|
||||
@Mixin(ClientWorld.class)
|
||||
public abstract class ClientWorldMixin {
|
||||
// Do not use the vanilla map because it is an Object2ObjectArrayMap. Array maps have O(n) retrievals compared to
|
||||
// hash maps' O(1) retrievals. If many custom ColorResolvers are registered, this may have a non-negligible
|
||||
// performance impact.
|
||||
@Unique
|
||||
private final Reference2ReferenceMap<ColorResolver, BiomeColorCache> customColorCache = ColorResolverRegistryImpl.createCustomCacheMap(resolver -> new BiomeColorCache(pos -> calculateColor(pos, resolver)));
|
||||
|
||||
@Shadow
|
||||
public abstract int calculateColor(BlockPos pos, ColorResolver colorResolver);
|
||||
|
||||
@Inject(method = "resetChunkColor(Lnet/minecraft/util/math/ChunkPos;)V", at = @At("RETURN"))
|
||||
private void onResetChunkColor(ChunkPos chunkPos, CallbackInfo ci) {
|
||||
for (BiomeColorCache cache : customColorCache.values()) {
|
||||
cache.reset(chunkPos.x, chunkPos.z);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "reloadColor()V", at = @At("RETURN"))
|
||||
private void onReloadColor(CallbackInfo ci) {
|
||||
for (BiomeColorCache cache : customColorCache.values()) {
|
||||
cache.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@ModifyExpressionValue(method = "getColor(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/biome/ColorResolver;)I", at = @At(value = "INVOKE", target = "it/unimi/dsi/fastutil/objects/Object2ObjectArrayMap.get(Ljava/lang/Object;)Ljava/lang/Object;"))
|
||||
private Object modifyNullCache(/* BiomeColorCache */ Object cache, BlockPos pos, ColorResolver resolver) {
|
||||
if (cache == null) {
|
||||
cache = customColorCache.get(resolver);
|
||||
|
||||
if (cache == null) {
|
||||
throw new UnsupportedOperationException("ClientWorld.getColor called with unregistered ColorResolver " + resolver);
|
||||
}
|
||||
}
|
||||
|
||||
return cache;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
"BlockEntityRendererFactoriesMixin",
|
||||
"BuiltinModelItemRendererMixin",
|
||||
"CapeFeatureRendererMixin",
|
||||
"ClientWorldMixin",
|
||||
"DimensionEffectsAccessor",
|
||||
"EntityModelLayersAccessor",
|
||||
"EntityModelsMixin",
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.test.rendering;
|
||||
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
|
||||
public class CustomColorResolverTestInit implements ModInitializer {
|
||||
public static final Block CUSTOM_COLOR_BLOCK = new Block(AbstractBlock.Settings.create());
|
||||
public static final Item CUSTOM_COLOR_BLOCK_ITEM = new BlockItem(CUSTOM_COLOR_BLOCK, new Item.Settings());
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
Registry.register(Registries.BLOCK, new Identifier("fabric-rendering-v1-testmod", "custom_color_block"), CUSTOM_COLOR_BLOCK);
|
||||
Registry.register(Registries.ITEM, new Identifier("fabric-rendering-v1-testmod", "custom_color_block"), CUSTOM_COLOR_BLOCK_ITEM);
|
||||
}
|
||||
}
|
|
@ -8,11 +8,13 @@
|
|||
"entrypoints": {
|
||||
"main": [
|
||||
"net.fabricmc.fabric.test.rendering.CustomAtlasSourcesTestInit",
|
||||
"net.fabricmc.fabric.test.rendering.CustomColorResolverTestInit",
|
||||
"net.fabricmc.fabric.test.rendering.TooltipComponentTestInit"
|
||||
],
|
||||
"client": [
|
||||
"net.fabricmc.fabric.test.rendering.client.ArmorRenderingTests",
|
||||
"net.fabricmc.fabric.test.rendering.client.CustomAtlasSourcesTest",
|
||||
"net.fabricmc.fabric.test.rendering.client.CustomColorResolverTest",
|
||||
"net.fabricmc.fabric.test.rendering.client.DimensionalRenderingTest",
|
||||
"net.fabricmc.fabric.test.rendering.client.FeatureRendererTest",
|
||||
"net.fabricmc.fabric.test.rendering.client.HudAndShaderTest",
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.test.rendering.client;
|
||||
|
||||
import net.minecraft.world.biome.ColorResolver;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.ColorResolverRegistry;
|
||||
import net.fabricmc.fabric.test.rendering.CustomColorResolverTestInit;
|
||||
|
||||
public class CustomColorResolverTest implements ClientModInitializer {
|
||||
public static final ColorResolver TEST_COLOR_RESOLVER = (biome, x, z) -> {
|
||||
if (biome.hasPrecipitation()) {
|
||||
return 0xFFFF00FF;
|
||||
} else {
|
||||
return 0xFFFFFF00;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
ColorResolverRegistry.register(TEST_COLOR_RESOLVER);
|
||||
|
||||
ColorProviderRegistry.BLOCK.register((state, world, pos, tintIndex) -> {
|
||||
if (world != null && pos != null) {
|
||||
return world.getColor(pos, TEST_COLOR_RESOLVER);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}, CustomColorResolverTestInit.CUSTOM_COLOR_BLOCK);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"variants": {
|
||||
"": { "model": "fabric-rendering-v1-testmod:block/custom_color_block" }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"all": "fabric-rendering-v1-testmod:block/blank",
|
||||
"particle": "#all"
|
||||
},
|
||||
"elements": [
|
||||
{ "from": [ 0, 0, 0 ],
|
||||
"to": [ 16, 16, 16 ],
|
||||
"faces": {
|
||||
"down": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "cullface": "down" },
|
||||
"up": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "tintindex": 0, "cullface": "up" },
|
||||
"north": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "cullface": "north" },
|
||||
"south": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "cullface": "south" },
|
||||
"west": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "cullface": "west" },
|
||||
"east": { "uv": [ 0, 0, 16, 16 ], "texture": "#all", "cullface": "east" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Binary file not shown.
After ![]() (image error) Size: 83 B |
Loading…
Add table
Add a link
Reference in a new issue