diff options
| author | Rime <81419447+Emirlol@users.noreply.github.com> | 2024-05-11 14:08:59 +0300 | 
|---|---|---|
| committer | Rime <81419447+Emirlol@users.noreply.github.com> | 2024-05-23 13:31:48 +0300 | 
| commit | e2f18c84ce2de2da228ff88b6b67fa5d46945255 (patch) | |
| tree | 02625a4bbf8ebb72a19f9f98d43f68603f1ce4e6 /src/main/java | |
| parent | 05a18be31a137148bcd446654c550eb2d713990c (diff) | |
| download | Skyblocker-e2f18c84ce2de2da228ff88b6b67fa5d46945255.tar.gz Skyblocker-e2f18c84ce2de2da228ff88b6b67fa5d46945255.tar.bz2 Skyblocker-e2f18c84ce2de2da228ff88b6b67fa5d46945255.zip | |
Add support for unemployed rabbits
- Refactored ItemUtils.getHeadTexture to use the property iterator instead of streams and return Optional<String> rather than empty string to make the results clear and easier to work with.
- Refactored regex matching logic in ChocolateFactorySolver.getCPSIncreaseFactor to a separate function
Diffstat (limited to 'src/main/java')
6 files changed, 68 insertions, 65 deletions
| diff --git a/src/main/java/de/hysky/skyblocker/debug/Debug.java b/src/main/java/de/hysky/skyblocker/debug/Debug.java index d9ac668c..038e7a5a 100644 --- a/src/main/java/de/hysky/skyblocker/debug/Debug.java +++ b/src/main/java/de/hysky/skyblocker/debug/Debug.java @@ -83,9 +83,9 @@ public class Debug {  						Iterable<ItemStack> equippedItems = armorStand.getEquippedItems();  						for (ItemStack stack : equippedItems) { -							String texture = ItemUtils.getHeadTexture(stack); - -							if (!texture.isEmpty()) context.getSource().sendFeedback(Text.of(texture)); +							ItemUtils.getHeadTexture(stack).ifPresent(texture -> { +								context.getSource().sendFeedback(Text.of(texture)); +							});  						}  					} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java index a59a5147..94c2b209 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java @@ -1,23 +1,15 @@  package de.hysky.skyblocker.skyblock.chocolatefactory;  import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.skyblock.experiment.ExperimentSolver; +import de.hysky.skyblocker.utils.ItemUtils;  import de.hysky.skyblocker.utils.render.gui.ColorHighlight;  import de.hysky.skyblocker.utils.render.gui.ContainerSolver;  import it.unimi.dsi.fastutil.ints.*; -import net.fabricmc.loader.impl.lib.sat4j.minisat.core.Solver; -import net.minecraft.client.MinecraftClient;  import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.LoreComponent;  import net.minecraft.item.ItemStack;  import net.minecraft.item.Items; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtList;  import net.minecraft.text.Text; -import java.awt.*;  import java.util.*;  import java.util.List;  import java.util.regex.Matcher; @@ -27,6 +19,7 @@ import java.util.stream.Collectors;  public class ChocolateFactorySolver extends ContainerSolver {  	private static final Pattern CPS_PATTERN = Pattern.compile("\\+([\\d,]+) Chocolate per second");  	private static final Pattern COST_PATTERN = Pattern.compile("Cost ([\\d,]+) Chocolate"); +	private static final Pattern HIRE_PATTERN = Pattern.compile("(HIRE|PROMOTE) ➜ \\[\\d+] \\S+ *");  	public ChocolateFactorySolver() {  		super("^Chocolate Factory$"); @@ -42,7 +35,6 @@ public class ChocolateFactorySolver extends ContainerSolver {  		markHighlightsDirty(); //Recalculate highlights when the screen is opened, which happens when upgrading rabbits  	} -	//Todo: Handle unemployed rabbits as well. They have a different lore format.  	@Override  	protected List<ColorHighlight> getColors(String[] groups, Int2ObjectMap<ItemStack> slots) {  		Int2DoubleMap cpsIncreaseFactors = new Int2DoubleLinkedOpenHashMap(5); //There are only 5 rabbits on the screen. @@ -51,7 +43,7 @@ public class ChocolateFactorySolver extends ContainerSolver {  			ItemStack item = entry.getValue();  			if (item.getItem() != Items.PLAYER_HEAD || item.isEmpty()) continue; -			String lore = getLore(item); +			String lore = getConcattedLore(item);  			if (lore.isBlank()) continue;  			OptionalDouble cpsIncreaseFactor = getCPSIncreaseFactor(lore); @@ -63,15 +55,13 @@ public class ChocolateFactorySolver extends ContainerSolver {  		return List.of(ColorHighlight.green(bestSlot.get().getIntKey()));  	} -	private String getLore(ItemStack item) { -		LoreComponent lore = item.get(DataComponentTypes.LORE); -		if (lore == null || lore.lines().isEmpty()) return ""; -		return lore.lines() -		           .stream() -		           .map(Text::getString) -		           .collect(Collectors.joining(" ")); //Join all lore lines into one string for ease of regexing -//					The space is so that the regex pattern still matches even if the word is split into 2 lines, -//					as normally the line end and line start contain no spaces and would not match the pattern when concatenated +	private String getConcattedLore(ItemStack item) { +		return ItemUtils.getLore(item) +		                .stream() +		                .map(Text::getString) +		                .collect(Collectors.joining(" ")); //Join all lore lines into one string for ease of regexing +//					     The space is so that the regex pattern still matches even if the word is split into 2 lines, +//					     as normally the line end and the line start contain no spaces and would not match the pattern when concatenated  	}  	/** @@ -82,15 +72,42 @@ public class ChocolateFactorySolver extends ContainerSolver {  	 * @return The CPS increase factor of the item, or an empty optional if it couldn't be found  	 */  	private OptionalDouble getCPSIncreaseFactor(String lore) { -		Matcher cpsMatcher = CPS_PATTERN.matcher(lore); -		if (!cpsMatcher.find()) return OptionalDouble.empty(); -		int currentCps = Integer.parseInt(cpsMatcher.group(1).replace(",", "")); -		if (!cpsMatcher.find()) return OptionalDouble.empty(); //If there is no second match, we can't get the CPS increase -		int nextCps = Integer.parseInt(cpsMatcher.group(1).replace(",", "")); - -		Matcher costMatcher = COST_PATTERN.matcher(lore); -		if (!costMatcher.find(cpsMatcher.end())) return OptionalDouble.empty(); //Cost is always at the end of the string, so we can start check from the end of the last match -		int cost = Integer.parseInt(costMatcher.group(1).replace(",", "")); -		return OptionalDouble.of((nextCps - currentCps) / (double) cost); +		Matcher hireMatcher = HIRE_PATTERN.matcher(lore); +		if (!hireMatcher.find()) return OptionalDouble.empty(); //Not a hireable/promotable rabbit. Could be a locked or maxed rabbit. + +		switch (hireMatcher.group(1)) { +			case "HIRE" -> { +				Matcher cpsMatcher = CPS_PATTERN.matcher(lore); +				OptionalInt cps = getValueFromMatcher(cpsMatcher, hireMatcher.end()); //Cps line is right after the hire line +				if (cps.isEmpty()) return OptionalDouble.empty(); + +				Matcher costMatcher = COST_PATTERN.matcher(lore); +				OptionalInt cost = getValueFromMatcher(costMatcher, cpsMatcher.end()); //Cost comes after the cps line +				if (cost.isEmpty()) return OptionalDouble.empty(); +				return OptionalDouble.of(cps.getAsInt() / (double) cost.getAsInt()); +			} +			case "PROMOTE" -> { +				Matcher cpsMatcher = CPS_PATTERN.matcher(lore); +				OptionalInt currentCps = getValueFromMatcher(cpsMatcher); //Current cps is before the hire line +				if (currentCps.isEmpty()) return OptionalDouble.empty(); +				OptionalInt nextCps = getValueFromMatcher(cpsMatcher, hireMatcher.end()); //Next cps is right after the hire line +				if (nextCps.isEmpty()) return OptionalDouble.empty(); + +				Matcher costMatcher = COST_PATTERN.matcher(lore); +				OptionalInt cost = getValueFromMatcher(costMatcher, cpsMatcher.end()); //Cost comes after the cps line +				if (cost.isEmpty()) return OptionalDouble.empty(); +				return OptionalDouble.of((nextCps.getAsInt() - currentCps.getAsInt()) / (double) cost.getAsInt()); +			} +			default -> { return OptionalDouble.empty(); } +		} +	} + +	private OptionalInt getValueFromMatcher(Matcher matcher) { +		return getValueFromMatcher(matcher, matcher.hasMatch() ? matcher.end() : 0); +	} + +	private OptionalInt getValueFromMatcher(Matcher matcher, int startingIndex) { +		if (!matcher.find(startingIndex)) return OptionalInt.empty(); +		return OptionalInt.of(Integer.parseInt(matcher.group(1).replace(",", "")));  	}  } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java index 7f8e9879..ee1d4aa7 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java @@ -3,6 +3,7 @@ package de.hysky.skyblocker.skyblock.chocolatefactory;  import de.hysky.skyblocker.config.SkyblockerConfigManager;  import de.hysky.skyblocker.utils.ColorUtils;  import de.hysky.skyblocker.utils.Constants; +import de.hysky.skyblocker.utils.ItemUtils;  import de.hysky.skyblocker.utils.waypoint.Waypoint;  import it.unimi.dsi.fastutil.objects.ObjectImmutableList;  import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; @@ -10,11 +11,9 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;  import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;  import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;  import net.minecraft.client.MinecraftClient; -import net.minecraft.component.DataComponentTypes;  import net.minecraft.entity.Entity;  import net.minecraft.entity.decoration.ArmorStandEntity;  import net.minecraft.item.ItemStack; -import net.minecraft.item.Items;  import net.minecraft.text.Text;  import org.apache.commons.lang3.mutable.MutableObject;  import org.slf4j.Logger; @@ -46,26 +45,14 @@ public class EggFinder {  		if (BREAKFAST.egg.getValue() != null && DINNER.egg.getValue() != null && LUNCH.egg.getValue() != null) return; //Don't check for eggs if we already found all of them  		if (!(entity instanceof ArmorStandEntity armorStand) || armorStand.hasCustomName() || !armorStand.isInvisible() || !armorStand.shouldHideBasePlate()) return;  		for (ItemStack itemStack : armorStand.getArmorItems()) { -			try { -				if (!itemStack.isEmpty() || itemStack.getItem() == Items.PLAYER_HEAD) { -					String texture = itemStack.getComponents() -					                          .get(DataComponentTypes.PROFILE) -					                          .properties() -					                          .get("textures") -					                          .iterator() -					                          .next() -					                          .value(); - -					for (EggType type : EggType.entries) { -						if (texture.equals(type.texture)) { -							handleFoundEgg(armorStand, type); -							return; -						} +			ItemUtils.getHeadTexture(itemStack).ifPresent(texture -> { +				for (EggType type : EggType.entries) { +					if (texture.equals(type.texture)) { +						handleFoundEgg(armorStand, type); +						return;  					}  				} -			} catch (Exception e) { -				//Ignored. This simply exists to make the code cleaner without a bunch of if statements to check the existence of each key. -			} +			});  		}  	} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java index d6f9410b..df9a32c6 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java @@ -104,7 +104,7 @@ public class MobGlow {  			// eb07594e2df273921a77c101d0bfdfa1115abed5b9b2029eb496ceba9bdbb4b3 is texture id for the nukekubi head,  			// compare against it to exclusively find armorstands that are nukekubi heads  			// get the texture of the nukekubi head item itself and compare it -			String texture = ItemUtils.getHeadTexture(armorItem); +			String texture = ItemUtils.getHeadTexture(armorItem).orElse("");  			return texture.contains("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWIwNzU5NGUyZGYyNzM5MjFhNzdjMTAxZDBiZmRmYTExMTVhYmVkNWI5YjIwMjllYjQ5NmNlYmE5YmRiYjRiMyJ9fX0=");  		} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java index 682933f4..0f349a4f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java @@ -94,9 +94,7 @@ public class VisitorHelper {      }      private static @Nullable String getTextureOrNull(ItemStack stack) { -        String texture = ItemUtils.getHeadTexture(stack); - -        return texture.isEmpty() ? null : texture; +        return ItemUtils.getHeadTexture(stack).orElse(null);      }      private static void processLore(String visitorName, @Nullable String visitorTexture, List<Text> loreList) { diff --git a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java index 1aa77080..6b850b3b 100644 --- a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java +++ b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java @@ -33,6 +33,7 @@ import java.time.Instant;  import java.time.ZoneId;  import java.time.format.DateTimeFormatter;  import java.time.temporal.TemporalAccessor; +import java.util.Iterator;  import java.util.List;  import java.util.Locale;  import java.util.Optional; @@ -202,16 +203,16 @@ public class ItemUtils {          return Codecs.GAME_PROFILE_PROPERTY_MAP.parse(JsonOps.INSTANCE, JsonParser.parseString("[{\"name\":\"textures\",\"value\":\"" + textureValue + "\"}]")).getOrThrow();      } -    public static String getHeadTexture(ItemStack stack) { -        if (!stack.isOf(Items.PLAYER_HEAD) || !stack.contains(DataComponentTypes.PROFILE)) return ""; +    public static Optional<String> getHeadTexture(ItemStack stack) { +        if (!stack.isOf(Items.PLAYER_HEAD) || !stack.contains(DataComponentTypes.PROFILE)) return Optional.empty(); -        ProfileComponent profile = stack.get(DataComponentTypes.PROFILE); -        String texture = profile.properties().get("textures").stream() -                .map(Property::value) -                .findFirst() -                .orElse(""); +        Iterator<Property> iterator = stack.get(DataComponentTypes.PROFILE) +                                           .properties() +                                           .get("textures") +                                           .iterator(); -        return texture; +        if (!iterator.hasNext()) return Optional.empty(); +        return Optional.of(iterator.next().value());      }      public static ItemStack getSkyblockerStack() { | 
