aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman / Linnea Gräf <roman.graef@gmail.com>2023-05-31 13:04:41 +0200
committerGitHub <noreply@github.com>2023-05-31 13:04:41 +0200
commitf4a9e4011b09be043ec086abd365d0e8c443bbec (patch)
tree763a8dc14d8b1e4a4af59f5f649a465a3c721c37
parent3740ac08399d4c16802729511b5032e8f8ac6e14 (diff)
downloadNotEnoughUpdates-f4a9e4011b09be043ec086abd365d0e8c443bbec.tar.gz
NotEnoughUpdates-f4a9e4011b09be043ec086abd365d0e8c443bbec.tar.bz2
NotEnoughUpdates-f4a9e4011b09be043ec086abd365d0e8c443bbec.zip
Add NPC Sell price to tooltip (#702)
-rw-r--r--build.gradle.kts5
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java47
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java9
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java6
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/util/hypixelapi/HypixelItemAPI.kt58
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/util/kotlin/KotlinTypeAdapterFactory.kt128
8 files changed, 230 insertions, 27 deletions
diff --git a/build.gradle.kts b/build.gradle.kts
index ec99fd5e..9523c739 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -30,8 +30,8 @@ plugins {
id("com.github.johnrengelman.shadow") version "7.1.2"
id("io.github.juuxel.loom-quiltflower") version "1.7.3"
`maven-publish`
- kotlin("jvm") version "1.8.0"
- id("com.google.devtools.ksp") version "1.8.0-1.0.8"
+ kotlin("jvm") version "1.8.21"
+ id("com.google.devtools.ksp") version "1.8.21-1.0.11"
}
@@ -133,6 +133,7 @@ dependencies {
// Please keep this version in sync with KotlinLoadingTweaker
implementation(enforcedPlatform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
kotlinDependencies(kotlin("stdlib"))
+ kotlinDependencies(kotlin("reflect"))
ksp("dev.zacsweers.autoservice:auto-service-ksp:1.0.0")
implementation("com.google.auto.service:auto-service-annotations:1.0.1")
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java
index 7d408e0f..6e7f83e4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java
@@ -26,6 +26,7 @@ import io.github.moulberry.notenoughupdates.auction.APIManager;
import io.github.moulberry.notenoughupdates.core.config.KeybindHelper;
import io.github.moulberry.notenoughupdates.util.Constants;
import io.github.moulberry.notenoughupdates.util.Utils;
+import io.github.moulberry.notenoughupdates.util.hypixelapi.HypixelItemAPI;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import org.lwjgl.input.Keyboard;
@@ -123,22 +124,18 @@ public class ItemPriceInformation {
}
}
+ int shiftStackMultiplier = useStackSize && stack.stackSize > 1 ? stack.stackSize : stack.getItem().getItemStackLimit(stack);
+ if (stack.getTagCompound() != null && stack.getTagCompound().hasKey(STACKSIZE_OVERRIDE)) {
+ shiftStackMultiplier = stack.getTagCompound().getInteger(STACKSIZE_OVERRIDE);
+ }
+ int stackMultiplier = 1;
+ boolean shiftPressed = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT);
+ if (shiftPressed) {
+ stackMultiplier = shiftStackMultiplier;
+ }
+ boolean added = false;
if (bazaarItem) {
List<Integer> lines = NotEnoughUpdates.INSTANCE.config.tooltipTweaks.priceInfoBaz;
-
- boolean added = false;
-
- boolean shiftPressed = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT);
-
- int stackMultiplier = 1;
- int shiftStackMultiplier = useStackSize && stack.stackSize > 1 ? stack.stackSize : 64;
- if (stack.getTagCompound() != null && stack.getTagCompound().hasKey(STACKSIZE_OVERRIDE)) {
- shiftStackMultiplier = stack.getTagCompound().getInteger(STACKSIZE_OVERRIDE);
- }
- if (shiftPressed) {
- stackMultiplier = shiftStackMultiplier;
- }
-
//values = {"", "Buy", "Sell", "Buy (Insta)", "Sell (Insta)", "Raw Craft Cost", "Instabuys (Hourly)", "Instasells (Hourly)", "Instabuys (Daily)", "Instasells (Daily)", "Instabuys (Weekly)", "Instasells (Weekly)"}
for (int lineId : lines) {
switch (lineId) {
@@ -288,7 +285,6 @@ public class ItemPriceInformation {
} else if (auctionItem && !auctionInfoErrored) {
List<Integer> lines = NotEnoughUpdates.INSTANCE.config.tooltipTweaks.priceInfoAuc;
- boolean added = false;
for (int lineId : lines) {
switch (lineId) {
@@ -444,14 +440,13 @@ public class ItemPriceInformation {
}
} else if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.rawCraft && craftCost != null && craftCost.fromRecipe) {
-
- if (craftCost.craftCost == 0) return;
- double cost = craftCost.craftCost;
- int shiftStackMultiplier = useStackSize && stack.stackSize > 1 ? stack.stackSize : 64;
- if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) cost = cost * shiftStackMultiplier;
- tooltip.add("");
- tooltip.add(formatPrice("Raw Craft Cost: ", cost));
-
+ if (craftCost.craftCost != 0) {
+ double cost = craftCost.craftCost;
+ cost = cost * stackMultiplier;
+ added = true;
+ tooltip.add("");
+ tooltip.add(formatPrice("Raw Craft Cost: ", cost));
+ }
} else if (auctionInfoErrored && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
String message = EnumChatFormatting.RED.toString() + EnumChatFormatting.BOLD + "[NEU] API is down";
if (auctionableItems != null && !auctionableItems.isEmpty()) {
@@ -462,6 +457,12 @@ public class ItemPriceInformation {
tooltip.add(message + " and no item data is cached");
}
}
+ Double npcSellPrice = HypixelItemAPI.getNPCSellPrice(internalname);
+ if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.npcSellPrice && npcSellPrice != null) {
+ if (!added)
+ tooltip.add("");
+ tooltip.add(formatPrice("NPC Sell Price: ", npcSellPrice * stackMultiplier));
+ }
}
private static String formatPrice(String label, double price) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
index 794df0f4..c6a0c04f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
@@ -54,6 +54,7 @@ import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
import io.github.moulberry.notenoughupdates.recipes.RecipeGenerator;
import io.github.moulberry.notenoughupdates.util.Utils;
import io.github.moulberry.notenoughupdates.util.brigadier.BrigadierRoot;
+import io.github.moulberry.notenoughupdates.util.hypixelapi.HypixelItemAPI;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiScreen;
@@ -301,6 +302,7 @@ public class NotEnoughUpdates {
manager.loadItemInformation();
overlay = new NEUOverlay(manager);
profileViewer = new ProfileViewer(manager);
+ HypixelItemAPI.INSTANCE.loadItemData();
for (KeyBinding kb : manager.keybinds) {
ClientRegistry.registerKeyBinding(kb);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java b/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java
index bf4e746f..720dd540 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java
@@ -82,7 +82,7 @@ public class KotlinLoadingTweaker implements ITweaker {
* Full version format: [1, 7, 20] (1.7.20)
* RC version format: [1, 7, 20, 1] (1.7.20-rc1)
*/
- public static final int[] BUNDLED_KOTLIN_VERSION = new int[]{1, 8, 0};
+ public static final int[] BUNDLED_KOTLIN_VERSION = new int[]{1, 8, 21};
@Override
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java
index cd6ecb26..2957015b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java
@@ -95,6 +95,15 @@ public class TooltipTweaks {
@Expose
@ConfigOption(
+ name = "Show NPC Sell price on Items",
+ desc = "Display for how much items can be sold to NPC Shops"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean npcSellPrice = false;
+
+ @Expose
+ @ConfigOption(
name = "Use Short Number Format",
desc = "Use Short Numbers (5.1m) instead of 5,130,302"
)
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
index 0cda91fd..4cb1abc8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
@@ -20,9 +20,11 @@
package io.github.moulberry.notenoughupdates.util;
import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.events.ProfileDataLoadedEvent;
+import io.github.moulberry.notenoughupdates.util.kotlin.KotlinTypeAdapterFactory;
import net.minecraft.client.Minecraft;
import net.minecraft.util.EnumChatFormatting;
import org.apache.commons.io.IOUtils;
@@ -63,7 +65,9 @@ import java.util.concurrent.Executors;
import java.util.zip.GZIPInputStream;
public class ApiUtil {
- private static final Gson gson = new Gson();
+ private static final Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(KotlinTypeAdapterFactory.INSTANCE)
+ .create();
private static final Comparator<NameValuePair> nameValuePairComparator = Comparator
.comparing(NameValuePair::getName)
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/hypixelapi/HypixelItemAPI.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/hypixelapi/HypixelItemAPI.kt
new file mode 100644
index 00000000..acb2b53f
--- /dev/null
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/hypixelapi/HypixelItemAPI.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util.hypixelapi
+
+import com.google.gson.JsonElement
+import com.google.gson.annotations.SerializedName
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates
+import io.github.moulberry.notenoughupdates.util.kotlin.ExtraData
+import io.github.moulberry.notenoughupdates.util.kotlin.KSerializable
+import io.github.moulberry.notenoughupdates.util.kotlin.KSerializedName
+
+object HypixelItemAPI {
+ @KSerializable
+ data class ApiResponse(
+ val items: List<ApiItem>,
+ )
+
+ @KSerializable
+ data class ApiItem(
+ val id: String,
+ val name: String,
+ @param:KSerializedName("npc_sell_price")
+ val npcSellPrice: Double? = null,
+ @param:ExtraData
+ val extraData: Map<String, JsonElement>,
+ )
+
+ var itemData: Map<String, ApiItem> = mapOf()
+ private set
+
+ @JvmStatic
+ fun getNPCSellPrice(itemId: String) = itemData[itemId]?.npcSellPrice
+
+ fun loadItemData() {
+ NotEnoughUpdates.INSTANCE.manager.apiUtils.newAnonymousHypixelApiRequest("resources/skyblock/items")
+ .requestJson(ApiResponse::class.java)
+ .thenAccept {
+ itemData = it.items.associateBy { it.id }
+ }
+ }
+}
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/kotlin/KotlinTypeAdapterFactory.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/kotlin/KotlinTypeAdapterFactory.kt
new file mode 100644
index 00000000..e531364a
--- /dev/null
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/kotlin/KotlinTypeAdapterFactory.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2023 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util.kotlin
+
+import com.google.gson.*
+import com.google.gson.annotations.SerializedName
+import com.google.gson.reflect.TypeToken
+import com.google.gson.stream.JsonReader
+import com.google.gson.stream.JsonToken
+import com.google.gson.stream.JsonWriter
+import kotlin.reflect.*
+import kotlin.reflect.full.findAnnotation
+import kotlin.reflect.full.isSubtypeOf
+import kotlin.reflect.full.memberProperties
+import kotlin.reflect.full.primaryConstructor
+import com.google.gson.internal.`$Gson$Types` as InternalGsonTypes
+
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.CLASS)
+annotation class KSerializable
+
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.VALUE_PARAMETER)
+annotation class ExtraData
+
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.VALUE_PARAMETER)
+annotation class KSerializedName(val serialName: String)
+
+object KotlinTypeAdapterFactory : TypeAdapterFactory {
+
+ internal data class ParameterInfo(
+ val param: KParameter,
+ val adapter: TypeAdapter<Any?>,
+ val name: String,
+ val field: KProperty1<Any, Any?>
+ )
+
+ @OptIn(ExperimentalStdlibApi::class)
+ override fun <T : Any> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
+ val kotlinClass = type.rawType.kotlin as KClass<T>
+ if (kotlinClass.findAnnotation<KSerializable>() == null) return null
+ if (!kotlinClass.isData) return null
+ val primaryConstructor = kotlinClass.primaryConstructor ?: return null
+ val params = primaryConstructor.parameters.filter { it.findAnnotation<ExtraData>() == null }
+ val extraDataParam = primaryConstructor.parameters
+ .find { it.findAnnotation<ExtraData>() != null && typeOf<MutableMap<String, JsonElement>>().isSubtypeOf(it.type) }
+ ?.let { param ->
+ param to kotlinClass.memberProperties.find { it.name == param.name && it.returnType.isSubtypeOf(typeOf<Map<String, JsonElement>>()) } as KProperty1<Any, Map<String, JsonElement>>
+ }
+ val parameterInfos = params.map { param ->
+ ParameterInfo(
+ param,
+ gson.getAdapter(
+ TypeToken.get(InternalGsonTypes.resolve(type.type, type.rawType, param.type.javaType))
+ ) as TypeAdapter<Any?>,
+ param.findAnnotation<KSerializedName>()?.serialName ?: param.name!!,
+ kotlinClass.memberProperties.find { it.name == param.name }!! as KProperty1<Any, Any?>
+ )
+ }.associateBy { it.name }
+ val jsonElementAdapter = gson.getAdapter(JsonElement::class.java)
+
+ return object : TypeAdapter<T>() {
+ override fun write(out: JsonWriter, value: T?) {
+ if (value == null) {
+ out.nullValue()
+ return
+ }
+ out.beginObject()
+ parameterInfos.forEach { (name, paramInfo) ->
+ out.name(name)
+ paramInfo.adapter.write(out, paramInfo.field.get(value))
+ }
+ if (extraDataParam != null) {
+ val extraData = extraDataParam.second.get(value)
+ extraData.forEach { (extraName, extraValue) ->
+ out.name(extraName)
+ jsonElementAdapter.write(out, extraValue)
+ }
+ }
+ out.endObject()
+ }
+
+ override fun read(reader: JsonReader): T? {
+ if (reader.peek() == JsonToken.NULL) {
+ reader.nextNull()
+ return null
+ }
+ reader.beginObject()
+ val args = mutableMapOf<KParameter, Any?>()
+ val extraData = mutableMapOf<String, JsonElement>()
+ while (reader.peek() != JsonToken.END_OBJECT) {
+ val name = reader.nextName()
+ val paramData = parameterInfos[name]
+ if (paramData == null) {
+ extraData[name] = jsonElementAdapter.read(reader)
+ continue
+ }
+ val value = paramData.adapter.read(reader)
+ args[paramData.param] = value
+ }
+ reader.endObject()
+ if (extraDataParam != null) {
+ args[extraDataParam.first] = extraData
+ }
+ return primaryConstructor.callBy(args)
+ }
+ }
+ }
+}
+