From 39266da312d918f2a1226dbc4d163e4891c5de18 Mon Sep 17 00:00:00 2001 From: Technici4n Date: Sat, 28 Nov 2020 20:46:56 +0100 Subject: [PATCH] Cache the fuel time map in the fuel registry (#1108) * Cache the fuel time map in the fuel registry * Use a faster map for the fuel times * Rebuild the fuel times map on the client side too * Use more compatible mixins * Replace a function overwrite by a TAIL inject * Mixin formatting * Indentation * Make cache thread-safe, switch to boxed collection (IHM) since most uses yield boxed results, refactor cache clearing * fix import formatting Co-authored-by: Player --- fabric-content-registries-v0/build.gradle | 1 + .../content/registry/FuelRegistryImpl.java | 35 +++++++++++++++++-- .../MixinAbstractFurnaceBlockEntity.java | 11 ++++++ .../client/MixinClientPlayNetworkHandler.java | 35 +++++++++++++++++++ .../fabric-content-registries-v0.mixins.json | 3 ++ .../src/main/resources/fabric.mod.json | 1 + 6 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/client/MixinClientPlayNetworkHandler.java diff --git a/fabric-content-registries-v0/build.gradle b/fabric-content-registries-v0/build.gradle index 1f464942e..fffacd5c7 100644 --- a/fabric-content-registries-v0/build.gradle +++ b/fabric-content-registries-v0/build.gradle @@ -3,5 +3,6 @@ version = getSubprojectVersion(project, "0.1.9") moduleDependencies(project, [ 'fabric-api-base', + 'fabric-lifecycle-events-v1', 'fabric-resource-loader-v0' ]) diff --git a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/impl/content/registry/FuelRegistryImpl.java b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/impl/content/registry/FuelRegistryImpl.java index 8d1dc9577..94da2ae6e 100644 --- a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/impl/content/registry/FuelRegistryImpl.java +++ b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/impl/content/registry/FuelRegistryImpl.java @@ -16,6 +16,7 @@ package net.fabricmc.fabric.impl.content.registry; +import java.util.IdentityHashMap; import java.util.Map; import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap; @@ -28,20 +29,38 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemConvertible; import net.minecraft.tag.Tag; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.registry.FuelRegistry; // TODO: Clamp values to 32767 (+ add hook for mods which extend the limit to disable the check?) -public class FuelRegistryImpl implements FuelRegistry { +public final class FuelRegistryImpl implements FuelRegistry { public static final FuelRegistryImpl INSTANCE = new FuelRegistryImpl(); private static final Logger LOGGER = LogManager.getLogger(); private final Object2IntMap itemCookTimes = new Object2IntLinkedOpenHashMap<>(); private final Object2IntMap> tagCookTimes = new Object2IntLinkedOpenHashMap<>(); + private volatile Map fuelTimeCache = null; // thread safe via copy-on-write mechanism - public FuelRegistryImpl() { } + public FuelRegistryImpl() { + ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, serverResourceManager, success) -> { + if (success) { + resetCache(); + } + }); + } + + public Map getFuelTimes() { + Map ret = fuelTimeCache; + + if (ret == null) { + fuelTimeCache = ret = new IdentityHashMap<>(AbstractFurnaceBlockEntity.createFuelTimeMap()); // IdentityHashMap is faster than vanilla's LinkedHashMap and suitable for Item keys + } + + return ret; + } @Override public Integer get(ItemConvertible item) { - return AbstractFurnaceBlockEntity.createFuelTimeMap().get(item.asItem()); + return getFuelTimes().get(item.asItem()); } @Override @@ -51,6 +70,7 @@ public class FuelRegistryImpl implements FuelRegistry { } itemCookTimes.put(item, cookTime.intValue()); + resetCache(); } @Override @@ -60,26 +80,31 @@ public class FuelRegistryImpl implements FuelRegistry { } tagCookTimes.put(tag, cookTime.intValue()); + resetCache(); } @Override public void remove(ItemConvertible item) { add(item, 0); + resetCache(); } @Override public void remove(Tag tag) { add(tag, 0); + resetCache(); } @Override public void clear(ItemConvertible item) { itemCookTimes.removeInt(item); + resetCache(); } @Override public void clear(Tag tag) { tagCookTimes.removeInt(tag); + resetCache(); } public void apply(Map map) { @@ -116,4 +141,8 @@ public class FuelRegistryImpl implements FuelRegistry { return tag.toString(); } + + public void resetCache() { + fuelTimeCache = null; + } } diff --git a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/MixinAbstractFurnaceBlockEntity.java b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/MixinAbstractFurnaceBlockEntity.java index cb918ef5d..d9dbf854a 100644 --- a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/MixinAbstractFurnaceBlockEntity.java +++ b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/MixinAbstractFurnaceBlockEntity.java @@ -21,6 +21,7 @@ import java.util.Map; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.block.entity.AbstractFurnaceBlockEntity; @@ -34,4 +35,14 @@ public class MixinAbstractFurnaceBlockEntity { private static void fuelTimeMapHook(CallbackInfoReturnable> info) { FuelRegistryImpl.INSTANCE.apply(info.getReturnValue()); } + + @Redirect(method = "canUseAsFuel", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/AbstractFurnaceBlockEntity;createFuelTimeMap()Ljava/util/Map;")) + private static Map canUseAsFuelRedirect() { + return FuelRegistryImpl.INSTANCE.getFuelTimes(); + } + + @Redirect(method = "getFuelTime", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/AbstractFurnaceBlockEntity;createFuelTimeMap()Ljava/util/Map;")) + private Map getFuelTimeRedirect() { + return FuelRegistryImpl.INSTANCE.getFuelTimes(); + } } diff --git a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/client/MixinClientPlayNetworkHandler.java b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/client/MixinClientPlayNetworkHandler.java new file mode 100644 index 000000000..c4d41bdbe --- /dev/null +++ b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/client/MixinClientPlayNetworkHandler.java @@ -0,0 +1,35 @@ +/* + * 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.client; + +import org.spongepowered.asm.mixin.Mixin; +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.network.ClientPlayNetworkHandler; +import net.minecraft.network.packet.s2c.play.SynchronizeTagsS2CPacket; + +import net.fabricmc.fabric.impl.content.registry.FuelRegistryImpl; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class MixinClientPlayNetworkHandler { + @Inject(at = @At("TAIL"), method = "onSynchronizeTags") + private void onSynchronizeTagsHook(SynchronizeTagsS2CPacket packet, CallbackInfo info) { + FuelRegistryImpl.INSTANCE.resetCache(); + } +} diff --git a/fabric-content-registries-v0/src/main/resources/fabric-content-registries-v0.mixins.json b/fabric-content-registries-v0/src/main/resources/fabric-content-registries-v0.mixins.json index 505cc89f2..5d1fac7fa 100644 --- a/fabric-content-registries-v0/src/main/resources/fabric-content-registries-v0.mixins.json +++ b/fabric-content-registries-v0/src/main/resources/fabric-content-registries-v0.mixins.json @@ -6,6 +6,9 @@ "MixinAbstractFurnaceBlockEntity", "MixinFireBlock" ], + "client": [ + "client.MixinClientPlayNetworkHandler" + ], "injectors": { "defaultRequire": 1 } diff --git a/fabric-content-registries-v0/src/main/resources/fabric.mod.json b/fabric-content-registries-v0/src/main/resources/fabric.mod.json index 18b0e90ac..b7486229b 100644 --- a/fabric-content-registries-v0/src/main/resources/fabric.mod.json +++ b/fabric-content-registries-v0/src/main/resources/fabric.mod.json @@ -18,6 +18,7 @@ "depends": { "fabricloader": ">=0.4.0", "fabric-api-base": "*", + "fabric-lifecycle-events-v1": "*", "fabric-resource-loader-v0": "*" }, "description": "Adds registries for vanilla mechanics that are missing them.",