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 <player@player.to>
This commit is contained in:
Technici4n 2020-11-28 20:46:56 +01:00 committed by GitHub
parent 2857667513
commit 39266da312
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 83 additions and 3 deletions

View file

@ -3,5 +3,6 @@ version = getSubprojectVersion(project, "0.1.9")
moduleDependencies(project, [
'fabric-api-base',
'fabric-lifecycle-events-v1',
'fabric-resource-loader-v0'
])

View file

@ -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<ItemConvertible> itemCookTimes = new Object2IntLinkedOpenHashMap<>();
private final Object2IntMap<Tag<Item>> tagCookTimes = new Object2IntLinkedOpenHashMap<>();
private volatile Map<Item, Integer> 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<Item, Integer> getFuelTimes() {
Map<Item, Integer> 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<Item> tag) {
add(tag, 0);
resetCache();
}
@Override
public void clear(ItemConvertible item) {
itemCookTimes.removeInt(item);
resetCache();
}
@Override
public void clear(Tag<Item> tag) {
tagCookTimes.removeInt(tag);
resetCache();
}
public void apply(Map<Item, Integer> map) {
@ -116,4 +141,8 @@ public class FuelRegistryImpl implements FuelRegistry {
return tag.toString();
}
public void resetCache() {
fuelTimeCache = null;
}
}

View file

@ -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<Map<Item, Integer>> 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<Item, Integer> canUseAsFuelRedirect() {
return FuelRegistryImpl.INSTANCE.getFuelTimes();
}
@Redirect(method = "getFuelTime", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/AbstractFurnaceBlockEntity;createFuelTimeMap()Ljava/util/Map;"))
private Map<Item, Integer> getFuelTimeRedirect() {
return FuelRegistryImpl.INSTANCE.getFuelTimes();
}
}

View file

@ -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();
}
}

View file

@ -6,6 +6,9 @@
"MixinAbstractFurnaceBlockEntity",
"MixinFireBlock"
],
"client": [
"client.MixinClientPlayNetworkHandler"
],
"injectors": {
"defaultRequire": 1
}

View file

@ -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.",