diff options
Diffstat (limited to 'src/main/java/io')
25 files changed, 1374 insertions, 262 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index 6572431b..c283464e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -1,14 +1,24 @@ package io.github.moulberry.notenoughupdates; -import com.google.gson.*; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import io.github.moulberry.notenoughupdates.auction.APIManager; +import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent; import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe; import io.github.moulberry.notenoughupdates.miscgui.KatSitterOverlay; import io.github.moulberry.notenoughupdates.recipes.CraftingOverlay; import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe; import io.github.moulberry.notenoughupdates.recipes.Ingredient; import io.github.moulberry.notenoughupdates.recipes.NeuRecipe; -import io.github.moulberry.notenoughupdates.util.*; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.HotmInformation; +import io.github.moulberry.notenoughupdates.util.HypixelApi; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.settings.KeyBinding; import net.minecraft.init.Blocks; @@ -16,24 +26,49 @@ import net.minecraft.init.Items; import net.minecraft.inventory.ContainerChest; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.*; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.JsonToNBT; +import net.minecraft.nbt.NBTException; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.common.ProgressManager; import org.apache.commons.io.FileUtils; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.Display; import javax.net.ssl.HttpsURLConnection; -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import java.io.*; +import javax.swing.*; +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; -import java.util.*; +import java.util.ArrayList; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.NavigableMap; +import java.util.Optional; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -44,6 +79,7 @@ public class NEUManager { public final APIManager auctionManager; private final TreeMap<String, JsonObject> itemMap = new TreeMap<>(); + private boolean hasBeenLoadedBefore = false; private final TreeMap<String, HashMap<String, List<Integer>>> titleWordMap = new TreeMap<>(); private final TreeMap<String, HashMap<String, List<Integer>>> loreWordMap = new TreeMap<>(); @@ -73,8 +109,6 @@ public class NEUManager { private final Map<String, ItemStack> itemstackCache = new HashMap<>(); - private final ExecutorService repoLoaderES = Executors.newSingleThreadExecutor(); - private static String GIT_COMMITS_URL; // TODO: private final Map<String, NeuItem> @@ -160,186 +194,102 @@ public class NEUManager { } } - /** - * Called when the game is first loaded. Compares the local repository to the github repository and handles the - * downloading of new/updated files. This then calls the "loadItem" method for every item in the local repository. - */ - public void loadItemInformation() { - /*File repoFile = new File(configLocation, "repo2"); - repoFile.mkdirs(); - - try(Git git = Git.init().setDirectory(repoFile).call()) { - StoredConfig config = git.getRepository().getConfig(); - config.setString("branch", "master", "merge", "refs/heads/master"); - config.setString("branch", "master", "remote", "origin"); - config.setString("remote", "origin", "fetch", "+refs/heads/*:refs/remotes/origin/*"); - config.setString("remote", "origin", "url", "https://github.com/Moulberry/NotEnoughUpdates-REPO.git"); - config.save(); - - git.remoteAdd().setName("origin").setUri(new URIish("https://github.com/Moulberry/NotEnoughUpdates-REPO.git")).call(); - PullResult result = git.pull().setRemote("origin").setTimeout(30000).call(); - System.out.println("successful pull: " + result.isSuccessful()); - } catch(Exception e) { - e.printStackTrace(); - }*/ - - /*if(repoFile.mkdirs()) { - try { - Git.cloneRepository() - .setURI("https://github.com/Moulberry/NotEnoughUpdates-REPO.git") - .setDirectory(repoFile) - .call(); - } catch(Exception e) { - e.printStackTrace(); - } - } else { - - }*/ - - repoLoaderES.submit(() -> { + public CompletableFuture<Boolean> fetchRepository() { + return CompletableFuture.<Boolean>supplyAsync(() -> { JDialog dialog = null; try { - if (NotEnoughUpdates.INSTANCE.config.hidden.autoupdate) { - JOptionPane pane = new JOptionPane("Getting items to download from remote repository."); - dialog = pane.createDialog("NotEnoughUpdates Remote Sync"); - dialog.setModal(false); - if (NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true); - - if (Display.isActive()) dialog.toFront(); - - JsonObject currentCommitJSON = getJsonFromFile(new File(configLocation, "currentCommit.json")); - - latestRepoCommit = null; - try (Reader inReader = new InputStreamReader(new URL(GIT_COMMITS_URL).openStream())) { - JsonObject commits = gson.fromJson(inReader, JsonObject.class); - latestRepoCommit = commits.get("sha").getAsString(); - } catch (Exception e) { - e.printStackTrace(); - } - if (latestRepoCommit == null || latestRepoCommit.isEmpty()) return; + JOptionPane pane = new JOptionPane("Getting items to download from remote repository."); + dialog = pane.createDialog("NotEnoughUpdates Remote Sync"); + dialog.setModal(false); + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true); - if (new File(configLocation, "repo").exists() && new File(configLocation, "repo/items").exists()) { - if (currentCommitJSON != null && currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) { - dialog.setVisible(false); - return; - } + if (Display.isActive()) dialog.toFront(); + + JsonObject currentCommitJSON = getJsonFromFile(new File(configLocation, "currentCommit.json")); + + latestRepoCommit = null; + try (Reader inReader = new InputStreamReader(new URL(GIT_COMMITS_URL).openStream())) { + JsonObject commits = gson.fromJson(inReader, JsonObject.class); + latestRepoCommit = commits.get("sha").getAsString(); + } catch (Exception e) { + e.printStackTrace(); + } + if (latestRepoCommit == null || latestRepoCommit.isEmpty()) return false; + + if (new File(configLocation, "repo").exists() && new File(configLocation, "repo/items").exists()) { + if (currentCommitJSON != null && currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) { + return false; } + } - if (Display.isActive()) dialog.toFront(); + if (Display.isActive()) dialog.toFront(); - Utils.recursiveDelete(repoLocation); - repoLocation.mkdirs(); + Utils.recursiveDelete(repoLocation); + repoLocation.mkdirs(); - String dlUrl = neu.config.hidden.repoURL; + String dlUrl = neu.config.hidden.repoURL; - pane.setMessage("Downloading NEU Master Archive. (DL# >20)"); - dialog.pack(); - if (NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true); - if (Display.isActive()) dialog.toFront(); + pane.setMessage("Downloading NEU Master Archive. (DL# >20)"); + dialog.pack(); + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true); + if (Display.isActive()) dialog.toFront(); - File itemsZip = new File(repoLocation, "neu-items-master.zip"); - try { - itemsZip.createNewFile(); - } catch (IOException e) { - return; - } + File itemsZip = new File(repoLocation, "neu-items-master.zip"); + try { + itemsZip.createNewFile(); + } catch (IOException e) { + return false; + } - URL url = new URL(dlUrl); - URLConnection urlConnection = url.openConnection(); - urlConnection.setConnectTimeout(15000); - urlConnection.setReadTimeout(30000); - - try (InputStream is = urlConnection.getInputStream()) { - FileUtils.copyInputStreamToFile(is, itemsZip); - } catch (IOException e) { - dialog.dispose(); - e.printStackTrace(); - System.err.println("Failed to download NEU Repo! Please report this issue to the mod creator"); - return; - } - /*try ( - BufferedInputStream inStream = new BufferedInputStream(urlConnection.getInputStream()); - FileOutputStream fileOutputStream = new FileOutputStream(itemsZip) - ) { - byte dataBuffer[] = new byte[1024]; - int bytesRead; - while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) { - fileOutputStream.write(dataBuffer, 0, bytesRead); - } - } catch (IOException e) { - dialog.dispose(); - return; - }*/ - - pane.setMessage("Unzipping NEU Master Archive."); - dialog.pack(); - //dialog.setVisible(true); - if (Display.isActive()) dialog.toFront(); - - unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), repoLocation.getAbsolutePath()); - - if (currentCommitJSON == null || !currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) { - JsonObject newCurrentCommitJSON = new JsonObject(); - newCurrentCommitJSON.addProperty("sha", latestRepoCommit); - try { - writeJson(newCurrentCommitJSON, new File(configLocation, "currentCommit.json")); - } catch (IOException ignored) { - } - } + URL url = new URL(dlUrl); + URLConnection urlConnection = url.openConnection(); + urlConnection.setConnectTimeout(15000); + urlConnection.setReadTimeout(30000); + + try (InputStream is = urlConnection.getInputStream()) { + FileUtils.copyInputStreamToFile(is, itemsZip); + } catch (IOException e) { + dialog.dispose(); + e.printStackTrace(); + System.err.println("Failed to download NEU Repo! Please report this issue to the mod creator"); + return false; } - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (dialog != null) dialog.dispose(); - } - File items = new File(repoLocation, "items"); - if (items.exists()) { - File[] itemFiles = new File(repoLocation, "items").listFiles(); - if (itemFiles != null) { - ProgressManager.ProgressBar bar = ProgressManager.push("Loading recipes", itemFiles.length); - for (File f : itemFiles) { - String internalname = f.getName().substring(0, f.getName().length() - 5); - bar.step(internalname); - synchronized (itemMap) { - if (!itemMap.containsKey(internalname)) { - loadItem(internalname); - } - } + pane.setMessage("Unzipping NEU Master Archive."); + dialog.pack(); + //dialog.setVisible(true); + if (Display.isActive()) dialog.toFront(); + + unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), repoLocation.getAbsolutePath()); + + if (currentCommitJSON == null || !currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) { + JsonObject newCurrentCommitJSON = new JsonObject(); + newCurrentCommitJSON.addProperty("sha", latestRepoCommit); + try { + writeJson(newCurrentCommitJSON, new File(configLocation, "currentCommit.json")); + } catch (IOException ignored) { } - ProgressManager.pop(bar); } - } - - try { - Constants.reload(); } catch (Exception e) { e.printStackTrace(); + } finally { + if (dialog != null) dialog.dispose(); } + return true; }); + } - File items = new File(repoLocation, "items"); - if (items.exists()) { - File[] itemFiles = new File(repoLocation, "items").listFiles(); - if (itemFiles != null) { - ProgressManager.ProgressBar bar = ProgressManager.push("Loading items", itemFiles.length); - for (File f : itemFiles) { - String internalname = f.getName().substring(0, f.getName().length() - 5); - bar.step(internalname); - synchronized (itemMap) { - if (!itemMap.containsKey(internalname)) { - loadItem(internalname); - } - } - } - ProgressManager.pop(bar); - } - } - - try { - Constants.reload(); - } catch (Exception e) { - e.printStackTrace(); + /** + * Called when the game is first loaded. Compares the local repository to the github repository and handles the + * downloading of new/updated files. This then calls the "loadItem" method for every item in the local repository. + */ + public void loadItemInformation() { + if (NotEnoughUpdates.INSTANCE.config.hidden.autoupdate) { + fetchRepository().thenAccept(i -> { + reloadRepository(); + }); + } else { + reloadRepository(); } } @@ -436,6 +386,10 @@ public class NEUManager { for (Ingredient input : recipe.getIngredients()) { usagesMap.computeIfAbsent(input.getInternalItemId(), ignored -> new HashSet<>()).add(recipe); } + for (Ingredient catalystItem : recipe.getCatalystItems()) { + recipesMap.computeIfAbsent(catalystItem.getInternalItemId(), ignored -> new HashSet<>()).add(recipe); + usagesMap.computeIfAbsent(catalystItem.getInternalItemId(), ignored -> new HashSet<>()).add(recipe); + } } public Set<NeuRecipe> getRecipesFor(String internalName) { @@ -1555,20 +1509,25 @@ public class NEUManager { } public void reloadRepository() { - File items = new File(repoLocation, "items"); - if (items.exists()) { - recipes.clear(); - recipesMap.clear(); - usagesMap.clear(); - - File[] itemFiles = new File(repoLocation, "items").listFiles(); - if (itemFiles != null) { - for (File f : itemFiles) { - String internalname = f.getName().substring(0, f.getName().length() - 5); - loadItem(internalname); + Minecraft.getMinecraft().addScheduledTask(() -> { + File items = new File(repoLocation, "items"); + if (items.exists()) { + recipes.clear(); + recipesMap.clear(); + usagesMap.clear(); + + File[] itemFiles = new File(repoLocation, "items").listFiles(); + if (itemFiles != null) { + for (File f : itemFiles) { + String internalname = f.getName().substring(0, f.getName().length() - 5); + loadItem(internalname); + } } } - } + + new RepositoryReloadEvent(repoLocation, !hasBeenLoadedBefore).post(); + hasBeenLoadedBefore = true; + }); } public ItemStack createItem(String internalname) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index d3efc06a..99dce3bb 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -87,6 +87,36 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.ascending_overlay; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.close; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.descending_overlay; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.help; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.itemPaneTabArrow; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.item_haschild; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.item_mask; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_alphabetical; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_alphabetical_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_rarity; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_rarity_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_value; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_value_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.quickcommand_background; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.rightarrow; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.rightarrow_overlay; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.settings; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_accessory; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_accessory_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_all; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_all_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_armor; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_armor_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_mob; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_mob_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_pet; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_pet_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_tool; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_tool_active; + public class NEUOverlay extends Gui { private static final ResourceLocation SUPERGEHEIMNISVERMOGEN = new ResourceLocation( "notenoughupdates:supersecretassets/bald.png"); @@ -137,7 +167,7 @@ public class NEUOverlay extends Gui { private final NEUManager manager; - private final String mobRegex = ".*?((_MONSTER)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$"; + private final String mobRegex = ".*?((_MONSTER)|(_NPC)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$"; private final String petRegex = ".*?;[0-5]$"; private final ResourceLocation[] sortIcons = new ResourceLocation[]{ @@ -211,7 +241,7 @@ public class NEUOverlay extends Gui { private boolean redrawItems = false; private boolean searchBarHasFocus = false; - private final GuiTextField textField = new GuiTextField(0, null, 0, 0, 0, 0); + private static final GuiTextField textField = new GuiTextField(0, null, 0, 0, 0, 0); private static final int COMPARE_MODE_ALPHABETICAL = 0; private static final int COMPARE_MODE_RARITY = 1; @@ -977,7 +1007,7 @@ public class NEUOverlay extends Gui { return paddingUnscaled; } - public GuiTextField getTextField() { + public static GuiTextField getTextField() { return textField; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 6d4e0d02..d08968c3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -26,6 +26,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns; import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager; import io.github.moulberry.notenoughupdates.miscfeatures.MiningStuff; import io.github.moulberry.notenoughupdates.miscfeatures.NPCRetexturing; +import io.github.moulberry.notenoughupdates.miscfeatures.Navigation; import io.github.moulberry.notenoughupdates.miscfeatures.NullzeeSphere; import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay; import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking; @@ -42,6 +43,7 @@ import io.github.moulberry.notenoughupdates.overlays.FuelBar; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.recipes.RecipeGenerator; +import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.Utils; import io.github.moulberry.notenoughupdates.util.XPInformation; @@ -139,6 +141,7 @@ public class NotEnoughUpdates { public NEUManager manager; public NEUOverlay overlay; public NEUConfig config; + public Navigation navigation = new Navigation(this); public GuiScreen openGui = null; public long lastOpenedGui = 0; public Commands commands; @@ -215,6 +218,7 @@ public class NotEnoughUpdates { MinecraftForge.EVENT_BUS.register(new CalendarOverlay()); MinecraftForge.EVENT_BUS.register(SBInfo.getInstance()); MinecraftForge.EVENT_BUS.register(CustomItemEffects.INSTANCE); + MinecraftForge.EVENT_BUS.register(new Constants()); MinecraftForge.EVENT_BUS.register(new DungeonMap()); MinecraftForge.EVENT_BUS.register(new SunTzu()); MinecraftForge.EVENT_BUS.register(new MiningStuff()); @@ -237,6 +241,7 @@ public class NotEnoughUpdates { MinecraftForge.EVENT_BUS.register(new ItemTooltipListener(this)); MinecraftForge.EVENT_BUS.register(new RenderListener(this)); MinecraftForge.EVENT_BUS.register(new OldAnimationChecker()); + MinecraftForge.EVENT_BUS.register(navigation); if (Minecraft.getMinecraft().getResourceManager() instanceof IReloadableResourceManager) { IReloadableResourceManager manager = (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java index 27944c92..478f4db7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java @@ -1,4 +1,4 @@ - package io.github.moulberry.notenoughupdates.commands.dev; +package io.github.moulberry.notenoughupdates.commands.dev; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; @@ -10,6 +10,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.Specia import io.github.moulberry.notenoughupdates.miscgui.GuiPriceGraph; import io.github.moulberry.notenoughupdates.util.SBInfo; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.util.BlockPos; @@ -24,7 +25,18 @@ import java.util.List; public class DevTestCommand extends ClientCommandBase { private static final List<String> DEV_TESTERS = - Arrays.asList("moulberry", "lucycoconut", "ironm00n", "ariyio", "throwpo", "lrg89", "dediamondpro", "lulonaut", "craftyoldminer"); + Arrays.asList( + "moulberry", + "lucycoconut", + "ironm00n", + "ariyio", + "throwpo", + "lrg89", + "dediamondpro", + "lulonaut", + "craftyoldminer", + "eisengolem" + ); private static final String[] DEV_FAIL_STRINGS = { "No.", @@ -132,6 +144,16 @@ public class DevTestCommand extends ClientCommandBase { "I would never search")); return; } + if (args.length == 2 && args[0].equalsIgnoreCase("openGui")) { + try { + NotEnoughUpdates.INSTANCE.openGui = (GuiScreen) Class.forName(args[1]).newInstance(); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "Opening gui: " + NotEnoughUpdates.INSTANCE.openGui)); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | ClassCastException e) { + e.printStackTrace(); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Failed to open this gui.")); + } + } if (args.length == 1 && args[0].equalsIgnoreCase("center")) { double x = Math.floor(Minecraft.getMinecraft().thePlayer.posX) + 0.5f; double z = Math.floor(Minecraft.getMinecraft().thePlayer.posZ) + 0.5f; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ReloadRepoCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ReloadRepoCommand.java index e363b59f..c4ef8c2c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ReloadRepoCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ReloadRepoCommand.java @@ -3,7 +3,6 @@ package io.github.moulberry.notenoughupdates.commands.repo; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import io.github.moulberry.notenoughupdates.options.NEUConfig; -import io.github.moulberry.notenoughupdates.util.Constants; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; @@ -20,9 +19,11 @@ public class ReloadRepoCommand extends ClientCommandBase { @Override public void processCommand(ICommandSender sender, String[] args) throws CommandException { - NotEnoughUpdates.INSTANCE.manager.reloadRepository(); - Constants.reload(); - + if (args.length > 1 && args[0].equals("fetch")) { + NotEnoughUpdates.INSTANCE.manager.fetchRepository(); + } else { + NotEnoughUpdates.INSTANCE.manager.reloadRepository(); + } NotEnoughUpdates.INSTANCE.newConfigFile(); if (NotEnoughUpdates.INSTANCE.getConfigFile().exists()) { try ( diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/RepoModeCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/RepoModeCommand.java index a8f53460..46156a47 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/RepoModeCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/RepoModeCommand.java @@ -5,7 +5,9 @@ import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import net.minecraft.client.Minecraft; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; +import net.minecraft.event.ClickEvent; import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatStyle; public class RepoModeCommand extends ClientCommandBase { @@ -33,10 +35,17 @@ public class RepoModeCommand extends ClientCommandBase { githubBranch = args[3]; } } - NotEnoughUpdates.INSTANCE.config.hidden.repoURL = "https://github.com/" + githubUser + "/" + githubRepo + "/archive/" + githubBranch + ".zip"; - NotEnoughUpdates.INSTANCE.config.hidden.repoCommitsURL = "https://api.github.com/repos/" + githubUser + "/" + githubRepo + "/commits/" + githubBranch; - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("\u00a75Set NEU repo URL to " + NotEnoughUpdates.INSTANCE.config.hidden.repoURL + - "\n\u00a75Set NEU repo commits URL to " + NotEnoughUpdates.INSTANCE.config.hidden.repoCommitsURL)); + NotEnoughUpdates.INSTANCE.config.hidden.repoURL = + "https://github.com/" + githubUser + "/" + githubRepo + "/archive/" + githubBranch + ".zip"; + NotEnoughUpdates.INSTANCE.config.hidden.repoCommitsURL = + "https://api.github.com/repos/" + githubUser + "/" + githubRepo + "/commits/" + githubBranch; + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "\u00a75Set NEU repo URL to " + NotEnoughUpdates.INSTANCE.config.hidden.repoURL + + "\n\u00a75Set NEU repo commits URL to " + NotEnoughUpdates.INSTANCE.config.hidden.repoCommitsURL)); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("\u00a75Run <") + .appendSibling(new ChatComponentText("/neureloadrepo fetch").setChatStyle(new ChatStyle().setChatClickEvent(new ClickEvent( + ClickEvent.Action.SUGGEST_COMMAND, "/neureloadrepo fetch")))) + .appendSibling(new ChatComponentText("\u00a75> to redownload your repo."))); } else { Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("\u00a7cUsage:" + diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java index d7fd7907..96e9729f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java @@ -13,11 +13,20 @@ import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.Entity; -import net.minecraft.util.*; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Vec3i; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL14; import org.lwjgl.util.vector.Vector3f; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class RenderUtils { public static void drawFloatingRectDark(int x, int y, int width, int height) { drawFloatingRectDark(x, y, width, height, true); @@ -345,11 +354,19 @@ public class RenderUtils { } } - public static void renderWayPoint(String str, BlockPos loc, float partialTicks) { + public static void renderWayPoint(String str, Vec3i loc, float partialTicks) { + renderWayPoint(str, new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks); + } + + public static void renderWayPoint(List<String> str, Vec3i loc, float partialTicks) { renderWayPoint(str, new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks); } public static void renderWayPoint(String str, Vector3f loc, float partialTicks) { + renderWayPoint(Arrays.asList(str), loc, partialTicks); + } + + public static void renderWayPoint(List<String> lines, Vector3f loc, float partialTicks) { GlStateManager.alphaFunc(516, 0.1F); GlStateManager.pushMatrix(); @@ -373,15 +390,9 @@ public class RenderUtils { GlStateManager.translate(x, y, z); GlStateManager.translate(0, viewer.getEyeHeight(), 0); - renderNametag(str); - - GlStateManager.rotate(-Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); - GlStateManager.rotate(Minecraft.getMinecraft().getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); - GlStateManager.translate(0, -0.25f, 0); - GlStateManager.rotate(-Minecraft.getMinecraft().getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F); - GlStateManager.rotate(Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F); - - renderNametag(EnumChatFormatting.YELLOW.toString() + Math.round(dist) + "m"); + lines = new ArrayList<>(lines); + lines.add(EnumChatFormatting.YELLOW.toString() + Math.round(dist) + "m"); + renderNametag(lines); GlStateManager.popMatrix(); @@ -389,6 +400,10 @@ public class RenderUtils { } public static void renderNametag(String str) { + renderNametag(Arrays.asList(str)); + } + + public static void renderNametag(List<String> lines) { FontRenderer fontrenderer = Minecraft.getMinecraft().fontRendererObj; float f = 1.6F; float f1 = 0.016666668F * f; @@ -406,20 +421,23 @@ public class RenderUtils { WorldRenderer worldrenderer = tessellator.getWorldRenderer(); int i = 0; - int j = fontrenderer.getStringWidth(str) / 2; - GlStateManager.disableTexture2D(); - worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); - worldrenderer.pos(-j - 1, -1 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); - worldrenderer.pos(-j - 1, 8 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); - worldrenderer.pos(j + 1, 8 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); - worldrenderer.pos(j + 1, -1 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); - tessellator.draw(); - GlStateManager.enableTexture2D(); - fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, 553648127); - GlStateManager.depthMask(true); - - fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, -1); - + for (String str : lines) { + int j = fontrenderer.getStringWidth(str) / 2; + + GlStateManager.disableTexture2D(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); + worldrenderer.pos(-j - 1, -1 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + worldrenderer.pos(-j - 1, 8 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + worldrenderer.pos(j + 1, 8 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + worldrenderer.pos(j + 1, -1 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex(); + tessellator.draw(); + GlStateManager.enableTexture2D(); + fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, 553648127); + GlStateManager.depthMask(true); + + fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, -1); + GlStateManager.translate(0, 10f, 0); + } GlStateManager.enableDepth(); GlStateManager.enableBlend(); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/events/RepositoryReloadEvent.java b/src/main/java/io/github/moulberry/notenoughupdates/events/RepositoryReloadEvent.java new file mode 100644 index 00000000..b0ffc3e7 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/events/RepositoryReloadEvent.java @@ -0,0 +1,21 @@ +package io.github.moulberry.notenoughupdates.events; + +import java.io.File; + +public class RepositoryReloadEvent extends NEUEvent { + private final File baseFile; + private boolean isFirstLoad; + + public RepositoryReloadEvent(File baseFile, boolean isFirstLoad) { + this.baseFile = baseFile; + this.isFirstLoad = isFirstLoad; + } + + public boolean isFirstLoad() { + return isFirstLoad; + } + + public File getRepositoryRoot() { + return baseFile; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java index 0392c32f..9f256d65 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java @@ -14,7 +14,11 @@ import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.entity.RenderItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.*; +import net.minecraft.nbt.JsonToNBT; +import net.minecraft.nbt.NBTException; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; @@ -27,7 +31,11 @@ import java.util.Arrays; import java.util.List; import java.util.function.Supplier; -import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.*; +import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.COLOUR; +import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.FORCE_CAPS; +import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.MULTILINE; +import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.NO_SPACE; +import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.NUM_ONLY; public class NEUItemEditor extends GuiScreen { private final NEUManager manager; @@ -52,6 +60,7 @@ public class NEUItemEditor extends GuiScreen { private final Supplier<String> clickcommand; private final Supplier<String> damage; private NBTTagCompound nbttag; + private boolean hasChanges = false; public NEUItemEditor(NEUManager manager, String internalname, JsonObject item) { this.manager = manager; @@ -295,6 +304,11 @@ public class NEUItemEditor extends GuiScreen { @Override protected void keyTyped(char typedChar, int keyCode) { + if (keyCode == Keyboard.KEY_ESCAPE && !hasChanges) { + Minecraft.getMinecraft().displayGuiScreen(null); + return; + } + for (GuiElement gui : options) { gui.keyTyped(typedChar, keyCode); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java index 54154955..6df2dd9a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java @@ -33,6 +33,7 @@ import io.github.moulberry.notenoughupdates.overlays.TextOverlay; import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; import io.github.moulberry.notenoughupdates.util.NotificationHandler; import io.github.moulberry.notenoughupdates.util.RequestFocusListener; +import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; @@ -55,6 +56,7 @@ import net.minecraft.nbt.NBTTagList; import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StringUtils; import net.minecraftforge.client.ClientCommandHandler; import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.client.event.GuiScreenEvent; @@ -74,16 +76,17 @@ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.text.NumberFormat; import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.TreeMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -107,6 +110,10 @@ public class RenderListener { private long buttonHoveredMillis = 0; private int inventoryLoadedTicks = 0; private String loadedInvName = ""; + //NPC parsing + private String correctingItem; + private boolean typing; + private HashMap<String, String> cachedDefinitions; public RenderListener(NotEnoughUpdates neu) { this.neu = neu; @@ -1011,6 +1018,9 @@ public class RenderListener { */ @SubscribeEvent public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) { + if (typing) { + event.setCanceled(true); + } if (Keyboard.isKeyDown(Keyboard.KEY_B) && NotEnoughUpdates.INSTANCE.config.hidden.dev) { if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; @@ -1094,7 +1104,7 @@ public class RenderListener { try { try ( BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(file), + Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8 )) ) { @@ -1112,6 +1122,141 @@ public class RenderListener { EnumChatFormatting.RED + "Error while parsing inventory. Try again or check logs for details.")); } } + } else if (Keyboard.isKeyDown(Keyboard.KEY_RETURN) && NotEnoughUpdates.INSTANCE.config.hidden.dev) { + Minecraft mc = Minecraft.getMinecraft(); + + if (typing) { + typing = false; + cachedDefinitions.put(correctingItem, NEUOverlay.getTextField().getText()); + NEUOverlay.getTextField().setText(""); + } + + if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + + try { + JsonObject newNPC = new JsonObject(); + String displayname = lower.getDisplayName().getUnformattedText(); + File file = new File( + Minecraft.getMinecraft().mcDataDir.getAbsolutePath(), + "config" + File.separator + "notenoughupdates" + + File.separator + "repo" + File.separator + "npc" + File.separator + + displayname.toUpperCase().replace(" ", "_") + ".json" + ); + newNPC.add("itemid", new JsonPrimitive("minecraft:skull")); + newNPC.add("displayname", new JsonPrimitive("§9" + displayname + " (NPC)")); + newNPC.add("nbttag", new JsonPrimitive("TODO")); + newNPC.add("damage", new JsonPrimitive(3)); + + JsonArray newArray = new JsonArray(); + newArray.add(new JsonPrimitive("")); + newNPC.add("lore", newArray); + newNPC.add("internalname", new JsonPrimitive(displayname.toUpperCase().replace(" ", "_") + "_NPC")); + newNPC.add("clickcommand", new JsonPrimitive("viewrecipe")); + newNPC.add("modver", new JsonPrimitive(NotEnoughUpdates.VERSION)); + newNPC.add("infoType", new JsonPrimitive("WIKI_URL")); + JsonArray emptyInfoArray = new JsonArray(); + emptyInfoArray.add(new JsonPrimitive("TODO")); + newNPC.add("info", emptyInfoArray); + newNPC.add("x", new JsonPrimitive((int) mc.thePlayer.posX)); + newNPC.add("y", new JsonPrimitive((int) mc.thePlayer.posY + 2)); + newNPC.add("z", new JsonPrimitive((int) mc.thePlayer.posZ)); + newNPC.add("island", new JsonPrimitive(SBInfo.getInstance().getLocation())); + + JsonArray recipesArray = new JsonArray(); + + TreeMap<String, JsonObject> itemInformation = NotEnoughUpdates.INSTANCE.manager.getItemInformation(); + for (int i = 0; i < 45; i++) { + ItemStack stack = lower.getStackInSlot(i); + if (stack == null) continue; + if (stack.getDisplayName().isEmpty() || stack.getDisplayName().equals(" ")) continue; + + String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalnameFromNBT(stack.getTagCompound()); + if (internalname == null) continue; + JsonObject currentRecipe = new JsonObject(); + currentRecipe.add("type", new JsonPrimitive("npc_shop")); + JsonArray costArray = new JsonArray(); + boolean inCost = false; + for (String s : NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound())) { + if (s.equals("§7Cost")) { + inCost = true; + continue; + } else if (s.equals("§eClick to trade!")) { + inCost = false; + } + if (!inCost) continue; + String entry = StringUtils.stripControlCodes(s); + if (entry.isEmpty()) continue; + int coinIndex = entry.indexOf(" Coins"); + if (coinIndex != -1) { + String amountString = entry.substring(0, coinIndex).replace(",", ""); + costArray.add(new JsonPrimitive("SKYBLOCK_COIN:" + amountString)); + } else { + if (cachedDefinitions == null) { + cachedDefinitions = new HashMap<>(); + } + + String item; + int amountIndex = entry.lastIndexOf(" x"); + String amountString; + if (amountIndex == -1) { + amountString = "1"; + item = entry.replace(" ", "_").toUpperCase(); + } else { + amountString = entry.substring(amountIndex); + item = entry.substring(0, amountIndex).replace(" ", "_").toUpperCase(); + } + amountString = amountString.replace(",", "").replace("x", "").trim(); + if (itemInformation.containsKey(item)) { + costArray.add(new JsonPrimitive(item + ":" + amountString)); + } else if (cachedDefinitions.containsKey(item)) { + costArray.add(new JsonPrimitive(cachedDefinitions.get(item) + ":" + amountString)); + } else { + mc.thePlayer.addChatMessage(new ChatComponentText( + "Change the item ID of " + item + " to the correct one and press Enter.")); + NEUOverlay.getTextField().setText(item); + event.setCanceled(true); + typing = true; + correctingItem = item; + if (cachedDefinitions == null) { + cachedDefinitions = new HashMap<>(); + } + return; + } + } + } + currentRecipe.add("cost", costArray); + currentRecipe.add("result", new JsonPrimitive(internalname)); + recipesArray.add(currentRecipe); + newNPC.add("recipes", recipesArray); + } + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(newNPC)); + try { + //noinspection ResultOfMethodCallIgnored + file.createNewFile(); + try ( + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( + Files.newOutputStream(file.toPath()), + StandardCharsets.UTF_8 + )) + ) { + writer.write(gson.toJson(newNPC)); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.AQUA + "Parsed and saved: " + EnumChatFormatting.WHITE + displayname)); + } + } catch (IOException ignored) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.RED + "Error while writing file.")); + } + } catch (Exception e) { + e.printStackTrace(); + mc.thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.RED + "Error while parsing inventory. Try again or check logs for details")); + } + } } if (AuctionBINWarning.getInstance().shouldShow()) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java new file mode 100644 index 00000000..3419b8c4 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java @@ -0,0 +1,398 @@ +package io.github.moulberry.notenoughupdates.miscfeatures; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; +import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent; +import io.github.moulberry.notenoughupdates.listener.RenderListener; +import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent; +import io.github.moulberry.notenoughupdates.miscgui.GuiNavigation; +import io.github.moulberry.notenoughupdates.util.ItemUtils; +import io.github.moulberry.notenoughupdates.util.JsonUtils; +import io.github.moulberry.notenoughupdates.util.NotificationHandler; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.Vec3i; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.lwjgl.input.Keyboard; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +public class Navigation { + + private List<Teleporter> teleporters = new ArrayList<>(); + private Map<String, String> areaNames = new HashMap<>(); + private Map<String, WarpPoint> warps = new HashMap<>(); + private Map<String, JsonObject> waypoints = new HashMap<>(); + + public Map<String, JsonObject> getWaypoints() { + return waypoints; + } + + public static class WarpPoint { + public final BlockPos blockPos; + public final String warpName, modeName; + + public WarpPoint(double x, double y, double z, String warpName, String modeName) { + this.blockPos = new BlockPos(x, y, z); + this.warpName = warpName; + this.modeName = modeName; + } + } + + public static class Teleporter { + public final double x, y, z; + public final String from, to; + + public Teleporter(double x, double y, double z, String from, String to) { + this.x = x; + this.y = y; + this.z = z; + this.from = from; + this.to = to; + } + } + + private NotEnoughUpdates neu; + + public Navigation(NotEnoughUpdates notEnoughUpdates) { + neu = notEnoughUpdates; + } + + /* JsonObject (x,y,z,island,displayname) */ + private JsonObject currentlyTrackedWaypoint = null; + private BlockPos position = null; + private String island = null; + private String displayName = null; + private String internalname = null; + private String warpAgainTo = null; + private int lastInvHashcode = 0; + private Instant warpAgainTiming = null; + + private Teleporter nextTeleporter = null; + + public boolean isValidWaypoint(JsonObject object) { + return object.has("x") + && object.has("y") + && object.has("z") + && object.has("island") + && object.has("displayname") + && object.has("internalname"); + } + + public void trackWaypoint(String trackNow) { + if (trackNow == null) { + trackWaypoint((JsonObject) null); + } else { + JsonObject jsonObject = waypoints.get(trackNow); + if (jsonObject == null) { + showError( + "Could not track waypoint " + trackNow + ". This is likely due to an outdated or broken repository.", + true + ); + return; + } + trackWaypoint(jsonObject); + } + } + + public void trackWaypoint(JsonObject trackNow) { + if (trackNow != null && !isValidWaypoint(trackNow)) { + showError("Could not track waypoint. This is likely due to an outdated or broken repository.", true); + return; + } + if (!neu.config.hidden.hasOpenedWaypointMenu) + NotificationHandler.displayNotification(Arrays.asList( + "You just tracked a waypoint.", + "Press [N] to open the waypoint menu to untrack it", + "or to find other waypoints to track.", + "Press [X] to close this message." + ), true, false); + currentlyTrackedWaypoint = trackNow; + updateData(); + } + + @SubscribeEvent + public void onRepositoryReload(RepositoryReloadEvent event) { + JsonObject obj = Utils.getConstant("islands", neu.manager.gson); + List<Teleporter> teleporters = JsonUtils.getJsonArrayOrEmpty(obj, "teleporters", jsonElement -> { + JsonObject teleporterObj = jsonElement.getAsJsonObject(); + return new Teleporter( + teleporterObj.get("x").getAsDouble(), + teleporterObj.get("y").getAsDouble(), + teleporterObj.get("z").getAsDouble(), + teleporterObj.get("from").getAsString(), + teleporterObj.get("to").getAsString() + ); + }); + for (Teleporter teleporter : teleporters) { + if (teleporter.from.equals(teleporter.to)) { + showError("Found self referencing teleporter: " + teleporter.from, true); + } + } + this.teleporters = teleporters; + this.waypoints = NotEnoughUpdates.INSTANCE.manager + .getItemInformation().values().stream() + .filter(this::isValidWaypoint) + .collect(Collectors.toMap(it -> it.get("internalname").getAsString(), it -> it)); + this.areaNames = JsonUtils.transformJsonObjectToMap(obj.getAsJsonObject("area_names"), JsonElement::getAsString); + this.warps = JsonUtils.getJsonArrayOrEmpty(obj, "island_warps", jsonElement -> { + JsonObject warpObject = jsonElement.getAsJsonObject(); + return new WarpPoint( + warpObject.get("x").getAsDouble(), + warpObject.get("y").getAsDouble(), + warpObject.get("z").getAsDouble(), + warpObject.get("warp").getAsString(), + warpObject.get("mode").getAsString() + ); + }).stream().collect(Collectors.toMap(it -> it.warpName, it -> it)); + } + + @SubscribeEvent + public void onKeybindPressed(InputEvent.KeyInputEvent event) { + if (!Keyboard.getEventKeyState()) return; + int key = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey(); + if (neu.config.misc.keybindWaypoint == key) { + if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { + if (currentlyTrackedWaypoint != null) { + useWarpCommand(); + } + } else { + Minecraft.getMinecraft().displayGuiScreen(new GuiNavigation()); + } + } + } + + @SubscribeEvent + public void onGuiTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + if (Minecraft.getMinecraft().theWorld == null) return; + if (Minecraft.getMinecraft().thePlayer == null) return; + + if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && RenderListener.inventoryLoaded) { + GuiChest currentScreen = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest container = (ContainerChest) currentScreen.inventorySlots; + if (container.getLowerChestInventory().getDisplayName().getUnformattedText().equals("Fast Travel")) { + int hashCode = container.getInventory().hashCode(); + if (hashCode == lastInvHashcode) return; + lastInvHashcode = hashCode; + for (ItemStack stackInSlot : container.getInventory()) { + if (stackInSlot == null) continue; + List<String> lore = ItemUtils.getLore(stackInSlot); + if (lore.isEmpty()) + continue; + String warpLine = Utils.cleanColour(lore.get(0)); + if (!warpLine.startsWith("/warp ")) continue; + String warpName = warpLine.substring(6); + boolean isUnlocked = !lore.contains("§cWarp not unlocked!"); + neu.config.getProfileSpecific().unlockedWarpScrolls.put(warpName, isUnlocked); + } + } + } + } + + public Map<String, WarpPoint> getWarps() { + return warps; + } + + public WarpPoint getClosestWarp(String mode, Vec3i position, boolean checkAvailable) { + double minDistance = -1; + HashMap<String, Boolean> unlockedWarpScrolls = neu.config.getProfileSpecific().unlockedWarpScrolls; + WarpPoint minWarp = null; + for (WarpPoint value : warps.values()) { + if (value.modeName.equals(mode)) { + if (checkAvailable && !unlockedWarpScrolls.getOrDefault(value.warpName, false)) + continue; + double distance = value.blockPos.distanceSq(position); + if (distance < minDistance || minWarp == null) { + minDistance = distance; + minWarp = value; + } + } + } + return minWarp; + } + + public void useWarpCommand() { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + if (currentlyTrackedWaypoint == null || thePlayer == null) return; + WarpPoint closestWarp = getClosestWarp(island, position, true); + if (closestWarp == null) { + showError("Could not find an unlocked warp that could be used.", false); + return; + } + + if (!island.equals(SBInfo.getInstance().mode)) { + warpAgainTiming = Instant.now(); + warpAgainTo = closestWarp.warpName; + } else if (thePlayer.getDistanceSq(position) < closestWarp.blockPos.distanceSq(position)) { + showError("You are already on the same island and nearer than the closest unlocked warp scroll.", false); + return; + } + thePlayer.sendChatMessage("/warp " + closestWarp.warpName); + } + + @SubscribeEvent + public void onTeleportDone(EntityJoinWorldEvent event) { + if (neu.config.misc.warpTwice + && event.entity == Minecraft.getMinecraft().thePlayer + && warpAgainTo != null + && warpAgainTiming != null + && warpAgainTiming.plusSeconds(1).isAfter(Instant.now())) { + warpAgainTiming = null; + String savedWarpAgain = warpAgainTo; + warpAgainTo = null; + Minecraft.getMinecraft().thePlayer.sendChatMessage("/warp " + savedWarpAgain); + } + } + + public String getNameForAreaMode(String mode) { + return areaNames.get(mode); + } + + public String getNameForAreaModeOrUnknown(String mode) { + return areaNames.getOrDefault(mode, "Unknown"); + } + + public void untrackWaypoint() { + trackWaypoint((JsonObject) null); + } + + public JsonObject getTrackedWaypoint() { + return currentlyTrackedWaypoint; + } + + public String getIsland() { + return island; + } + + public String getDisplayName() { + return displayName; + } + + public BlockPos getPosition() { + return position; + } + + public String getInternalname() { + return internalname; + } + + private void updateData() { + if (currentlyTrackedWaypoint == null) { + position = null; + island = null; + displayName = null; + nextTeleporter = null; + internalname = null; + return; + } + position = new BlockPos( + currentlyTrackedWaypoint.get("x").getAsDouble(), + currentlyTrackedWaypoint.get("y").getAsDouble(), + currentlyTrackedWaypoint.get("z").getAsDouble() + ); + internalname = currentlyTrackedWaypoint.get("internalname").getAsString(); + island = currentlyTrackedWaypoint.get("island").getAsString(); + displayName = currentlyTrackedWaypoint.get("displayname").getAsString(); + recalculateNextTeleporter(SBInfo.getInstance().mode); + } + + @SubscribeEvent + public void onLocationChange(LocationChangeEvent event) { + recalculateNextTeleporter(event.newLocation); + } + + public Teleporter recalculateNextTeleporter(String from) { + String to = island; + if (from == null || to == null) return null; + List<Teleporter> nextTeleporter = findNextTeleporter0(from, to, new HashSet<>()); + if (nextTeleporter == null || nextTeleporter.isEmpty()) { + this.nextTeleporter = null; + } else { + this.nextTeleporter = nextTeleporter.get(0); + } + return this.nextTeleporter; + } + + private List<Teleporter> findNextTeleporter0(String from, String to, Set<String> visited) { + if (from.equals(to)) return new ArrayList<>(); + if (visited.contains(from)) return null; + visited.add(from); + int minPathLength = 0; + List<Teleporter> minPath = null; + for (Teleporter teleporter : teleporters) { + if (!teleporter.from.equals(from)) continue; + List<Teleporter> nextTeleporter0 = findNextTeleporter0(teleporter.to, to, visited); + if (nextTeleporter0 == null) continue; + if (minPath == null || nextTeleporter0.size() < minPathLength) { + minPathLength = nextTeleporter0.size(); + nextTeleporter0.add(0, teleporter); + minPath = nextTeleporter0; + } + } + visited.remove(from); + return minPath; + } + + private void showError(String message, boolean log) { + EntityPlayerSP player = Minecraft.getMinecraft().thePlayer; + if (player != null) + player.addChatMessage(new ChatComponentText(EnumChatFormatting.DARK_RED + + "[NEU-Waypoint] " + message)); + if (log) + new RuntimeException("[NEU-Waypoint] " + message).printStackTrace(); + } + + @SubscribeEvent + public void onEvent(TickEvent.ClientTickEvent event) { + if (event.phase == TickEvent.Phase.END && currentlyTrackedWaypoint != null + && NotEnoughUpdates.INSTANCE.config.misc.untrackCloseWaypoints + && island.equals(SBInfo.getInstance().mode)) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + if (thePlayer.getDistanceSq(position) < 16) + untrackWaypoint(); + } + } + + @SubscribeEvent + public void onRenderLast(RenderWorldLastEvent event) { + if (currentlyTrackedWaypoint != null) { + if (island.equals(SBInfo.getInstance().mode)) { + RenderUtils.renderWayPoint(displayName, position, event.partialTicks); + } else if (nextTeleporter != null) { + String to = nextTeleporter.to; + String toName = getNameForAreaModeOrUnknown(to); + RenderUtils.renderWayPoint( + Arrays.asList("Teleporter to " + toName, "(towards " + displayName + "§r)"), + new BlockPos( + nextTeleporter.x, + nextTeleporter.y, + nextTeleporter.z + ), event.partialTicks + ); + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java index be9ce6c7..129e25e7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java @@ -8,6 +8,7 @@ import io.github.moulberry.notenoughupdates.recipes.RecipeType; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; @@ -22,8 +23,11 @@ import org.lwjgl.opengl.GL11; import java.awt.*; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; -import java.util.*; +import java.util.Map; public class GuiItemRecipe extends GuiScreen { public static final ResourceLocation resourcePacksTexture = new ResourceLocation("textures/gui/resource_packs.png"); @@ -68,6 +72,13 @@ public class GuiItemRecipe extends GuiScreen { } } + @Override + public void initGui() { + this.guiLeft = (width - this.xSize) / 2; + this.guiTop = (height - this.ySize) / 2; + changeRecipe(0, 0); + } + public NeuRecipe getCurrentRecipe() { List<NeuRecipe> currentRecipes = getCurrentRecipeList(); currentIndex = MathHelper.clamp_int(currentIndex, 0, currentRecipes.size() - 1); @@ -84,8 +95,8 @@ public class GuiItemRecipe extends GuiScreen { } public boolean isWithinRect(int x, int y, int topLeftX, int topLeftY, int width, int height) { - return topLeftX <= x && x <= topLeftX + width - && topLeftY <= y && y <= topLeftY + height; + return topLeftX <= x && x < topLeftX + width + && topLeftY <= y && y < topLeftY + height; } private ImmutableList<RecipeSlot> getAllRenderedSlots() { @@ -99,9 +110,6 @@ public class GuiItemRecipe extends GuiScreen { drawDefaultBackground(); FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj; - this.guiLeft = (width - this.xSize) / 2; - this.guiTop = (height - this.ySize) / 2; - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); NeuRecipe currentRecipe = getCurrentRecipe(); @@ -131,7 +139,7 @@ public class GuiItemRecipe extends GuiScreen { ); currentRecipe.drawExtraInfo(this, mouseX, mouseY); - + super.drawScreen(mouseX, mouseY, partialTicks); for (RecipeSlot slot : slots) { if (isWithinRect(mouseX, mouseY, slot.getX(this), slot.getY(this), SLOT_SIZE, SLOT_SIZE)) { if (slot.getItemStack() == null) continue; @@ -292,6 +300,18 @@ public class GuiItemRecipe extends GuiScreen { } } + public void changeRecipe(int tabIndex, int recipeIndex) { + buttonList.removeAll(getCurrentRecipe().getExtraButtons(this)); + currentTab = tabIndex; + currentIndex = recipeIndex; + buttonList.addAll(getCurrentRecipe().getExtraButtons(this)); + } + + @Override + protected void actionPerformed(GuiButton p_actionPerformed_1_) throws IOException { + getCurrentRecipe().actionPerformed(p_actionPerformed_1_); + } + @Override protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { super.mouseClicked(mouseX, mouseY, mouseButton); @@ -310,7 +330,7 @@ public class GuiItemRecipe extends GuiScreen { BUTTON_HEIGHT ) && currentIndex > 0) { - currentIndex = currentIndex - 1; + changeRecipe(currentTab, currentIndex - 1); Utils.playPressSound(); return; } @@ -324,7 +344,7 @@ public class GuiItemRecipe extends GuiScreen { BUTTON_HEIGHT ) && currentIndex < getCurrentRecipeList().size()) { - currentIndex = currentIndex + 1; + changeRecipe(currentTab, currentIndex + 1); Utils.playPressSound(); return; } @@ -338,7 +358,7 @@ public class GuiItemRecipe extends GuiScreen { TAB_SIZE_X, TAB_SIZE_Y )) { - currentTab = i; + changeRecipe(i, currentIndex); Utils.playPressSound(); return; } @@ -349,10 +369,14 @@ public class GuiItemRecipe extends GuiScreen { ItemStack itemStack = slot.getItemStack(); if (mouseButton == 0) { manager.displayGuiItemRecipe(manager.getInternalNameForItem(itemStack)); + return; } else if (mouseButton == 1) { manager.displayGuiItemUsages(manager.getInternalNameForItem(itemStack)); + return; } } } + + currentRecipe.mouseClicked(this, mouseX, mouseY, mouseButton); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiNavigation.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiNavigation.java new file mode 100644 index 00000000..d34988f6 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiNavigation.java @@ -0,0 +1,154 @@ +package io.github.moulberry.notenoughupdates.miscgui; + +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.GuiElementTextField; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ResourceLocation; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +public class GuiNavigation extends GuiScreen { + + public static ResourceLocation BACKGROUND = new ResourceLocation( + "notenoughupdates", + "textures/gui/navigation.png" + ); + + public static final int PIN_POSITION_U = 182; + public static final int PIN_POSITION_V = 3; + public static final int TICK_POSITION_U = 182; + public static final int TICK_POSITION_V = 34; + public static final int ICON_SIZE = 26; + + public static final int SEARCH_BAR_X = 14; + public static final int SEARCH_BAR_Y = 11; + public static final int SEARCH_BAR_WIDTH = 151; + public static final int SEARCH_BAR_HEIGHT = 24; + + public static final int LIST_START_X = 14; + public static final int LIST_START_Y = 43; + public static final int LIST_OFFSET_Y = 28; + public static final int TEXT_OFFSET_X = 28; + public static final int LIST_COUNT = 6; + + List<String> searchResults = new ArrayList<>(); + + public int xSize = 176; + public int ySize = 222; + public int guiLeft, guiTop; + + public GuiElementTextField textField = new GuiElementTextField("", SEARCH_BAR_WIDTH, SEARCH_BAR_HEIGHT, 0); + + @Override + public void initGui() { + super.initGui(); + NotEnoughUpdates.INSTANCE.config.hidden.hasOpenedWaypointMenu = true; + guiLeft = (width - xSize) / 2; + guiTop = (height - ySize) / 2; + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + drawDefaultBackground(); + Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND); + this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize); + textField.render(guiLeft + SEARCH_BAR_X, guiTop + SEARCH_BAR_Y); + + refreshResults(); + for (int i = 0; i < LIST_COUNT; i++) { + if (i < searchResults.size()) { + Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND); + String name = searchResults.get(i); + JsonObject json = NotEnoughUpdates.INSTANCE.navigation.getWaypoints().get(name); + boolean selected = name.equals(NotEnoughUpdates.INSTANCE.navigation.getInternalname()); + int baseX = guiLeft + LIST_START_X; + int baseY = guiTop + LIST_START_Y + LIST_OFFSET_Y * i; + + GlStateManager.color(1F, 1F, 1F); + drawTexturedModalRect( + baseX, + baseY, + selected ? TICK_POSITION_U : PIN_POSITION_U, selected ? TICK_POSITION_V : PIN_POSITION_V, + ICON_SIZE, ICON_SIZE + ); + Utils.drawStringF( + json.get("displayname").getAsString(), + Minecraft.getMinecraft().fontRendererObj, + baseX + TEXT_OFFSET_X, + baseY + LIST_OFFSET_Y / 2F - Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT / 2F, + false, + 0x000000 + ); + } + } + } + + private void refreshResults() { + String text = textField.getText().toLowerCase(); + List<String> results = NotEnoughUpdates.INSTANCE.navigation + .getWaypoints() + .values() + .stream() + .filter(it -> + it.get("internalname").getAsString().toLowerCase().contains(text) + || it.get("displayname").getAsString().toLowerCase().contains(text)) + .map(it -> it.get("internalname").getAsString()) + .sorted(Comparator.comparing(String::length) + .thenComparing(String.CASE_INSENSITIVE_ORDER)) + .collect(Collectors.toList()); + + String internalname = NotEnoughUpdates.INSTANCE.navigation.getInternalname(); + if (internalname != null) { + results.remove(internalname); + results.add(0, internalname); + } + searchResults = results; + } + + @Override + protected void keyTyped(char p_keyTyped_1_, int p_keyTyped_2_) throws IOException { + super.keyTyped(p_keyTyped_1_, p_keyTyped_2_); + textField.keyTyped(p_keyTyped_1_, p_keyTyped_2_); + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + super.mouseClicked(mouseX, mouseY, mouseButton); + if (Utils.isWithinRect( + mouseX, + mouseY, + guiLeft + SEARCH_BAR_X, + guiTop + SEARCH_BAR_Y, + SEARCH_BAR_WIDTH, + SEARCH_BAR_HEIGHT + )) { + textField.mouseClicked(mouseX, mouseY, mouseButton); + } else { + textField.setFocus(false); + } + for (int i = 0; i < LIST_COUNT; i++) { + if (i < searchResults.size()) { + int baseX = guiLeft + LIST_START_X; + int baseY = guiTop + LIST_START_Y + LIST_OFFSET_Y * i; + if (Utils.isWithinRect(mouseX, mouseY, baseX, baseY, ICON_SIZE, ICON_SIZE)) { + String thing = searchResults.get(i); + boolean selected = thing.equals(NotEnoughUpdates.INSTANCE.navigation.getInternalname()); + if (selected) { + NotEnoughUpdates.INSTANCE.navigation.untrackWaypoint(); + } else { + NotEnoughUpdates.INSTANCE.navigation.trackWaypoint(thing); + } + Utils.playPressSound(); + } + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java index 5c766254..2e31fbf3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java @@ -417,6 +417,9 @@ public class NEUConfig extends Config { @Expose public boolean npcRetextureOnSelf = false; + @Expose + public boolean hasOpenedWaypointMenu = false; + } public static ArrayList<String> createDefaultEnchantColours() { @@ -511,6 +514,8 @@ public class NEUConfig extends Config { @Expose public long dailyMithrilPowerCompleted = 0L; @Expose + public HashMap<String, Boolean> unlockedWarpScrolls = new HashMap<>(); + @Expose public long dailyHeavyPearlCompleted = 0L; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java index 631ce545..a04a51f9 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java @@ -1,7 +1,15 @@ package io.github.moulberry.notenoughupdates.options.seperateSections; import com.google.gson.annotations.Expose; -import io.github.moulberry.notenoughupdates.core.config.annotations.*; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorKeybind; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption; +import org.lwjgl.input.Keyboard; public class Misc { @Expose @@ -163,4 +171,29 @@ public class Misc { "Fandom" }) public int wiki = 0; + + @Expose + @ConfigOption( + name = "Waypoint Keybind", + desc = "Press this keybind to show waypoints to various NPCs" + ) + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_N) + public int keybindWaypoint = Keyboard.KEY_N; + + @Expose + @ConfigOption( + name = "Untrack close Waypoints", + desc = "Automatically untrack waypoints once you get close to them." + ) + @ConfigEditorBoolean + public boolean untrackCloseWaypoints = true; + + @Expose + @ConfigOption( + name = "Warp twice", + desc = "Warp twice when using SHIFT+N to /warp to a waypoint." + ) + @ConfigEditorBoolean + public boolean warpTwice = true; + } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java index 87712378..1729cfa7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java @@ -4835,12 +4835,7 @@ public class GuiProfileViewer extends GuiScreen { if (profile.getUuid().equals("20934ef9488c465180a78f861586b4cf")) { locationStr = "Ignoring DMs"; } else { - if (location != null) { - JsonObject misc = Constants.MISC; - if (misc != null) { - locationStr = Utils.getElementAsString(Utils.getElement(misc, "area_names." + location), "Unknown"); - } - } + locationStr = NotEnoughUpdates.INSTANCE.navigation.getNameForAreaModeOrUnknown(location); } if (locationStr != null) { statusStr += EnumChatFormatting.GRAY + " - " + EnumChatFormatting.GREEN + locationStr; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/ItemShopRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/ItemShopRecipe.java new file mode 100644 index 00000000..778f156f --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/ItemShopRecipe.java @@ -0,0 +1,189 @@ +package io.github.moulberry.notenoughupdates.recipes; + +import com.google.common.collect.Sets; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import io.github.moulberry.notenoughupdates.NEUManager; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe; +import io.github.moulberry.notenoughupdates.miscgui.GuiNavigation; +import io.github.moulberry.notenoughupdates.util.JsonUtils; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class ItemShopRecipe implements NeuRecipe { + public static ResourceLocation BACKGROUND = new ResourceLocation( + "notenoughupdates", + "textures/gui/item_shop_recipe.png" + ); + + private static final int SLOT_IMAGE_U = 176; + private static final int SLOT_IMAGE_V = 0; + + private static final int SLOT_IMAGE_SIZE = 18; + public static final int RESULT_SLOT_Y = 66; + public static final int RESULT_SLOT_X = 124; + + public static final int BUTTON_X = 130; + public static final int BUTTON_Y = 16; + + private static final int COST_SLOT_X = 30; + private static final int COST_SLOT_SPACING = 6; + private static final int ROW_SPACING = 18; + private final List<Ingredient> cost; + private final Ingredient result; + private boolean selected; + + private final Ingredient npcIngredient; + private final boolean hasWaypoint; + private final JsonObject npcObject; + + public ItemShopRecipe(Ingredient npcIngredient, List<Ingredient> cost, Ingredient result, JsonObject npcObject) { + this.npcIngredient = npcIngredient; + this.cost = cost; + this.result = result; + this.npcObject = npcObject; + hasWaypoint = NotEnoughUpdates.INSTANCE.navigation.isValidWaypoint(npcObject); + } + + @Override + public Set<Ingredient> getCatalystItems() { + return Sets.newHashSet(npcIngredient); + } + + @Override + public Set<Ingredient> getIngredients() { + return new HashSet<>(cost); + } + + @Override + public Set<Ingredient> getOutputs() { + return Sets.newHashSet(result); + } + + @Override + public List<RecipeSlot> getSlots() { + List<RecipeSlot> slots = new ArrayList<>(); + + int i = 0; + int colCount = cost.size() / 4; + int startX = COST_SLOT_X - 8 * (colCount - 1); + int rowSize = cost.size(); + if (rowSize > 4) rowSize = 4; + int startY = RESULT_SLOT_Y + 8 - (SLOT_IMAGE_SIZE * rowSize + COST_SLOT_SPACING * (rowSize - 1)) / 2; + for (Ingredient ingredient : cost) { + slots.add(new RecipeSlot( + startX + (i / 4) * ROW_SPACING + 1, + startY + (i % 4) * (SLOT_IMAGE_SIZE + COST_SLOT_SPACING) + 1, + ingredient.getItemStack() + )); + i++; + } + slots.add(new RecipeSlot(RESULT_SLOT_X, RESULT_SLOT_Y, result.getItemStack())); + return slots; + } + + @Override + public void drawExtraBackground(GuiItemRecipe gui, int mouseX, int mouseY) { + Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND); + int colCount = cost.size() / 4; + int startX = COST_SLOT_X - 8 * (colCount - 1); + int rowSize = cost.size(); + if (rowSize > 4) rowSize = 4; + int startY = RESULT_SLOT_Y + 8 - (SLOT_IMAGE_SIZE * rowSize + COST_SLOT_SPACING * (rowSize - 1)) / 2; + for (int i = 0; i < cost.size(); i++) { + gui.drawTexturedModalRect( + gui.guiLeft + startX + (i / 4) * ROW_SPACING, + gui.guiTop + startY + (i % 4) * (SLOT_IMAGE_SIZE + COST_SLOT_SPACING), + SLOT_IMAGE_U, SLOT_IMAGE_V, + SLOT_IMAGE_SIZE, SLOT_IMAGE_SIZE + ); + } + if (!hasWaypoint) return; + Minecraft.getMinecraft().getTextureManager().bindTexture(GuiNavigation.BACKGROUND); + selected = npcIngredient.getInternalItemId().equals(NotEnoughUpdates.INSTANCE.navigation.getInternalname()); + gui.drawTexturedModalRect( + gui.guiLeft + BUTTON_X, + gui.guiTop + BUTTON_Y, + selected ? GuiNavigation.TICK_POSITION_U : GuiNavigation.PIN_POSITION_U, + selected ? GuiNavigation.TICK_POSITION_V : GuiNavigation.PIN_POSITION_V, + GuiNavigation.ICON_SIZE, + GuiNavigation.ICON_SIZE + ); + } + + @Override + public void mouseClicked(GuiItemRecipe gui, int mouseX, int mouseY, int mouseButton) { + if (hasWaypoint && Utils.isWithinRect( + mouseX - gui.guiLeft, + mouseY - gui.guiTop, + BUTTON_X, + BUTTON_Y, + GuiNavigation.ICON_SIZE, + GuiNavigation.ICON_SIZE + )) { + boolean shiftPressed = Keyboard.isKeyDown(Keyboard.KEY_RSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_LSHIFT); + if (selected && !shiftPressed) { + NotEnoughUpdates.INSTANCE.navigation.untrackWaypoint(); + } else { + NotEnoughUpdates.INSTANCE.navigation.trackWaypoint(npcIngredient.getInternalItemId()); + if (shiftPressed) { + NotEnoughUpdates.INSTANCE.navigation.useWarpCommand(); + } + } + Utils.playPressSound(); + selected = !selected; + } + } + + @Override + public String getTitle() { + return npcObject.get("displayname").getAsString(); + } + + @Override + public RecipeType getType() { + return RecipeType.NPC_SHOP; + } + + @Override + public boolean hasVariableCost() { + return false; + } + + @Override + public JsonObject serialize() { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("type", "npc_shop"); + jsonObject.addProperty("result", result.serialize()); + jsonObject.add( + "cost", + JsonUtils.transformListToJsonArray(cost, costItem -> new JsonPrimitive(costItem.serialize())) + ); + return jsonObject; + } + + @Override + public ResourceLocation getBackground() { + return BACKGROUND; + } + + public static NeuRecipe parseItemRecipe(NEUManager neuManager, JsonObject recipe, JsonObject outputItemJson) { + return new ItemShopRecipe( + new Ingredient(neuManager, outputItemJson.get("internalname").getAsString()), + JsonUtils.transformJsonArrayToList( + recipe.getAsJsonArray("cost"), + it -> new Ingredient(neuManager, it.getAsString()) + ), + new Ingredient(neuManager, recipe.get("result").getAsString()), + outputItemJson + ); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java index dcbf71da..b98fbe10 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java @@ -1,7 +1,6 @@ package io.github.moulberry.notenoughupdates.recipes; import com.google.common.collect.Sets; -import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; @@ -14,7 +13,6 @@ import io.github.moulberry.notenoughupdates.util.JsonUtils; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; @@ -24,7 +22,6 @@ import java.util.List; import java.util.Set; import java.util.function.BiConsumer; import java.util.stream.Collectors; -import java.util.stream.Stream; public class MobLootRecipe implements NeuRecipe { @@ -144,8 +141,13 @@ public class MobLootRecipe implements NeuRecipe { } @Override + public Set<Ingredient> getCatalystItems() { + return Sets.newHashSet(mobIngredient); + } + + @Override public Set<Ingredient> getOutputs() { - return Stream.concat(drops.stream().map(it -> it.drop), Stream.of(mobIngredient)).collect(Collectors.toSet()); + return drops.stream().map(it -> it.drop).collect(Collectors.toSet()); } @Override diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java index 8202bb48..04945cc5 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java @@ -3,8 +3,11 @@ package io.github.moulberry.notenoughupdates.recipes; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe; +import net.minecraft.client.gui.GuiButton; import net.minecraft.util.ResourceLocation; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -30,10 +33,22 @@ public interface NeuRecipe { default void drawHoverInformation(GuiItemRecipe gui, int mouseX, int mouseY) { } + default void mouseClicked(GuiItemRecipe gui, int mouseX, int mouseY, int mouseButton) {} + + default void handleKeyboardInput() {} + + default Set<Ingredient> getCatalystItems() { + return Collections.emptySet(); + } + boolean hasVariableCost(); JsonObject serialize(); + default List<GuiButton> getExtraButtons(GuiItemRecipe guiItemRecipe) { + return new ArrayList<>(); + } + ResourceLocation getBackground(); static NeuRecipe parseRecipe(NEUManager manager, JsonObject recipe, JsonObject output) { @@ -59,4 +74,6 @@ public interface NeuRecipe { default int[] getPageFlipPositionLeftTopCorner() { return new int[]{110, 90}; } + + default void actionPerformed(GuiButton button) {} } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeType.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeType.java index cc8b50be..023b20eb 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeType.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeType.java @@ -10,7 +10,8 @@ public enum RecipeType { CRAFTING("crafting", "Crafting", CraftingRecipe::parseCraftingRecipe, new ItemStack(Blocks.crafting_table)), FORGE("forge", "Forging", ForgeRecipe::parseForgeRecipe, new ItemStack(Blocks.anvil)), TRADE("trade", "Trading", VillagerTradeRecipe::parseStaticRecipe, new ItemStack(Items.emerald)), - MOB_LOOT("drops", "Mob Loot", MobLootRecipe::parseRecipe, new ItemStack(Items.diamond_sword)); + MOB_LOOT("drops", "Mob Loot", MobLootRecipe::parseRecipe, new ItemStack(Items.diamond_sword)), + NPC_SHOP("npc_shop", "NPC Item Shop", ItemShopRecipe::parseItemRecipe, new ItemStack(Items.wheat_seeds)); private final String id; private final String label; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java index 2e53e153..10eb96a5 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java @@ -125,7 +125,7 @@ public class VillagerTradeRecipe implements NeuRecipe { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("type", "trade"); jsonObject.addProperty("result", result.serialize()); - jsonObject.addProperty("cost", cost.getInternalItemId()); + jsonObject.addProperty("cost", cost.serialize()); if (minCost > 0) jsonObject.addProperty("min", minCost); if (maxCost > 0) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java index dab4844d..4c421f3e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java @@ -1,6 +1,17 @@ package io.github.moulberry.notenoughupdates.util; -import com.google.gson.*; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import java.lang.reflect.Type; import java.util.concurrent.locks.ReentrantLock; @@ -42,7 +53,8 @@ public class Constants { private static final ReentrantLock lock = new ReentrantLock(); - public static void reload() { + @SubscribeEvent + public void reload(RepositoryReloadEvent event) { try { lock.lock(); @@ -57,6 +69,8 @@ public class Constants { ESSENCECOSTS = Utils.getConstant("essencecosts", gson); FAIRYSOULS = Utils.getConstant("fairy_souls", gson); REFORGESTONES = Utils.getConstant("reforgestones", gson); + } catch (Exception ex) { + ex.printStackTrace(); } finally { lock.unlock(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java index e3d90aaa..729e68bd 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java @@ -1,19 +1,39 @@ package io.github.moulberry.notenoughupdates.util; -import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagString; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class ItemUtils { - public static ItemStack getCoinItemStack(int coinAmount) { - ItemStack itemStack = new ItemStack(Items.gold_nugget); - itemStack.setStackDisplayName("\u00A7r\u00A76" + Utils.formatNumberWithDots(coinAmount) + " Coins"); - return itemStack; + public static ItemStack getCoinItemStack(long coinAmount) { + String uuid = "2070f6cb-f5db-367a-acd0-64d39a7e5d1b"; + String texture = + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTM4MDcxNzIxY2M1YjRjZDQwNmNlNDMxYTEzZjg2MDgzYTg5NzNlMTA2NGQyZjg4OTc4Njk5MzBlZTZlNTIzNyJ9fX0="; + if (coinAmount >= 100000) { + uuid = "94fa2455-2881-31fe-bb4e-e3e24d58dbe3"; + texture = + "eyJ0aW1lc3RhbXAiOjE2MzU5NTczOTM4MDMsInByb2ZpbGVJZCI6ImJiN2NjYTcxMDQzNDQ0MTI4ZDMwODllMTNiZGZhYjU5IiwicHJvZmlsZU5hbWUiOiJsYXVyZW5jaW8zMDMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2M5Yjc3OTk5ZmVkM2EyNzU4YmZlYWYwNzkzZTUyMjgzODE3YmVhNjQwNDRiZjQzZWYyOTQzM2Y5NTRiYjUyZjYiLCJtZXRhZGF0YSI6eyJtb2RlbCI6InNsaW0ifX19fQo="; + } + if (coinAmount >= 10000000) { + uuid = "0af8df1f-098c-3b72-ac6b-65d65fd0b668"; + texture = + "ewogICJ0aW1lc3RhbXAiIDogMTYzNTk1NzQ4ODQxNywKICAicHJvZmlsZUlkIiA6ICJmNThkZWJkNTlmNTA0MjIyOGY2MDIyMjExZDRjMTQwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ1bnZlbnRpdmV0YWxlbnQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2I5NTFmZWQ2YTdiMmNiYzIwMzY5MTZkZWM3YTQ2YzRhNTY0ODE1NjRkMTRmOTQ1YjZlYmMwMzM4Mjc2NmQzYiIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9"; + } + ItemStack skull = Utils.createSkull( + "\u00A7r\u00A76" + Utils.formatNumberWithDots(coinAmount) + " Coins", + uuid, + texture + ); + NBTTagCompound extraAttributes = skull.getTagCompound().getCompoundTag("ExtraAttributes"); + extraAttributes.setString("id", "SKYBLOCK_COIN"); + skull.getTagCompound().setTag("ExtraAttributes", extraAttributes); + return skull; } public static void appendLore(ItemStack is, List<String> moreLore) { @@ -30,4 +50,17 @@ public class ItemUtils { tagCompound.setTag("display", display); is.setTagCompound(tagCompound); } + + public static List<String> getLore(ItemStack is) { + NBTTagCompound tagCompound = is.getTagCompound(); + if (tagCompound == null) { + return Collections.emptyList(); + } + NBTTagList tagList = tagCompound.getCompoundTag("display").getTagList("Lore", 8); + List<String> list = new ArrayList<>(); + for (int i = 0; i < tagList.tagCount(); i++) { + list.add(tagList.getStringTagAt(i)); + } + return list; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java index 916631b7..b4193c88 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java @@ -5,7 +5,9 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -16,11 +18,18 @@ public class JsonUtils { return StreamSupport.stream(array.spliterator(), false); } - public static <T> List<T> transformJsonArrayToList(JsonArray array, Function<? super JsonElement, ? extends T> mapper) { + public static <T> List<T> transformJsonArrayToList( + JsonArray array, + Function<? super JsonElement, ? extends T> mapper + ) { return getJsonArrayAsStream(array).map(mapper).collect(Collectors.toList()); } - public static <T> List<T> getJsonArrayOrEmpty(JsonObject rootObject, String name, Function<? super JsonElement, ? extends T> mapper) { + public static <T> List<T> getJsonArrayOrEmpty( + JsonObject rootObject, + String name, + Function<? super JsonElement, ? extends T> mapper + ) { if (!rootObject.has(name)) { return Collections.emptyList(); } @@ -31,7 +40,10 @@ public class JsonUtils { return Collections.emptyList(); } - public static <T> JsonArray transformListToJsonArray(List<T> things, Function<? super T, ? extends JsonElement> mapper) { + public static <T> JsonArray transformListToJsonArray( + List<T> things, + Function<? super T, ? extends JsonElement> mapper + ) { JsonArray array = new JsonArray(); for (T t : things) { array.add(mapper.apply(t)); @@ -39,4 +51,15 @@ public class JsonUtils { return array; } + public static <T> Map<String, T> transformJsonObjectToMap( + JsonObject object, + Function<? super JsonElement, ? extends T> mapper + ) { + Map<String, T> map = new HashMap<>(); + for (Map.Entry<String, JsonElement> entry : object.entrySet()) { + map.put(entry.getKey(), mapper.apply(entry.getValue())); + } + return map; + } + } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java index 7b714cd0..e572a391 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java @@ -1854,8 +1854,8 @@ public class Utils { } public static boolean isWithinRect(int x, int y, int left, int top, int width, int height) { - return left <= x && x <= left + width && - top <= y && y <= top + height; + return left <= x && x < left + width && + top <= y && y < top + height; } public static int getNumberOfStars(ItemStack stack) { |