diff --git a/src/main/java/net/fabricmc/fabric/api/client/render/ColorProviderRegistry.java b/src/main/java/net/fabricmc/fabric/api/client/render/ColorProviderRegistry.java new file mode 100644 index 000000000..88e23ffbe --- /dev/null +++ b/src/main/java/net/fabricmc/fabric/api/client/render/ColorProviderRegistry.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, 2017, 2018 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.render; + +import net.fabricmc.fabric.impl.client.render.ColorProviderRegistryImpl; +import net.minecraft.block.Block; +import net.minecraft.client.render.block.BlockColorMapper; +import net.minecraft.client.render.item.ItemColorMapper; +import net.minecraft.item.ItemContainer; + +public interface ColorProviderRegistry { + ColorProviderRegistry ITEM = ColorProviderRegistryImpl.ITEM; + + ColorProviderRegistry BLOCK = ColorProviderRegistryImpl.BLOCK; + + /** + * Register a color provider for one or more objects + * + * @param provider The color provider to register. + * @param objects The objects which should be colored using this provider. + */ + void register(Provider provider, T... objects); + + /** + * Get a color provider for the given object. + * + * Please note that the underlying registry may not be fully populated or stable until the game has started, + * as other mods may overwrite the registry. + * + * @param object The object to acquire the provide for. + * @return The registered mapper for this provider, or {@code null} if none is registered or available. + */ + Provider get(T object); +} diff --git a/src/main/java/net/fabricmc/fabric/impl/client/render/ColorProviderRegistryImpl.java b/src/main/java/net/fabricmc/fabric/impl/client/render/ColorProviderRegistryImpl.java new file mode 100644 index 000000000..c635679db --- /dev/null +++ b/src/main/java/net/fabricmc/fabric/impl/client/render/ColorProviderRegistryImpl.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, 2017, 2018 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.render; + +import net.fabricmc.fabric.api.client.render.ColorProviderRegistry; +import net.minecraft.block.Block; +import net.minecraft.client.render.block.BlockColorMap; +import net.minecraft.client.render.block.BlockColorMapper; +import net.minecraft.client.render.item.ItemColorMap; +import net.minecraft.client.render.item.ItemColorMapper; +import net.minecraft.item.ItemContainer; + +import java.util.IdentityHashMap; +import java.util.Map; + +public abstract class ColorProviderRegistryImpl implements ColorProviderRegistry { + public static final ColorProviderRegistryImpl BLOCK = new ColorProviderRegistryImpl() { + @Override + void registerUnderlying(BlockColorMap map, BlockColorMapper mapper, Block block) { + map.register(mapper, block); + } + }; + + public static final ColorProviderRegistryImpl ITEM = new ColorProviderRegistryImpl() { + @Override + void registerUnderlying(ItemColorMap map, ItemColorMapper mapper, ItemContainer block) { + map.method_1708(mapper, block); + } + }; + + private Underlying colorMap; + private Map tempMappers = new IdentityHashMap<>(); + + abstract void registerUnderlying(Underlying colorMap, Provider provider, T objects); + + public void initialize(Underlying colorMap) { + if (this.colorMap != null) { + if (this.colorMap != colorMap) throw new IllegalStateException("Cannot set colorMap twice"); + return; + } + + this.colorMap = colorMap; + for (Map.Entry mappers : tempMappers.entrySet()) { + registerUnderlying(colorMap, mappers.getValue(), mappers.getKey()); + } + tempMappers = null; + } + + @Override + @SafeVarargs + public final void register(Provider provider, T... objects) { + if (colorMap != null) { + for (T object : objects) registerUnderlying(colorMap, provider, object); + } else { + for (T object : objects) tempMappers.put(object, provider); + } + } + + @Override + @SuppressWarnings("unchecked") + public Provider get(T object) { + return colorMap == null ? null : ((ColorMapperHolder) colorMap).get(object); + } + + public interface ColorMapperHolder { + Provider get(T item); + } +} diff --git a/src/main/java/net/fabricmc/fabric/mixin/client/render/MixinBlockColorMap.java b/src/main/java/net/fabricmc/fabric/mixin/client/render/MixinBlockColorMap.java new file mode 100644 index 000000000..06fcffc3d --- /dev/null +++ b/src/main/java/net/fabricmc/fabric/mixin/client/render/MixinBlockColorMap.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, 2017, 2018 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.render; + +import net.fabricmc.fabric.impl.client.render.ColorProviderRegistryImpl; +import net.minecraft.block.Block; +import net.minecraft.client.render.block.BlockColorMap; +import net.minecraft.client.render.block.BlockColorMapper; +import net.minecraft.util.IdList; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(BlockColorMap.class) +public class MixinBlockColorMap implements ColorProviderRegistryImpl.ColorMapperHolder { + @Shadow + @Final + private IdList mappers; + + @Inject(method = "create", at = @At("RETURN")) + private static void create(CallbackInfoReturnable info) { + ColorProviderRegistryImpl.BLOCK.initialize(info.getReturnValue()); + } + + @Override + public BlockColorMapper get(Block block) { + return mappers.getInt(Registry.BLOCK.getRawId(block)); + } +} diff --git a/src/main/java/net/fabricmc/fabric/mixin/client/render/MixinItemColorMap.java b/src/main/java/net/fabricmc/fabric/mixin/client/render/MixinItemColorMap.java new file mode 100644 index 000000000..c52ab756f --- /dev/null +++ b/src/main/java/net/fabricmc/fabric/mixin/client/render/MixinItemColorMap.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, 2017, 2018 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.render; + +import net.fabricmc.fabric.impl.client.render.ColorProviderRegistryImpl; +import net.minecraft.client.render.block.BlockColorMap; +import net.minecraft.client.render.item.ItemColorMap; +import net.minecraft.client.render.item.ItemColorMapper; +import net.minecraft.item.ItemContainer; +import net.minecraft.util.IdList; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ItemColorMap.class) +public class MixinItemColorMap implements ColorProviderRegistryImpl.ColorMapperHolder { + @Shadow + @Final + private IdList field_1996; + + @Inject(method = "method_1706", at = @At("RETURN")) + private static void method_1706(BlockColorMap blockMap, CallbackInfoReturnable info) { + ColorProviderRegistryImpl.ITEM.initialize(info.getReturnValue()); + } + + @Override + public ItemColorMapper get(ItemContainer item) { + return field_1996.getInt(Registry.ITEM.getRawId(item.getItem())); + } +} diff --git a/src/main/resources/net.fabricmc.fabric.mixins.client.json b/src/main/resources/net.fabricmc.fabric.mixins.client.json index 102b0307d..4c8fa0393 100644 --- a/src/main/resources/net.fabricmc.fabric.mixins.client.json +++ b/src/main/resources/net.fabricmc.fabric.mixins.client.json @@ -5,8 +5,10 @@ "mixins": [ "block.entity.MixinClientPlayNetworkHandler", "bugfix.MixinBiomeColors", + "client.render.MixinBlockColorMap", "client.render.MixinBlockEntityRenderManager", "client.render.MixinEntityRenderManager", + "client.render.MixinItemColorMap", "client.texture.MixinSpriteAtlasTexture", "events.playerinteraction.MixinClientPlayerInteractionManager", "events.tick.MixinMinecraftClient", @@ -19,4 +21,4 @@ "injectors": { "defaultRequire": 1 } -} \ No newline at end of file +} diff --git a/src/test/java/net/fabricmc/fabric/colormapper/ColorProviderMod.java b/src/test/java/net/fabricmc/fabric/colormapper/ColorProviderMod.java new file mode 100644 index 000000000..323437935 --- /dev/null +++ b/src/test/java/net/fabricmc/fabric/colormapper/ColorProviderMod.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, 2017, 2018 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.colormapper; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.render.ColorProviderRegistry; +import net.minecraft.block.Blocks; +import net.minecraft.client.render.block.BlockColorMapper; +import net.minecraft.item.Items; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ColorProviderMod implements ClientModInitializer { + private static final boolean ENABLED = true; + + private static final Logger LOGGER = LogManager.getLogger(); + + @Override + public void onInitializeClient() { + if (!ENABLED) return; + LOGGER.info("Initialising ColorProviderMod"); + + // Redstone is now the same color as grass + ColorProviderRegistry.BLOCK.register((block, pos, world, layer) -> { + BlockColorMapper provider = ColorProviderRegistry.BLOCK.get(Blocks.GRASS); + return provider == null ? -1 : provider.getColor(block, pos, world, layer); + }, Blocks.REDSTONE_WIRE); + + // Make white dye glow red. + ColorProviderRegistry.ITEM.register((item, layer) -> + (int) (64 * (Math.sin(System.currentTimeMillis() / 5e2) + 3)) << 16, + Items.WHITE_DYE); + } +} diff --git a/src/test/resources/mod.json b/src/test/resources/mod.json new file mode 100644 index 000000000..c43aa5f21 --- /dev/null +++ b/src/test/resources/mod.json @@ -0,0 +1,11 @@ +{ + "id": "fabric_test", + "name": "Fabric API Tests", + "version": "0.1.1", + "side": "universal", + "description": "A series of test mods to check Fabric works.", + "license": "Apache-2.0", + "initializers": [ + "net.fabricmc.fabric.colormapper.ColorProviderMod" + ] +}