Improve Async Locator backport for 1.16

This commit is contained in:
embeddedt 2023-09-22 22:04:55 -04:00
parent 5c21a98c7f
commit 7b1d9ff8bb
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
4 changed files with 127 additions and 7 deletions

View File

@ -0,0 +1,26 @@
package org.embeddedt.modernfix.forge.mixin.perf.async_locator;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.loot.functions.SetNameFunction;
import org.embeddedt.modernfix.forge.structure.logic.CommonLogic;
import org.embeddedt.modernfix.forge.structure.logic.ExplorationMapFunctionLogic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(SetNameFunction.class)
public class SetNameFunctionMixin {
@Redirect(
method = "run",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/item/ItemStack;setHoverName(Lnet/minecraft/network/chat/Component;)Lnet/minecraft/world/item/ItemStack;"
)
)
public ItemStack deferSetName(ItemStack stack, Component name) {
if (CommonLogic.isEmptyPendingMap(stack))
ExplorationMapFunctionLogic.cacheName(stack, name);
return stack;
}
}

View File

@ -0,0 +1,28 @@
package org.embeddedt.modernfix.forge.mixin.perf.async_locator;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import org.embeddedt.modernfix.forge.structure.logic.CommonLogic;
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(Slot.class)
public abstract class SlotMixin {
@Shadow
public abstract ItemStack getItem();
@Inject(
method = "mayPickup",
at = @At(value = "HEAD"),
cancellable = true
)
public void preventPickupOfPendingExplorationMap(Player player, CallbackInfoReturnable<Boolean> cir) {
if (CommonLogic.isEmptyPendingMap(getItem())) {
cir.setReturnValue(false);
}
}
}

View File

@ -1,6 +1,8 @@
package org.embeddedt.modernfix.forge.structure.logic;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.ByteTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.inventory.AbstractContainerMenu;
@ -15,6 +17,9 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import org.embeddedt.modernfix.forge.mixin.perf.async_locator.MapItemAccess;
public class CommonLogic {
private static final String MAP_HOVER_NAME_KEY = "menu.working";
private static final String KEY_LOCATING = "asynclocator.locating";
private CommonLogic() {}
/**
@ -24,10 +29,23 @@ public class CommonLogic {
*/
public static ItemStack createEmptyMap() {
ItemStack stack = new ItemStack(Items.FILLED_MAP);
stack.setHoverName(new TranslatableComponent("asynclocator.map.locating"));
stack.setHoverName(new TranslatableComponent(MAP_HOVER_NAME_KEY));
stack.addTagElement(KEY_LOCATING, ByteTag.ONE);
return stack;
}
/**
* Returns true if the stack is an empty FILLED_MAP item with the hover tooltip name stating that it's locating a
* feature.
*
* @param stack The stack to check.
* @return True if the stack is an empty FILLED_MAP awaiting to be populated with location data.
*/
@SuppressWarnings("DataFlowIssue")
public static boolean isEmptyPendingMap(ItemStack stack) {
return stack.getItem() == Items.FILLED_MAP && stack.hasTag() && stack.getTag().contains(KEY_LOCATING);
}
/**
* Updates the map stack with all the given data.
*
@ -44,7 +62,7 @@ public class CommonLogic {
int scale,
MapDecoration.Type destinationType
) {
updateMap(mapStack, level, pos, scale, destinationType, null);
updateMap(mapStack, level, pos, scale, destinationType, (Component)null);
}
/**
@ -64,6 +82,27 @@ public class CommonLogic {
int scale,
MapDecoration.Type destinationType,
String displayName
) {
updateMap(mapStack, level, pos, scale, destinationType, new TranslatableComponent(displayName));
}
/**
* Updates the map stack with all the given data.
*
* @param mapStack The map ItemStack to update
* @param level The ServerLevel
* @param pos The feature position
* @param scale The map scale
* @param destinationType The map feature type
* @param displayName The hover tooltip display name of the ItemStack
*/
public static void updateMap(
ItemStack mapStack,
ServerLevel level,
BlockPos pos,
int scale,
MapDecoration.Type destinationType,
Component displayName
) {
MapItemAccess.callCreateAndStoreSavedData(
mapStack, level, pos.getX(), pos.getZ(), scale, true, true, level.dimension()
@ -71,7 +110,8 @@ public class CommonLogic {
MapItem.renderBiomePreviewMap(level, mapStack);
MapItemSavedData.addTargetDecoration(mapStack, pos, "+", destinationType);
if (displayName != null)
mapStack.setHoverName(new TranslatableComponent(displayName));
mapStack.setHoverName(displayName);
mapStack.removeTagKey(KEY_LOCATING);
}
/**

View File

@ -1,7 +1,11 @@
package org.embeddedt.modernfix.forge.structure.logic;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableSet;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
@ -15,13 +19,29 @@ import net.minecraftforge.items.IItemHandlerModifiable;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.forge.structure.AsyncLocator;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
// TODO: Need to test this
public class ExplorationMapFunctionLogic {
// I'd like to think that structure locating shouldn't take *this* long
private static final Cache<ItemStack, Component> MAP_NAME_CACHE =
CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build();
private static final int MAX_STACK_SIZE = 64;
private ExplorationMapFunctionLogic() {}
public static void cacheName(ItemStack stack, Component name) {
MAP_NAME_CACHE.put(stack, name);
}
public static Component getCachedName(ItemStack stack) {
Component name = MAP_NAME_CACHE.getIfPresent(stack);
MAP_NAME_CACHE.invalidate(stack);
return name;
}
public static void invalidateMap(ItemStack mapStack, ServerLevel level, BlockPos pos) {
handleUpdateMapInChest(mapStack, level, pos, (handler, slot) -> {
if (handler instanceof IItemHandlerModifiable) {
@ -39,9 +59,10 @@ public class ExplorationMapFunctionLogic {
BlockPos pos,
int scale,
MapDecoration.Type destinationType,
BlockPos invPos
BlockPos invPos,
Component displayName
) {
CommonLogic.updateMap(mapStack, level, pos, scale, destinationType);
CommonLogic.updateMap(mapStack, level, pos, scale, destinationType, displayName);
// Shouldn't need to set the stack in its slot again, as we're modifying the same instance
handleUpdateMapInChest(mapStack, level, invPos, (handler, slot) -> {});
}
@ -84,12 +105,17 @@ public class ExplorationMapFunctionLogic {
BlockPos pos,
int scale,
MapDecoration.Type destinationType,
StructureFeature<?> destination,
BlockPos invPos
) {
if (pos == null) {
invalidateMap(mapStack, level, invPos);
} else {
updateMap(mapStack, level, pos, scale, destinationType, invPos);
Component displayName = getCachedName(mapStack);
if(displayName == null) {
displayName = new TranslatableComponent("filled_map." + destination.getFeatureName().toLowerCase(Locale.ROOT));
}
updateMap(mapStack, level, pos, scale, destinationType, invPos, displayName);
}
}
@ -104,7 +130,7 @@ public class ExplorationMapFunctionLogic {
) {
ItemStack mapStack = CommonLogic.createEmptyMap();
AsyncLocator.locateLevel(level, ImmutableSet.of(destination), blockPos, searchRadius, skipKnownStructures)
.thenOnServerThread(pos -> handleLocationFound(mapStack, level, pos, scale, destinationType, blockPos));
.thenOnServerThread(pos -> handleLocationFound(mapStack, level, pos, scale, destinationType, destination, blockPos));
return mapStack;
}
}