add flammable block registry, *2ObjectMap.clear to remove Fabric overrides (#75)

This commit is contained in:
Adrian Siekierka 2019-02-09 16:37:26 +01:00 committed by GitHub
parent 004281cdac
commit a585b4833e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 399 additions and 9 deletions

View file

@ -0,0 +1,73 @@
/*
* 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.registry;
import net.fabricmc.fabric.api.util.Block2ObjectMap;
import net.fabricmc.fabric.impl.registry.FlammableBlockRegistryImpl;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.tag.Tag;
public interface FlammableBlockRegistry extends Block2ObjectMap<FlammableBlockRegistry.Entry> {
static FlammableBlockRegistry getDefaultInstance() {
return getInstance(Blocks.FIRE);
}
static FlammableBlockRegistry getInstance(Block block) {
return FlammableBlockRegistryImpl.getInstance(block);
}
default void add(Block block, int burn, int spread) {
this.add(block, new Entry(burn, spread));
}
default void add(Tag<Block> tag, int burn, int spread) {
this.add(tag, new Entry(burn, spread));
}
public static final class Entry {
private final int burn, spread;
public Entry(int burn, int spread) {
this.burn = burn;
this.spread = spread;
}
public int getBurnChance() {
return burn;
}
public int getSpreadChance() {
return spread;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Entry)) {
return false;
} else {
Entry other = (Entry) o;
return other.burn == burn && other.spread == spread;
}
}
@Override
public int hashCode() {
return burn * 11 + spread;
}
}
}

View file

@ -17,6 +17,7 @@
package net.fabricmc.fabric.api.util;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemProvider;
import net.minecraft.tag.Tag;
@ -26,4 +27,6 @@ public interface Block2ObjectMap<V> {
void add(Tag<Block> tag, V value);
void remove(Block block);
void remove(Tag<Block> tag);
void clear(Block block);
void clear(Tag<Block> tag);
}

View file

@ -26,4 +26,6 @@ public interface Item2ObjectMap<V> {
void add(Tag<Item> tag, V value);
void remove(ItemProvider item);
void remove(Tag<Item> tag);
void clear(ItemProvider item);
void clear(Tag<Item> tag);
}

View file

@ -22,6 +22,9 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemProvider;
import net.minecraft.tag.Tag;
import java.util.ArrayList;
import java.util.List;
public class CompostingChanceRegistryImpl implements CompostingChanceRegistry {
@Override
public Float get(ItemProvider item) {
@ -47,4 +50,14 @@ public class CompostingChanceRegistryImpl implements CompostingChanceRegistry {
public void remove(Tag<Item> tag) {
throw new UnsupportedOperationException("Tags currently not supported!");
}
@Override
public void clear(ItemProvider item) {
throw new UnsupportedOperationException("CompostingChanceRegistry operates directly on the vanilla map - clearing not supported!");
}
@Override
public void clear(Tag<Item> tag) {
throw new UnsupportedOperationException("CompostingChanceRegistry operates directly on the vanilla map - clearing not supported!");
}
}

View file

@ -0,0 +1,24 @@
/*
* 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.registry;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.minecraft.block.Block;
public interface FireBlockHooks {
FlammableBlockRegistry.Entry fabric_getVanillaEntry(Block block);
}

View file

@ -0,0 +1,162 @@
/*
* 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.registry;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.fabric.api.resource.ResourceReloadListenerKeys;
import net.minecraft.block.Block;
import net.minecraft.resource.ResourceManager;
import net.minecraft.resource.ResourceType;
import net.minecraft.tag.Tag;
import net.minecraft.util.Identifier;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class FlammableBlockRegistryImpl implements FlammableBlockRegistry, IdentifiableResourceReloadListener {
private static final FlammableBlockRegistry.Entry REMOVED = new FlammableBlockRegistry.Entry(0, 0);
private static final Map<Block, FlammableBlockRegistryImpl> REGISTRIES = new HashMap<>();
private static final Collection<Identifier> RELOAD_DEPS = Collections.singletonList(ResourceReloadListenerKeys.TAGS);
private static int idCounter = 0;
private final Map<Block, FlammableBlockRegistry.Entry> registeredEntriesBlock = new HashMap<>();
private final Map<Tag<Block>, FlammableBlockRegistry.Entry> registeredEntriesTag = new HashMap<>();
private final Map<Block, FlammableBlockRegistry.Entry> computedEntries = new HashMap<>();
private final Object2IntMap<Block> computedBurnChances = new Object2IntOpenHashMap<>();
private final Object2IntMap<Block> computedSpreadChances = new Object2IntOpenHashMap<>();
private final Identifier id;
private final Block key;
private boolean tagsPresent = false;
private FlammableBlockRegistryImpl(Block key) {
ResourceManagerHelper.get(ResourceType.DATA).addReloadListener(this);
this.id = new Identifier("fabric:private/fire_registry_" + (++idCounter));
this.key = key;
}
@Override
public void onResourceReload(ResourceManager var1) {
reload();
tagsPresent = true;
}
private void reload() {
computedEntries.clear();
// tags take precedence before blocks
for (Tag<Block> tag : registeredEntriesTag.keySet()) {
FlammableBlockRegistry.Entry entry = registeredEntriesTag.get(tag);
for (Block block : tag.values()) {
computedEntries.put(block, entry);
}
}
computedEntries.putAll(registeredEntriesBlock);
computedBurnChances.clear();
computedSpreadChances.clear();
for (Block block : computedEntries.keySet()) {
FlammableBlockRegistry.Entry entry = computedEntries.get(block);
computedBurnChances.put(block, entry.getBurnChance());
computedSpreadChances.put(block, entry.getSpreadChance());
}
}
// User-facing fire registry interface - queries vanilla fire block
@Override
public Entry get(Block block) {
Entry entry = computedEntries.get(block);
if (entry != null) {
return entry;
} else {
return ((FireBlockHooks) key).fabric_getVanillaEntry(block);
}
}
public Entry getFabric(Block block) {
return computedEntries.get(block);
}
@Override
public void add(Block block, Entry value) {
registeredEntriesBlock.put(block, value);
if (tagsPresent) {
reload();
}
}
@Override
public void add(Tag<Block> tag, Entry value) {
registeredEntriesTag.put(tag, value);
if (tagsPresent) {
reload();
}
}
@Override
public void remove(Block block) {
add(block, REMOVED);
}
@Override
public void remove(Tag<Block> tag) {
add(tag, REMOVED);
}
@Override
public void clear(Block block) {
registeredEntriesBlock.remove(block);
if (tagsPresent) {
reload();
}
}
@Override
public void clear(Tag<Block> tag) {
registeredEntriesTag.remove(tag);
if (tagsPresent) {
reload();
}
}
public static FlammableBlockRegistryImpl getInstance(Block block) {
if (!(block instanceof FireBlockHooks)) {
throw new RuntimeException("Not a hookable fire block: " + block);
}
return REGISTRIES.computeIfAbsent(block, FlammableBlockRegistryImpl::new);
}
@Override
public Identifier getFabricId() {
return id;
}
@Override
public Collection<Identifier> getFabricDependencies() {
return RELOAD_DEPS;
}
}

View file

@ -70,16 +70,18 @@ public class FuelRegistryImpl implements FuelRegistry {
add(tag, 0);
}
public void apply(Map<Item, Integer> map) {
for (ItemProvider item : itemCookTimes.keySet()) {
int time = itemCookTimes.getInt(item);
if (time <= 0) {
map.remove(item.getItem());
} else {
map.put(item.getItem(), time);
}
}
@Override
public void clear(ItemProvider item) {
itemCookTimes.removeInt(item);
}
@Override
public void clear(Tag<Item> tag) {
tagCookTimes.removeInt(tag);
}
public void apply(Map<Item, Integer> map) {
// tags take precedence before blocks
for (Tag<Item> tag : tagCookTimes.keySet()) {
int time = tagCookTimes.getInt(tag);
if (time <= 0) {
@ -92,5 +94,14 @@ public class FuelRegistryImpl implements FuelRegistry {
}
}
}
for (ItemProvider item : itemCookTimes.keySet()) {
int time = itemCookTimes.getInt(item);
if (time <= 0) {
map.remove(item.getItem());
} else {
map.put(item.getItem(), time);
}
}
}
}

View file

@ -0,0 +1,72 @@
/*
* 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.block;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.fabricmc.fabric.impl.registry.FireBlockHooks;
import net.fabricmc.fabric.impl.registry.FlammableBlockRegistryImpl;
import net.minecraft.block.Block;
import net.minecraft.block.FireBlock;
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.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(FireBlock.class)
public class MixinFireBlock implements FireBlockHooks {
private FlammableBlockRegistryImpl fabric_registry;
@Shadow
private int getSpreadChance(Block block_1) {
return 0;
}
@Shadow
private int getBurnChance(Block block_1) {
return 0;
}
@Inject(at = @At("RETURN"), method = "<init>")
private void afterConstruct(Block.Settings settings, CallbackInfo info) {
fabric_registry = FlammableBlockRegistryImpl.getInstance((Block) (Object) this);
}
@Inject(at = @At("HEAD"), method = "getBurnChance", cancellable = true)
private void getFabricBurnChance(Block block, CallbackInfoReturnable info) {
FlammableBlockRegistry.Entry entry = fabric_registry.getFabric(block);
if (entry != null) {
info.setReturnValue(entry.getBurnChance());
info.cancel();
}
}
@Inject(at = @At("HEAD"), method = "getSpreadChance", cancellable = true)
private void getFabricSpreadChance(Block block, CallbackInfoReturnable info) {
FlammableBlockRegistry.Entry entry = fabric_registry.getFabric(block);
if (entry != null) {
info.setReturnValue(entry.getSpreadChance());
info.cancel();
}
}
@Override
public FlammableBlockRegistry.Entry fabric_getVanillaEntry(Block block) {
return new FlammableBlockRegistry.Entry(getBurnChance(block), getSpreadChance(block));
}
}

View file

@ -4,6 +4,7 @@
"compatibilityLevel": "JAVA_8",
"mixins": [
"block.MixinBlockBuilder",
"block.MixinFireBlock",
"block.entity.MixinBlockEntity",
"commands.MixinServerCommandManager",
"container.MixinServerPlayerEntity",

View file

@ -0,0 +1,29 @@
/*
* 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.block;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.minecraft.block.Blocks;
public class FireMod implements ModInitializer {
@Override
public void onInitialize() {
FlammableBlockRegistry.getDefaultInstance().add(Blocks.STONE, 100, 100);
FlammableBlockRegistry.getDefaultInstance().remove(Blocks.OAK_PLANKS);
}
}