diff options
6 files changed, 196 insertions, 8 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java index 8cdf2ef0..3311f21d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java @@ -32,9 +32,9 @@ public class GUIClientPlayer extends AbstractClientPlayer { super(null, new GameProfile(UUID.randomUUID(), "GuiPlayer")); } - ResourceLocation overrideSkin = DefaultPlayerSkin.getDefaultSkinLegacy(); - ResourceLocation overrideCape = null; - boolean overrideIsSlim = false; + public ResourceLocation overrideSkin = DefaultPlayerSkin.getDefaultSkinLegacy(); + public ResourceLocation overrideCape = null; + public boolean overrideIsSlim = false; NetworkPlayerInfo playerInfo = new NetworkPlayerInfo(this.getGameProfile()) { @Override public String getSkinType() { 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 f8f42b80..93ea6127 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java @@ -19,6 +19,7 @@ package io.github.moulberry.notenoughupdates.util; +import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -36,16 +37,34 @@ import net.minecraft.nbt.NBTTagString; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.MathHelper; +import java.nio.charset.StandardCharsets; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.BiFunction; public class ItemUtils { + private static final Gson smallPrintingGson = new Gson(); + + public static ItemStack createSkullItemStack(String displayName, String uuid, String skinAbsoluteUrl) { + JsonObject object = new JsonObject(); + JsonObject textures = new JsonObject(); + JsonObject skin = new JsonObject(); + skin.addProperty("url", skinAbsoluteUrl); + textures.add("SKIN", skin); + object.add("textures", textures); + String json = smallPrintingGson.toJson(object); + return Utils.createSkull( + displayName, + uuid, + Base64.getEncoder().encodeToString(json.getBytes(StandardCharsets.UTF_8)) + ); + } public static ItemStack getCoinItemStack(double coinAmount) { String uuid = "2070f6cb-f5db-367a-acd0-64d39a7e5d1b"; @@ -187,6 +206,13 @@ public class ItemUtils { return text; } + public static NBTTagCompound getExtraAttributes(ItemStack itemStack) { + NBTTagCompound tag = getOrCreateTag(itemStack); + NBTTagCompound extraAttributes = tag.getCompoundTag("ExtraAttributes"); + tag.setTag("ExtraAttributes", extraAttributes); + return extraAttributes; + } + public static ItemStack createPetItemstackFromPetInfo(PetInfoOverlay.Pet currentPet) { if (currentPet == null) { ItemStack stack = ItemUtils.createQuestionMarkSkull(EnumChatFormatting.RED + "Unknown Pet"); diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.kt index fceacfab..9e29d248 100644 --- a/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.kt +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.kt @@ -67,7 +67,7 @@ class PackDevCommand { reply("No $name found within $dist blocks") return@thenArgumentExecute } - MiscUtils.copyToClipboard(StringBuilder().appendEntityData(entity).toString().trim()) + MiscUtils.copyToClipboard(StringBuilder().also { it.appendEntityData(entity) }.toString().trim()) reply("Copied data to clipboard") }.withHelp("Find the nearest $name and copy data about them to your clipboard") } diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/misc/FairySoulsCommand.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/misc/FairySoulsCommand.kt index 1d766646..a38ee8c9 100644 --- a/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/misc/FairySoulsCommand.kt +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/commands/misc/FairySoulsCommand.kt @@ -41,22 +41,22 @@ class FairySoulsCommand { reply("${DARK_PURPLE}Enabled fairy soul waypoints") FairySouls.getInstance().setShowFairySouls(true) }.withHelp("Show fairy soul waypoints") - thenLiteral("on") { redirect(enable) } + thenLiteral("on") { thenRedirect(enable) } val disable = thenLiteralExecute("disable") { FairySouls.getInstance().setShowFairySouls(false) reply("${DARK_PURPLE}Disabled fairy soul waypoints") }.withHelp("Hide fairy soul waypoints") - thenLiteral("off") { redirect(disable) } + thenLiteral("off") { thenRedirect(disable) } val clear = thenLiteralExecute("clear") { FairySouls.getInstance().markAllAsFound() // Reply handled by mark all as found }.withHelp("Mark all fairy souls in your current world as found") - thenLiteral("markfound") { redirect(clear) } + thenLiteral("markfound") { thenRedirect(clear) } val unclear = thenLiteralExecute("unclear") { FairySouls.getInstance().markAllAsMissing() // Reply handled by mark all as missing }.withHelp("Mark all fairy souls in your current world as not found") - thenLiteral("marknotfound") { redirect(unclear) } + thenLiteral("marknotfound") { thenRedirect(unclear) } } } } diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/recipes/generators/NPCLocationExporter.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/recipes/generators/NPCLocationExporter.kt new file mode 100644 index 00000000..7acd88a9 --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/recipes/generators/NPCLocationExporter.kt @@ -0,0 +1,153 @@ +/* + * 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.recipes.generators + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe +import io.github.moulberry.notenoughupdates.core.util.StringUtils +import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils +import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField +import io.github.moulberry.notenoughupdates.util.ItemUtils +import io.github.moulberry.notenoughupdates.util.SBInfo +import io.github.moulberry.notenoughupdates.util.Utils +import io.github.moulberry.notenoughupdates.util.kotlin.set +import net.minecraft.client.Minecraft +import net.minecraft.client.entity.AbstractClientPlayer +import net.minecraft.client.gui.GuiScreen +import net.minecraft.client.renderer.GlStateManager +import net.minecraft.entity.passive.EntityVillager +import net.minecraft.util.BlockPos +import net.minecraftforge.client.event.MouseEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.lwjgl.input.Keyboard +import java.util.* + +@NEUAutoSubscribe +class NPCLocationExporter { + class NPCNamePrompt(val uuid: UUID, val position: BlockPos, val island: String, val skinId: String) : GuiScreen() { + val nameField = GuiElementTextField("ยง9Unknown (NPC)", GuiElementTextField.COLOUR).also { + it.setSize(100, 20) + } + var name + get() = nameField.text + set(value) { + nameField.text = value + } + val id + get() = StringUtils.cleanColour(name.replace(" ", "_")) + .uppercase() + .replace("[^A-Z_0-9]".toRegex(), "") + val itemStack + get() = ItemUtils.createSkullItemStack( + name, + uuid.toString(), + "https://textures.minecraft.net/texture/$skinId" + ) + val top get() = height / 2 - 50 + val left get() = width / 2 - 100 + + override fun drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float) { + super.drawScreen(mouseX, mouseY, partialTicks) + drawDefaultBackground() + RenderUtils.drawFloatingRect(left, top, 200, 100) + nameField.render(left + 48 + 20, top + 20) + GlStateManager.pushMatrix() + GlStateManager.translate((left + 5).toDouble(), (top + 5).toDouble(), 0.0) + GlStateManager.scale(3.0, 3.0, 1.0) + GlStateManager.translate(8F, 8F, 0F) + + GlStateManager.rotate(((System.currentTimeMillis() / 5000.0) % 1 * 360).toFloat(), 0F, 0F, 1F) + Utils.drawItemStack(itemStack, -8, -8, false) + GlStateManager.popMatrix() + } + + fun save() { + val itemStack = this.itemStack + ItemUtils.getExtraAttributes(itemStack).setString("id", id) + val json = NotEnoughUpdates.INSTANCE.manager.getJsonForItem(itemStack) + json["internalname"] = id + json["clickcommand"] = "" + json["modver"] = NotEnoughUpdates.VERSION + json["x"] = position.x + json["y"] = position.y + 1 + json["z"] = position.z + json["island"] = island + NotEnoughUpdates.INSTANCE.manager.writeJsonDefaultDir(json, "$id.json") + Utils.addChatMessage("Saved to file") + Minecraft.getMinecraft().displayGuiScreen(null) + } + + override fun keyTyped(typedChar: Char, keyCode: Int) { + super.keyTyped(typedChar, keyCode) + if (keyCode == Keyboard.KEY_RETURN) { + save() + } + nameField.keyTyped(typedChar, keyCode) + } + + override fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) { + super.mouseClicked(mouseX, mouseY, mouseButton) + val mouseX = Utils.getMouseX() + val mouseY = Utils.getMouseY() + if (mouseX - left - 48 - 20 in 0..nameField.width && + mouseY - top - 20 in 0..nameField.height + ) { + nameField.mouseClicked(mouseX, mouseY, mouseButton) + } else { + nameField.otherComponentClick() + } + } + } + + @SubscribeEvent + fun onMouseClick(event: MouseEvent) { + if (event.buttonstate || event.button != 2 || !NotEnoughUpdates.INSTANCE.config.apiData.repositoryEditing) return + val pointedEntity = Minecraft.getMinecraft().pointedEntity + if (pointedEntity == null) { + Utils.addChatMessage("Could not find entity under cursor") + return + } + if (pointedEntity is EntityVillager) { + Minecraft.getMinecraft().displayGuiScreen( + NPCNamePrompt( + // Just use jerry pet skin, idk, this will probably cause texture packs to overwrite us, but uhhhhh uhhhhhhh + UUID.fromString("c9540683-51e4-3942-ad17-4f2c3f3ae4b7"), + pointedEntity.position, + SBInfo.getInstance().getLocation(), + "822d8e751c8f2fd4c8942c44bdb2f5ca4d8ae8e575ed3eb34c18a86e93b" + ) + ) + return + } + if (pointedEntity !is AbstractClientPlayer) { + Utils.addChatMessage("Entity under cursor is not a player") + return + } + val uuid = pointedEntity.uniqueID + val position = pointedEntity.position + val island = SBInfo.getInstance().getLocation() + val skin = pointedEntity.locationSkin.resourcePath?.replace("skins/", "") + if (skin == null) { + Utils.addChatMessage("Could not load skin") + return + } + Minecraft.getMinecraft().displayGuiScreen(NPCNamePrompt(uuid, position, island, skin)) + } +} diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/brigadier/dsl.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/brigadier/dsl.kt index 17203a4b..1ce00d99 100644 --- a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/brigadier/dsl.kt +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/brigadier/dsl.kt @@ -136,6 +136,15 @@ fun <T : ArgumentBuilder<DefaultSource, T>> T.thenLiteralExecute( thenExecute(block) } +fun <T : ArgumentBuilder<DefaultSource, T>> T.thenRedirect(node: CommandNode<DefaultSource>): T { + node.children.forEach { + this.then(it) + } + forward(node.redirect, node.redirectModifier, node.isFork) + executes(node.command) + return this +} + fun <T : ArgumentBuilder<DefaultSource, T>, U : ArgumentBuilder<DefaultSource, U>> T.then( node: U, block: U.() -> Unit |