mirror of
https://github.com/FabricMC/fabric.git
synced 2025-04-08 21:14:41 -04:00
Fix modded oxidizable blocks not oxidizing (#4436)
Fixes #4371 `OxidizableBlocksRegistry.registerOxidizableBlockPair` will now re-cache the value of the `ticksRandomly` field of the passed blocks' states to ensure that the default implementation of oxidization will actually work on the blocks. This may be considered a slightly dirty workaround, but it works well and isn't particularly intrusive, despite using 2 mixins. I've also included a test (though not a GameTest) to ensure that this works, and split the `OxidizableBlocksRegistry` into separate API and impl classes to more easily allow for potential extensibility in future while not breaking compatibility.
This commit is contained in:
parent
6816ccd43b
commit
25d1a67691
6 changed files with 156 additions and 13 deletions
fabric-content-registries-v0/src
main
java/net/fabricmc/fabric
api/registry
impl/content/registry
mixin/content/registry
resources
testmod/java/net/fabricmc/fabric/test/content/registry
|
@ -16,11 +16,9 @@
|
|||
|
||||
package net.fabricmc.fabric.api.registry;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Oxidizable;
|
||||
import net.minecraft.item.HoneycombItem;
|
||||
|
||||
import net.fabricmc.fabric.impl.content.registry.OxidizableBlocksRegistryImpl;
|
||||
|
||||
/**
|
||||
* Provides methods for registering oxidizable and waxable blocks.
|
||||
|
@ -36,9 +34,7 @@ public final class OxidizableBlocksRegistry {
|
|||
* @param more the variant with more oxidation
|
||||
*/
|
||||
public static void registerOxidizableBlockPair(Block less, Block more) {
|
||||
Objects.requireNonNull(less, "Oxidizable block cannot be null!");
|
||||
Objects.requireNonNull(more, "Oxidizable block cannot be null!");
|
||||
Oxidizable.OXIDATION_LEVEL_INCREASES.get().put(less, more);
|
||||
OxidizableBlocksRegistryImpl.registerOxidizableBlockPair(less, more);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,8 +44,6 @@ public final class OxidizableBlocksRegistry {
|
|||
* @param waxed the waxed variant
|
||||
*/
|
||||
public static void registerWaxableBlockPair(Block unwaxed, Block waxed) {
|
||||
Objects.requireNonNull(unwaxed, "Unwaxed block cannot be null!");
|
||||
Objects.requireNonNull(waxed, "Waxed block cannot be null!");
|
||||
HoneycombItem.UNWAXED_TO_WAXED_BLOCKS.get().put(unwaxed, waxed);
|
||||
OxidizableBlocksRegistryImpl.registerWaxableBlockPair(unwaxed, waxed);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.content.registry;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Oxidizable;
|
||||
import net.minecraft.item.HoneycombItem;
|
||||
|
||||
public final class OxidizableBlocksRegistryImpl {
|
||||
private OxidizableBlocksRegistryImpl() {
|
||||
}
|
||||
|
||||
public static void registerOxidizableBlockPair(Block less, Block more) {
|
||||
Objects.requireNonNull(less, "Oxidizable block cannot be null!");
|
||||
Objects.requireNonNull(more, "Oxidizable block cannot be null!");
|
||||
Oxidizable.OXIDATION_LEVEL_INCREASES.get().put(less, more);
|
||||
// Fix #4371
|
||||
refreshRandomTickCache(less);
|
||||
refreshRandomTickCache(more);
|
||||
}
|
||||
|
||||
public static void registerWaxableBlockPair(Block unwaxed, Block waxed) {
|
||||
Objects.requireNonNull(unwaxed, "Unwaxed block cannot be null!");
|
||||
Objects.requireNonNull(waxed, "Waxed block cannot be null!");
|
||||
HoneycombItem.UNWAXED_TO_WAXED_BLOCKS.get().put(unwaxed, waxed);
|
||||
}
|
||||
|
||||
private static void refreshRandomTickCache(Block block) {
|
||||
block.getStateManager().getStates().forEach(state -> ((RandomTickCacheRefresher) state).fabric_api$refreshRandomTickCache());
|
||||
}
|
||||
|
||||
public interface RandomTickCacheRefresher {
|
||||
void fabric_api$refreshRandomTickCache();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.content.registry;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.BlockState;
|
||||
|
||||
@Mixin(AbstractBlock.class)
|
||||
public interface AbstractBlockMixin {
|
||||
@Invoker
|
||||
boolean callHasRandomTicks(BlockState state);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.content.registry;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.state.State;
|
||||
import net.minecraft.state.property.Property;
|
||||
|
||||
import net.fabricmc.fabric.impl.content.registry.OxidizableBlocksRegistryImpl;
|
||||
|
||||
@Mixin(AbstractBlock.AbstractBlockState.class)
|
||||
public abstract class AbstractBlockStateMixin extends State<Block, BlockState> implements OxidizableBlocksRegistryImpl.RandomTickCacheRefresher {
|
||||
@Shadow
|
||||
private boolean ticksRandomly;
|
||||
|
||||
private AbstractBlockStateMixin(Block owner, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap, MapCodec<BlockState> codec) {
|
||||
super(owner, propertyMap, codec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fabric_api$refreshRandomTickCache() {
|
||||
this.ticksRandomly = ((AbstractBlockMixin) this.owner).callHasRandomTicks(this.asBlockState());
|
||||
}
|
||||
|
||||
@Shadow
|
||||
protected BlockState asBlockState() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -3,18 +3,20 @@
|
|||
"package": "net.fabricmc.fabric.mixin.content.registry",
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"mixins": [
|
||||
"AbstractBlockMixin",
|
||||
"AbstractBlockStateMixin",
|
||||
"AxeItemAccessor",
|
||||
"BrewingRecipeRegistryBuilderMixin",
|
||||
"PathContextMixin",
|
||||
"FarmerWorkTaskAccessor",
|
||||
"FireBlockMixin",
|
||||
"FuelRegistryMixin",
|
||||
"GiveGiftsToHeroTaskAccessor",
|
||||
"GiveGiftsToHeroTaskMixin",
|
||||
"HoeItemAccessor",
|
||||
"HoneycombItemMixin",
|
||||
"LandPathNodeMakerMixin",
|
||||
"FireBlockMixin",
|
||||
"OxidizableMixin",
|
||||
"PathContextMixin",
|
||||
"ShovelItemAccessor",
|
||||
"VillagerEntityAccessor",
|
||||
"VillagerEntityMixin"
|
||||
|
|
|
@ -23,6 +23,8 @@ import net.minecraft.block.AbstractBlock;
|
|||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.Oxidizable;
|
||||
import net.minecraft.block.OxidizableBlock;
|
||||
import net.minecraft.entity.ai.pathing.PathNodeType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.HoeItem;
|
||||
|
@ -79,6 +81,9 @@ public final class ContentRegistryTest implements ModInitializer {
|
|||
public static final RegistryKey<Block> TEST_EVENT_BLOCK_KEY = RegistryKey.of(RegistryKeys.BLOCK, TEST_EVENT_ID);
|
||||
public static final RegistryEntry.Reference<GameEvent> TEST_EVENT = Registry.registerReference(Registries.GAME_EVENT, TEST_EVENT_ID, new GameEvent(GameEvent.DEFAULT_RANGE));
|
||||
|
||||
public static final RegistryKey<Block> TEST_OXIDIZING_BLOCK_KEY = RegistryKey.of(RegistryKeys.BLOCK, id("test_oxidizing"));
|
||||
public static final RegistryKey<Block> EXPOSED_TEST_OXIDIZING_BLOCK_KEY = RegistryKey.of(RegistryKeys.BLOCK, id("exposed_test_oxidizing"));
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
// Expected behavior:
|
||||
|
@ -92,6 +97,7 @@ public final class ContentRegistryTest implements ModInitializer {
|
|||
// - green wool is tillable to lime wool
|
||||
// - copper ore, iron ore, gold ore, and diamond ore can be waxed into their deepslate variants and scraped back again
|
||||
// - aforementioned ores can be scraped from diamond -> gold -> iron -> copper
|
||||
// - the 'test_oxidizing' block will randomly tick to oxidize into an 'exposed_test_oxidizing' block
|
||||
// - villagers can now collect, consume (at the same level of bread) and compost apples
|
||||
// - villagers can now collect oak saplings
|
||||
// - assign a loot table to the nitwit villager type
|
||||
|
@ -149,9 +155,20 @@ public final class ContentRegistryTest implements ModInitializer {
|
|||
throw new AssertionError("OxidizableBlocksRegistry didn't throw when blocks were null!");
|
||||
} catch (NullPointerException e) {
|
||||
// expected behavior
|
||||
LOGGER.info("OxidizableBlocksRegistry test passed!");
|
||||
LOGGER.info("OxidizableBlocksRegistry null test passed!");
|
||||
}
|
||||
|
||||
Block testOxidizingBlock = Registry.register(Registries.BLOCK, TEST_OXIDIZING_BLOCK_KEY, new OxidizableBlock(Oxidizable.OxidationLevel.UNAFFECTED, AbstractBlock.Settings.copy(Blocks.COPPER_BLOCK).registryKey(TEST_OXIDIZING_BLOCK_KEY)));
|
||||
Block exposedTestOxidizingBlock = Registry.register(Registries.BLOCK, EXPOSED_TEST_OXIDIZING_BLOCK_KEY, new OxidizableBlock(Oxidizable.OxidationLevel.EXPOSED, AbstractBlock.Settings.copy(Blocks.EXPOSED_COPPER).registryKey(EXPOSED_TEST_OXIDIZING_BLOCK_KEY)));
|
||||
|
||||
OxidizableBlocksRegistry.registerOxidizableBlockPair(testOxidizingBlock, exposedTestOxidizingBlock);
|
||||
|
||||
if (!testOxidizingBlock.getStateManager().getDefaultState().hasRandomTicks()) {
|
||||
throw new AssertionError("OxidizableBlocksRegistry didn't refresh random ticks cache for state!");
|
||||
}
|
||||
|
||||
LOGGER.info("OxidizableBlocksRegistry random ticks test passed!");
|
||||
|
||||
VillagerInteractionRegistries.registerFood(Items.APPLE, 4);
|
||||
VillagerInteractionRegistries.registerCompostable(Items.APPLE);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue