diff options
Diffstat (limited to 'mod')
699 files changed, 56931 insertions, 0 deletions
diff --git a/mod/build.gradle b/mod/build.gradle new file mode 100644 index 00000000..bae9614d --- /dev/null +++ b/mod/build.gradle @@ -0,0 +1,85 @@ +buildscript { + repositories { + gradlePluginPortal() + mavenCentral() + maven { + name = "forge" + url = "https://maven.minecraftforge.net/" + } + maven { url "https://jitpack.io" } + } + dependencies { + classpath "com.github.Skytils:ForgeGradle:6f5327" + classpath "com.github.jengelman.gradle.plugins:shadow:6.1.0" + } + +} +apply plugin: "net.minecraftforge.gradle.forge" +apply plugin: "com.github.johnrengelman.shadow" +apply plugin: "java" + +version = "3.0" +group = "kr.syeyoung.dungeonsguide" +archivesBaseName = "dungeonsguide" + +sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8 + +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} + +minecraft { + version = "1.8.9-11.15.1.2318-1.8.9" + runDir = "run" + + mappings = "stable_22" + makeObfSourceJar = false +} + +repositories { + mavenCentral() + maven { url "https://jitpack.io" } +} +dependencies { + implementation "org.jetbrains:annotations-java5:19.0.0" + implementation "org.java-websocket:Java-WebSocket:1.5.1" + implementation "org.json:json:20171018" + implementation "com.twelvemonkeys.imageio:imageio-bmp:3.7.0" + + compileOnly project(':wrapper') + + + compileOnly "org.projectlombok:lombok:1.18.20" + compileOnly files("mods/Hychat-1.12.1-BETA.jar") + annotationProcessor "org.projectlombok:lombok:1.18.16" + + testCompileOnly "org.projectlombok:lombok:1.18.20" + testAnnotationProcessor "org.projectlombok:lombok:1.18.20" +} + +shadowJar { + + archiveFileName = jar.archiveFileName + + relocate "org.java_websocket", "kr.syeyoung.org.java_websocket" + + dependencies { + include(dependency("org.java-websocket:Java-WebSocket:1.5.1")) + include(dependency("org.slf4j:slf4j-api:1.7.25")) + include(dependency("org.json:json:20171018")) + include(dependency("com.twelvemonkeys..*:.*")) + } +} + +reobf { + shadowJar { + mappingType = "SEARGE" + } +} + +processResources { + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude "mcmod.info" + } +}
\ No newline at end of file diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java new file mode 100755 index 00000000..5ec5b95a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java @@ -0,0 +1,241 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.commands.CommandDungeonsGuide; +import kr.syeyoung.dungeonsguide.commands.CommandReparty; +import kr.syeyoung.dungeonsguide.launcher.authentication.Authenticator; +import kr.syeyoung.dungeonsguide.launcher.DGInterface; +import kr.syeyoung.dungeonsguide.launcher.Main; +import kr.syeyoung.dungeonsguide.chat.ChatProcessor; +import kr.syeyoung.dungeonsguide.chat.PartyManager; +import kr.syeyoung.dungeonsguide.config.Config; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticsManager; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoomInfoRegistry; +import kr.syeyoung.dungeonsguide.eventlistener.DungeonListener; +import kr.syeyoung.dungeonsguide.eventlistener.FeatureListener; +import kr.syeyoung.dungeonsguide.eventlistener.PacketListener; +import kr.syeyoung.dungeonsguide.events.StompConnectedEvent; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.resources.DGTexturePack; +import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager; +import kr.syeyoung.dungeonsguide.stomp.CloseListener; +import kr.syeyoung.dungeonsguide.stomp.StompClient; +import kr.syeyoung.dungeonsguide.stomp.StompInterface; +import kr.syeyoung.dungeonsguide.utils.AhUtils; +import kr.syeyoung.dungeonsguide.utils.TimeScoreUtil; +import kr.syeyoung.dungeonsguide.utils.cursor.GLCursors; +import kr.syeyoung.dungeonsguide.wsresource.StaticResourceCache; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.IReloadableResourceManager; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourcePack; +import net.minecraft.launchwrapper.LaunchClassLoader; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.client.ClientCommandHandler; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.ProgressManager; +import net.minecraftforge.fml.relauncher.ReflectionHelper; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.io.*; +import java.net.URI; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class DungeonsGuide implements DGInterface, CloseListener { + + private SkyblockStatus skyblockStatus; + + private static DungeonsGuide dungeonsGuide; + + @Getter + private final Authenticator authenticator; + + @Getter + private StompInterface stompConnection; + @Getter + private CosmeticsManager cosmeticsManager; + + public DungeonsGuide(Authenticator authenticator) { + this.authenticator = authenticator; + } + + public static void sendDebugChat(IChatComponent iChatComponent) { + if (FeatureRegistry.DEBUG.isEnabled()) + Minecraft.getMinecraft().thePlayer.addChatMessage(iChatComponent); + } + @Getter + CommandReparty commandReparty; + CommandDungeonsGuide commandDungeonsGuide; + + + private final String stompURL = "wss://dungeons.guide/ws"; +// private String stompURL = "ws://localhost/ws"; + public void init(File resourceDir) { + ProgressManager.ProgressBar progressbar = ProgressManager.push("DungeonsGuide", 4); + + configDir = new File(resourceDir,"dungeonsguide"); + File configFile = new File(configDir, "config.json"); + if (!configFile.exists()) { + configDir.mkdirs(); + firstTimeUsingDG = true; + } + Config.f = configFile; + Minecraft.getMinecraft().getFramebuffer().enableStencil(); + + + try { + List<IResourcePack> resourcePackList = ReflectionHelper.getPrivateValue(Minecraft.class, Minecraft.getMinecraft(),"defaultResourcePacks", "aA", "field_110449_ao"); + resourcePackList.add(new DGTexturePack(authenticator)); + Minecraft.getMinecraft().refreshResources(); + } catch (Throwable t){ + t.printStackTrace(); + } + + + try { + Set<String> invalid = ReflectionHelper.getPrivateValue(LaunchClassLoader.class, (LaunchClassLoader) Main.class.getClassLoader(), "invalidClasses"); + ((LaunchClassLoader) Main.class.getClassLoader()).clearNegativeEntries(Sets.newHashSet("org.slf4j.LoggerFactory")); + invalid.clear(); + } catch (Throwable t) { + t.printStackTrace(); + } + + progressbar.step("Registering Events & Commands"); + dungeonsGuide = this; + skyblockStatus = new SkyblockStatus(); + + registerEvents(new DungeonListener()); + ClientCommandHandler.instance.registerCommand(commandDungeonsGuide = new CommandDungeonsGuide()); + registerEvents(commandDungeonsGuide); + + commandReparty = new CommandReparty(); + registerEvents(commandReparty); + + registerEvents(new FeatureListener()); + registerEvents(new PacketListener()); + registerEvents(new Keybinds()); + + registerEvents(ChatProcessor.INSTANCE); + registerEvents(PartyManager.INSTANCE); + registerEvents(StaticResourceCache.INSTANCE); + + AhUtils.registerTimer(); + + progressbar.step("Loading Roomdatas"); + try { + DungeonRoomInfoRegistry.loadAll(configDir); + } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | IOException | NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } + progressbar.step("Opening connection"); + + cosmeticsManager = new CosmeticsManager(); + registerEvents(cosmeticsManager); + + try { + connectStomp(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + + progressbar.step("Loading Config"); + try { + Config.loadConfig( null ); + } catch (IOException e) { + e.printStackTrace(); + } + + if (FeatureRegistry.ETC_REPARTY.isEnabled()) + ClientCommandHandler.instance.registerCommand(commandReparty); + if (FeatureRegistry.DISCORD_DONOTUSE.isEnabled()) + System.setProperty("dg.safe", "true"); + registerEvents(RichPresenceManager.INSTANCE); + TimeScoreUtil.init(); + + ProgressManager.pop(progressbar); + + ((IReloadableResourceManager)Minecraft.getMinecraft().getResourceManager()).registerReloadListener(resourceManager -> GLCursors.setupCursors()); + } + @Getter + private boolean firstTimeUsingDG = false; + private List<Object> listeners = new ArrayList<>(); + + private void registerEvents(Object obj) { + listeners.add(obj); + registerEvents(obj); + } + + @Override + public void onResourceReload(IResourceManager a) { + GLCursors.setupCursors(); + } + + @Override + public void unload() { + ClientCommandHandler.instance.getCommands().remove(commandReparty.getCommandName()); + ClientCommandHandler.instance.getCommands().remove(commandDungeonsGuide.getCommandName()); + listeners.forEach(MinecraftForge.EVENT_BUS::unregister); + stompConnection.disconnect(); + List<IResourcePack> resourcePackList = ReflectionHelper.getPrivateValue(Minecraft.class, Minecraft.getMinecraft(),"defaultResourcePacks", "aA", "field_110449_ao"); + resourcePackList.removeIf(a -> a instanceof DGTexturePack); + } + + @Getter + private File configDir; + + + public SkyblockStatus getSkyblockStatus() { + return skyblockStatus; + } + + public static DungeonsGuide getDungeonsGuide() { + return dungeonsGuide; + } + ScheduledExecutorService ex = Executors.newScheduledThreadPool(2); + @Override + public void onClose(int code, String reason, boolean remote) { + System.out.println("Stomp Connection closed, trying to reconnect - "+reason+ " - "+code); + connectStomp(); + } + + public void connectStomp() { + ex.schedule(() -> { + try { + stompConnection = new StompClient(new URI(stompURL), authenticator.getUnexpiredToken(), DungeonsGuide.this); + MinecraftForge.EVENT_BUS.post(new StompConnectedEvent(stompConnection)); + } catch (Exception e) { + e.printStackTrace(); + } + }, 5L, TimeUnit.SECONDS); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/Keybinds.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/Keybinds.java new file mode 100755 index 00000000..8b65c27f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/Keybinds.java @@ -0,0 +1,47 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide; + +import kr.syeyoung.dungeonsguide.events.KeyBindPressedEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; + +public class Keybinds +{ + + @SubscribeEvent + public void onTogglePathfindStatus(InputEvent.KeyInputEvent keyInputEvent) { + if (Keyboard.getEventKeyState()) { + int key = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey(); + KeyBindPressedEvent keyBindPressedEvent = new KeyBindPressedEvent(key); + MinecraftForge.EVENT_BUS.post(keyBindPressedEvent); + } + } + @SubscribeEvent + public void onMousePressed(InputEvent.MouseInputEvent mouseInputEvent) { + if (Mouse.getEventButtonState()) { + int key = Mouse.getEventButton() - 100; + KeyBindPressedEvent keyBindPressedEvent = new KeyBindPressedEvent(key); + MinecraftForge.EVENT_BUS.post(keyBindPressedEvent); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/SkyblockStatus.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/SkyblockStatus.java new file mode 100755 index 00000000..516e1eaf --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/SkyblockStatus.java @@ -0,0 +1,109 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.scoreboard.*; + +import java.util.Collection; +import java.util.Set; + +public class SkyblockStatus { + @Getter + private boolean isOnSkyblock; + private boolean isOnDungeon; + + public boolean isOnDungeon() { + return forceIsOnDungeon || isOnDungeon; + } + + @Getter @Setter + private boolean forceIsOnDungeon; + + @Getter + @Setter + private DungeonContext context; + + @Getter + @Setter + private int percentage; + + @Getter @Setter + private String dungeonName; + + public boolean isOnHypixel() { + Minecraft mc = Minecraft.getMinecraft(); + if (mc == null || mc.thePlayer == null) return false; + if (!mc.isSingleplayer() && mc.thePlayer.getClientBrand() != null) { + return mc.thePlayer.getClientBrand().startsWith("Hypixel BungeeCord"); + } + return false; + } + + private static final Set<String> SKYBLOCK_IN_ALL_LANGUAGES = Sets.newHashSet("SKYBLOCK"); + + public void updateStatus() { + if (!isOnHypixel()) { + isOnDungeon = false; + isOnSkyblock = false; + return; + } + + Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard(); + ScoreObjective scoreObjective = scoreboard.getObjectiveInDisplaySlot(1); + if (scoreObjective == null) return; + + String objectiveName = TextUtils.stripColor(scoreObjective.getDisplayName()); + boolean skyblockFound = false; + for (String skyblock : SKYBLOCK_IN_ALL_LANGUAGES) { + if (objectiveName.startsWith(skyblock)) { + skyblockFound = true; + isOnSkyblock = true; + break; + } + } + + if (!skyblockFound) { + isOnSkyblock = false; + isOnDungeon = false; + return; + } + + Collection<Score> scores = scoreboard.getSortedScores(scoreObjective); + boolean foundDungeon = false; + for (Score sc:scores) { + ScorePlayerTeam scorePlayerTeam = scoreboard.getPlayersTeam(sc.getPlayerName()); + String strippedLine = TextUtils.keepScoreboardCharacters(TextUtils.stripColor(ScorePlayerTeam.formatPlayerName(scorePlayerTeam, sc.getPlayerName()))).trim(); + if (strippedLine.contains("Cleared: ")) { + foundDungeon = true; + percentage = Integer.parseInt(strippedLine.substring(9).split(" ")[0]); + } + if (ScorePlayerTeam.formatPlayerName(scorePlayerTeam, sc.getPlayerName()).startsWith(" §7⏣")) { + dungeonName = strippedLine.trim(); + } + } + + isOnDungeon = foundDungeon; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessResult.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessResult.java new file mode 100644 index 00000000..94bafa95 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessResult.java @@ -0,0 +1,31 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.chat; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum ChatProcessResult { + NONE(false, false), REMOVE_LISTENER(true, false), REMOVE_LISTENER_AND_CHAT(true, true), REMOVE_CHAT(false, true); + + private boolean removeListener; + private boolean removeChat; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessor.java new file mode 100644 index 00000000..e781ffef --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessor.java @@ -0,0 +1,114 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.chat; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiNewChat; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.Tuple; +import net.minecraftforge.client.event.ClientChatReceivedEvent; +import net.minecraftforge.fml.common.eventhandler.Event; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.simple.SimpleLogger; + +import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class ChatProcessor { + public static final ChatProcessor INSTANCE = new ChatProcessor(); + + private static final Logger logger = LogManager.getLogger(); + private ChatProcessor() { + Logger l = LogManager.getLogger(GuiNewChat.class); + if (l instanceof SimpleLogger) { + ((SimpleLogger) l).setLevel(Level.OFF); + } else if (l instanceof org.apache.logging.log4j.core.Logger) { + ((org.apache.logging.log4j.core.Logger) l).setLevel(Level.OFF); + } + } + + private Queue<ChatSubscriber> chatSubscriberQueue = new ConcurrentLinkedQueue<>(); + private Queue<Tuple<String, Runnable>> chatQueue = new ConcurrentLinkedQueue<>(); + + public void subscribe(ChatSubscriber chatSubscribed) { + chatSubscriberQueue.add(chatSubscribed); + } + public void addToChatQueue(String chat, Runnable onSend, boolean noDupe) { + if (noDupe && chatQueue.stream().anyMatch(a -> a.getFirst().trim().equalsIgnoreCase(chat.trim()))) return; + chatQueue.add(new Tuple<>(chat, onSend)); + } + + + private long minimumNext = 0; + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent clientTickEvent) { + try { + if (clientTickEvent.phase == TickEvent.Phase.START && Minecraft.getMinecraft().thePlayer != null && minimumNext < System.currentTimeMillis()) { + if (!chatQueue.isEmpty()) { + Tuple<String, Runnable> tuple = chatQueue.poll(); + Minecraft.getMinecraft().thePlayer.sendChatMessage(tuple.getFirst()); + if (tuple.getSecond() != null) + tuple.getSecond().run(); + minimumNext = System.currentTimeMillis() + 200; + DungeonsGuide.sendDebugChat(new ChatComponentText("Sending " + tuple.getFirst() + " Secretly")); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + + @SubscribeEvent(priority = EventPriority.HIGHEST, receiveCanceled = true) + public void onMessage(ClientChatReceivedEvent chatReceivedEvent) { + if (chatReceivedEvent.type == 2) return; + String txt = chatReceivedEvent.message.getFormattedText(); + logger.log(Level.INFO, "[CHAT] "+txt); + + int processed = 0; + int listenened = 0; + Map<String, Object> context = new HashMap<>(); + Iterator<ChatSubscriber> it = chatSubscriberQueue.iterator(); + while (it.hasNext()) { + ChatSubscriber chatSubscribed = it.next(); + context.put("removed", processed); + context.put("onceListenered", listenened); + ChatProcessResult chatProcessResult = chatSubscribed.process(txt, context); + if (chatProcessResult.isRemoveChat()) processed++; + if (chatProcessResult.isRemoveListener()) listenened++; + + if (chatProcessResult.isRemoveChat()) chatReceivedEvent.setResult(Event.Result.DENY); + if (chatProcessResult.isRemoveListener()) it.remove(); + } + } + + + @SubscribeEvent(priority = EventPriority.LOWEST) + public void cancelMessage(ClientChatReceivedEvent chatReceivedEvent) { + if (chatReceivedEvent.getResult() == Event.Result.DENY) + chatReceivedEvent.setCanceled(true); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatSubscriber.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatSubscriber.java new file mode 100644 index 00000000..72879eb0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatSubscriber.java @@ -0,0 +1,26 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.chat; + +import java.util.Map; + +@FunctionalInterface +public interface ChatSubscriber { + ChatProcessResult process(String txt, Map<String, Object> context); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyContext.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyContext.java new file mode 100644 index 00000000..87d1a264 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyContext.java @@ -0,0 +1,89 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.chat; + +import lombok.Data; +import net.minecraft.client.Minecraft; + +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; + + +@Data +public class PartyContext { + private String partyID; + + private String partyOwner; + private Set<String> partyModerator; private boolean isModeratorComplete; + private Set<String> partyMember; private boolean isMemberComplete; + + private Set<String> partyRawMembers = new HashSet<>(); private boolean isRawMemberComplete; + + private Boolean allInvite; + + private boolean partyExistHypixel = true; + + public void setPartyOwner(String partyOwner) { + this.partyOwner = partyOwner; + if (partyMember != null) partyMember.remove(partyOwner); + if (partyModerator != null) partyModerator.remove(partyOwner); + addRawMember(partyOwner); + } + public void addPartyModerator(String partyModerator) { + if (partyModerator.equalsIgnoreCase(partyOwner)) partyOwner = null; + if (partyMember != null) partyMember.remove(partyModerator); + + if (this.partyModerator == null) this.partyModerator = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + this.partyModerator.add(partyModerator); + addRawMember(partyModerator); + } + public void addPartyMember(String partyMember) { + if (partyMember.equalsIgnoreCase(partyOwner)) partyOwner = null; + if (partyModerator != null) partyModerator.remove(partyMember); + + if (this.partyMember == null) this.partyMember = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + this.partyMember.add(partyMember); + addRawMember(partyMember); + } + public void addRawMember(String partyMember){ + partyRawMembers.add(partyMember); + } + public void removeFromParty(String username) { + if (username.equalsIgnoreCase(partyOwner)) { + partyOwner = null; + } + if (partyModerator != null) partyModerator.remove(username); + if (partyMember != null) partyMember.remove(username); + partyRawMembers.remove(username); + } + + public boolean hasModerator(String username) { + return partyModerator != null && partyModerator.contains(username); + } + public boolean hasMember(String username) { + return partyMember != null && partyMember.contains(username); + } + public boolean hasLeader(String username) { + return username.equalsIgnoreCase(partyOwner); + } + public boolean isSelfSolo() { + return hasLeader(Minecraft.getMinecraft().getSession().getUsername()) && getPartyRawMembers().size() == 1; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyManager.java new file mode 100644 index 00000000..f1a40098 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyManager.java @@ -0,0 +1,604 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.chat; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.events.HypixelJoinedEvent; +import kr.syeyoung.dungeonsguide.events.StompConnectedEvent; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ChatComponentText; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.security.SecureRandom; +import java.util.*; +import java.util.function.Consumer; + +public class PartyManager implements StompMessageHandler { + public static final PartyManager INSTANCE = new PartyManager(); + @Getter + private PartyContext partyContext; + + public PartyContext getPartyContext(boolean createIfNeeded) { + PartyContext pc = partyContext == null && createIfNeeded ? partyContext = new PartyContext() : partyContext; + if (createIfNeeded) + pc.addRawMember(Minecraft.getMinecraft().getSession().getUsername()); + return pc; + } + + @Getter + @Setter + private int maxParty = 5; + @Getter + private String askToJoinSecret = null; + + private static final SecureRandom random = new SecureRandom(); + private static final String validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; + + + private Set<Consumer<PartyContext>> partyBuiltCallback = new HashSet<>(); + + public PartyManager() { + ChatProcessor cp = ChatProcessor.INSTANCE; + // Not in Party + cp.subscribe((str, a) -> { + if (str.equals("§cYou are not currently in a party.§r") + || str.equals("§eYou left the party.§r") + || str.equals("§cYou must be in a party to join the party channel!§r") + || str.equals("§cThe party was disbanded because all invites expired and the party was empty§r") + || str.equals("§cYou are not in a party and were moved to the ALL channel.§r") + || str.startsWith("§cThe party was disbanded") + || str.endsWith("§ehas disbanded the party!§r") + || str.startsWith("§cYou are not in a party") + || str.startsWith("§eYou have been kicked from the party by ")) { + leaveParty(); + + for (Consumer<PartyContext> partyContextConsumer : partyBuiltCallback) { + try { + partyContextConsumer.accept(null); + } catch (Exception e) { + e.printStackTrace(); + } + } + partyBuiltCallback.clear(); + a.put("type", "notinparty"); + } + return ChatProcessResult.NONE; + }); + // All invite + cp.subscribe((str, a) -> { + if (str.endsWith("§aenabled All Invite§r")) { + getPartyContext(true).setAllInvite(true); + a.put("type", "allinvite_on"); + } else if (str.endsWith("§cdisabled All Invite§r") + || str.equals("§cYou are not allowed to invite players.§r")) { + getPartyContext(true).setAllInvite(false); + a.put("type", "allinvite_off"); + potentialInvitenessChange(); + } + return ChatProcessResult.NONE; + }); + // Member building + cp.subscribe(new ChatSubscriber() { + boolean memberExpected; + PartyContext partyContext = new PartyContext(); + @Override + public ChatProcessResult process(String txt, Map<String, Object> context) { + if (txt.startsWith("§6Party Members ")) { + memberExpected = true; + partyContext = new PartyContext(); + partyContext.setPartyModerator(new TreeSet<>(String.CASE_INSENSITIVE_ORDER)); + partyContext.setPartyMember(new TreeSet<>(String.CASE_INSENSITIVE_ORDER)); + context.put("type", "member_start"); + } else if (txt.startsWith("§eParty ") && txt.contains(":")){ + String role = txt.split(":")[0]; + String playerNames = TextUtils.stripColor(txt.split(":")[1]); + for (String s : playerNames.split(" ")) { + if (s.isEmpty()) continue; + if (s.equals("●")) continue; + if (s.startsWith("[")) continue; + partyContext.addRawMember(s); + if (role.contains("Moder")) partyContext.addPartyModerator(s); + if (role.contains("Member")) partyContext.addPartyMember(s); + if (role.contains("Leader")) partyContext.setPartyOwner(s); + } + if (role.contains("Moder")) { + partyContext.setModeratorComplete(true); + context.put("type", "member_moder"); + } + if (role.contains("Member")) { + partyContext.setMemberComplete(true); + context.put("type", "member_member"); + } + if (role.contains("Leader")) { + context.put("type", "member_leader"); + } + } else if (txt.startsWith("§9§m---------------------------")) { + if (memberExpected) { + PartyContext old = getPartyContext(true); + old.setPartyOwner(partyContext.getPartyOwner()); + old.setPartyModerator(partyContext.getPartyModerator()); + old.setPartyMember(partyContext.getPartyMember()); + old.setPartyRawMembers(new TreeSet<>(String.CASE_INSENSITIVE_ORDER)); + old.getPartyRawMembers().addAll(old.getPartyMember()); + old.getPartyRawMembers().addAll(old.getPartyModerator()); + old.getPartyRawMembers().add(old.getPartyOwner()); + old.setModeratorComplete(true); old.setMemberComplete(true); + old.setRawMemberComplete(true); + old.setPartyExistHypixel(true); + + memberExpected = false; + context.put("type", "member_end"); + + for (Consumer<PartyContext> partyContextConsumer : partyBuiltCallback) { + try { + partyContextConsumer.accept(partyContext); + } catch (Exception e) { + e.printStackTrace(); + } + } + partyBuiltCallback.clear(); + + if (old.getPartyID() == null) { + joinedParty(); + } + potentialInvitenessChange(); + } + } + return ChatProcessResult.NONE; + } + }); + // Player party join / leave + cp.subscribe((str ,a) -> { + if (str.endsWith("§ejoined the party.§r")) { + String username = null; + for (String s : TextUtils.stripColor(str).split(" ")) { + if (s.startsWith("[")) continue; + username = s; + break; + } + if (username != null) { + getPartyContext(true).addPartyMember(username); + } + a.put("type", "party_join"); + } else if (str.endsWith("§ehas been removed from the party.§r") + || str.endsWith("§ehas left the party.§r")) { + String username = null; + for (String s : TextUtils.stripColor(str).split(" ")) { + if (s.startsWith("[")) continue; + username = s; + break; + } + if (username != null && partyContext != null) { + getPartyContext().removeFromParty(username); + } + a.put("type", "party_leave"); + } else if (str.endsWith(" They have §r§c60 §r§eseconds to accept.§r")) { + String[] messageSplit = TextUtils.stripColor(str).split(" "); + String inviter = null; + for (String s : messageSplit) { + if (s.startsWith("[")) continue; + inviter = s; + break; + } + if (inviter != null && partyContext != null) { + if (getPartyContext().hasMember(inviter)) { + getPartyContext().setAllInvite(true); + } + } + getPartyContext(true).setPartyExistHypixel(true); + a.put("type", "party_invite_exist"); + } else if (str.equals("§cCouldn't find a player with that name!§r") || str.equals("§cYou cannot invite that player since they're not online.")) { + a.put("type", "party_invite_noexist"); + String username = Minecraft.getMinecraft().getSession().getUsername(); + if (partyContext != null && getPartyContext().hasMember(username)) { + getPartyContext().setAllInvite(true); + } + } + return ChatProcessResult.NONE; + }); + // Promotion + cp.subscribe((str, a) -> { + if (str.startsWith("§eThe party was transferred to ")) { + // §eThe party was transferred to §r§b[MVP§r§f+§r§b] apotato321 §r§eby §r§a[VIP§r§6+§r§a] syeyoung§r + String[] messageSplit = TextUtils.stripColor(str.substring(31)).split(" "); + String newLeader = null; + for (String s : messageSplit) { + if (s.startsWith("[")) continue; + newLeader = s; + break; + } + String oldLeader; + boolean left= false; + if (str.endsWith("§r§eleft§r")) { + oldLeader = messageSplit[messageSplit.length-2]; + left = true; + } else { + oldLeader = messageSplit[messageSplit.length-1]; + } + + if (oldLeader != null && newLeader != null ) { + getPartyContext(true).setPartyOwner(newLeader); + if (left) + getPartyContext(true).removeFromParty(oldLeader); + else + getPartyContext(true).addPartyModerator(oldLeader); + } + a.put("type", "party_transfer"); + potentialInvitenessChange(); + } else if (str.endsWith("§eto Party Leader§r")) { + // §a[VIP§r§6+§r§a] syeyoung§r§e has promoted §r§b[MVP§r§f+§r§b] apotato321 §r§eto Party Leader§r + String[] messageSplit = TextUtils.stripColor(str).split(" "); + String oldLeader = null; + for (String s : messageSplit) { + if (s.startsWith("[")) continue; + oldLeader = s; + break; + } + messageSplit = TextUtils.stripColor(str.substring(str.indexOf("has promoted") + 13)).split(" "); + String newLeader = null; + for (String s : messageSplit) { + if (s.startsWith("[")) continue; + newLeader = s; + break; + } + + if (oldLeader != null && newLeader != null) { + getPartyContext(true).setPartyOwner(newLeader); + getPartyContext(true).addPartyModerator(oldLeader); + } + a.put("type", "party_transfer"); + potentialInvitenessChange(); + } else if (str.endsWith("§r§eto Party Moderator§r")) { + // §b[MVP§r§f+§r§b] apotato321§r§e has promoted §r§a[VIP§r§6+§r§a] syeyoung §r§eto Party Moderator§r + String[] messageSplit = TextUtils.stripColor(str).split(" "); + String oldLeader = null; + for (String s : messageSplit) { + if (s.startsWith("[")) continue; + oldLeader = s; + break; + } + messageSplit = TextUtils.stripColor(str.substring(str.indexOf("has promoted") + 13)).split(" "); + String newModerator = null; + for (String s : messageSplit) { + if (s.startsWith("[")) continue; + newModerator = s; + break; + } + + if (oldLeader != null && newModerator != null) { + getPartyContext(true).setPartyOwner(oldLeader); + getPartyContext(true).addPartyModerator(newModerator); + } + a.put("type", "party_promotion"); + potentialInvitenessChange(); + } else if (str.endsWith("§r§eto Party Member§r")) { + String[] messageSplit = TextUtils.stripColor(str).split(" "); + String oldLeader = null; + for (String s : messageSplit) { + if (s.startsWith("[")) continue; + oldLeader = s; + break; + } + messageSplit = TextUtils.stripColor(str.substring(str.indexOf("has demoted") + 12)).split(" "); + String newMember = null; + for (String s : messageSplit) { + if (s.startsWith("[")) continue; + newMember = s; + break; + } + + if (oldLeader != null && newMember != null) { + getPartyContext(true).setPartyOwner(oldLeader); + getPartyContext(true).addPartyMember(newMember); + } + a.put("type", "party_demotion"); + potentialInvitenessChange(); + } + return ChatProcessResult.NONE; + }); + // Player Join + cp.subscribe(new ChatSubscriber() { + boolean joined; + @Override + public ChatProcessResult process(String str, Map<String, Object> context) { + if (str.startsWith("§eYou have joined ")) { + String[] messageSplit = TextUtils.stripColor(str.substring(18)).split(" "); + String leader = null; + for (String s : messageSplit) { + if (s.startsWith("[")) continue; + leader = s; + break; + } + leader = leader.substring(0, leader.length()-2); // remove 's + partyContext = new PartyContext(); + getPartyContext().setPartyOwner(leader); + getPartyContext().addPartyMember(Minecraft.getMinecraft().getSession().getUsername()); + context.put("type", "party_selfjoin_leader"); + joined= true; + } else if (str.startsWith("§eYou'll be partying with: ")) { + String[] players = TextUtils.stripColor(str.substring(27)).split(" "); + for (String player : players) { + if (player.startsWith("[")) continue; + getPartyContext().addRawMember(player); + } + context.put("type", "party_selfjoin_players"); + } else if (str.startsWith("§9§m---------------------------") && joined) { + joined = false; + getPartyContext().setRawMemberComplete(true); + joinedParty(); + potentialInvitenessChange(); + } + return ChatProcessResult.NONE; + }}); + // Player Join Dungon + cp.subscribe((str, a)-> { + if (str.contains("§r§ejoined the dungeon group! (§r§b")) { + String username = TextUtils.stripColor(str).split(" ")[3]; + if (username.equalsIgnoreCase(Minecraft.getMinecraft().getSession().getUsername())) { + partyContext = new PartyContext(); + requestPartyList((str2) -> { + potentialInvitenessChange(); + }); + } else { + getPartyContext(true).setMemberComplete(false); + requestPartyList((str2) -> {}); + } + } + return ChatProcessResult.NONE; + }); + } + + public void toggleAllowAskToJoin() { + if (canInvite()) { + if (askToJoinSecret != null) askToJoinSecret = null; + else { + updateAskToJoin(); + } + } + } + + public void updateAskToJoin() { + StringBuilder secretBuilder = new StringBuilder(); + for (int i = 0; i < 20; i++) { + secretBuilder.append(validChars.charAt(random.nextInt(validChars.length()))); + } + askToJoinSecret = secretBuilder.toString(); + + StompInterface stompInterface = DungeonsGuide.getDungeonsGuide().getStompConnection(); + stompInterface.send(new StompPayload().payload(new JSONObject().put("secret", askToJoinSecret).toString()).header("destination", "/app/party.setjoinsecret")); + } + + public static ChatSubscriber dashShredder() { + return (str, a) -> (int)a.get("removed") == 0 && str.startsWith("§9§m---------------------------") ? ChatProcessResult.REMOVE_LISTENER_AND_CHAT : ChatProcessResult.NONE; + } + + public static ChatSubscriber typeShredder(boolean end, String... types) { + return (str, a) -> (int)a.get("removed") == 0 &&Arrays.stream(types).anyMatch(s -> s.equals(a.getOrDefault("type", null))) ? (end ? ChatProcessResult.REMOVE_LISTENER_AND_CHAT : ChatProcessResult.REMOVE_CHAT) : ChatProcessResult.NONE; + } + + public static ChatSubscriber combinedShredder(ChatSubscriber... chatSubscribers) { + return (str, a) -> { + boolean removeChat = false; + boolean removeListener = false; + for (ChatSubscriber chatSubscriber : chatSubscribers) { + ChatProcessResult chatProcessResult = chatSubscriber.process(str, a); + if (chatProcessResult.isRemoveChat()) removeChat = true; + if (chatProcessResult.isRemoveListener()) removeListener = true; + } + return (removeChat && removeListener) ? ChatProcessResult.REMOVE_LISTENER_AND_CHAT : (removeChat ? ChatProcessResult.REMOVE_CHAT : (removeListener ? ChatProcessResult.REMOVE_LISTENER : ChatProcessResult.NONE)); + }; + } + + @SubscribeEvent + public void onHypixelJoin(HypixelJoinedEvent skyblockJoinedEvent) { + partyContext = null; + requestPartyList((a) -> { + if (a == null) return; + if (isLeader() || isModerator()) return; + if (a.getAllInvite() != null) return; + requestAllInvite(); + }); + } + + private void leaveParty() { + if (partyContext != null) { + getPartyContext().setPartyExistHypixel(false); + if (getPartyContext().isSelfSolo()) return; + if (getPartyContext().getPartyID() != null) { + JSONObject object = new JSONObject(); + object.put("partyid", getPartyContext().getPartyID()); + StompInterface stompInterface = DungeonsGuide.getDungeonsGuide().getStompConnection(); + stompInterface.send(new StompPayload().payload(object.toString()).header("destination", "/app/party.leave")); + } + } + + partyContext = new PartyContext(); + playerInvAntiSpam.clear(); + + getPartyContext().setPartyExistHypixel(false); + getPartyContext().setPartyOwner(Minecraft.getMinecraft().getSession().getUsername()); + getPartyContext().setPartyModerator(new TreeSet<>(String.CASE_INSENSITIVE_ORDER)); getPartyContext().setMemberComplete(true); + getPartyContext().setPartyMember(new TreeSet<>(String.CASE_INSENSITIVE_ORDER)); getPartyContext().setModeratorComplete(true); + getPartyContext().setAllInvite(false); + joinedParty(); + } + private void joinedParty() { + JSONArray jsonArray = new JSONArray(); + for (String member : getPartyContext().getPartyRawMembers()) { + jsonArray.put(member); + } + JSONObject object = new JSONObject(); + object.put("members", jsonArray); + StompInterface stompInterface = DungeonsGuide.getDungeonsGuide().getStompConnection(); + stompInterface.send(new StompPayload().payload(object.toString()).header("destination", "/app/party.join")); + + getPartyContext().setPartyID("!@#!@#!@#..........FETCHING..........$!@$!@$!@$"+UUID.randomUUID().toString()); + } + + public boolean isLeader() { + return partyContext != null && getPartyContext().hasLeader(Minecraft.getMinecraft().getSession().getUsername()); // "getUsername" + } + public boolean isModerator() { + return partyContext != null && getPartyContext().hasModerator(Minecraft.getMinecraft().getSession().getUsername()); + } + public boolean canInvite() { + return isLeader() || isModerator() || (partyContext != null && getPartyContext().getAllInvite() != null && getPartyContext().getAllInvite()); + } + + private boolean requested = false; + public void requestPartyList(Consumer<PartyContext> onPartyCallback) { + if (requested) { + partyBuiltCallback.add(onPartyCallback); + return; + } + requested = true; + + ChatProcessor.INSTANCE.addToChatQueue("/pl", () -> { + ChatProcessor.INSTANCE.subscribe(dashShredder()); + ChatProcessor.INSTANCE.subscribe(combinedShredder(typeShredder(true, "member_end"), dashShredder(), typeShredder(false,"notinparty", "member_start", "member_moder", "member_leader", "member_member"))); + }, true); + partyBuiltCallback.add(onPartyCallback); + partyBuiltCallback.add(pc -> requested=false); + } + + public void requestAllInvite() { + if (isLeader() || isModerator()) return; + if (partyContext != null && getPartyContext().getAllInvite() != null) return; + + ChatProcessor.INSTANCE.addToChatQueue("/p invite -", () -> { + ChatProcessor.INSTANCE.subscribe(dashShredder()); + ChatProcessor.INSTANCE.subscribe(typeShredder(true, "notinparty", "allinvite_off", "party_invite_noexist")); + ChatProcessor.INSTANCE.subscribe(dashShredder()); + }, true); + } + + private Map<String, Long> playerInvAntiSpam = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + @Override + public void handle(StompInterface stompInterface, StompPayload stompPayload) { + JSONObject object = new JSONObject(stompPayload.payload()); + if ("/user/queue/party.check".equals(stompPayload.headers().get("destination"))) { + String playerName = object.getString("player"); + String token = object.getString("token"); + if (partyContext == null) { + requestPartyList((pc) -> { + boolean contains = pc.getPartyRawMembers().contains(playerName); + if (!contains) { + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "failure").put("token", token).toString()).header("destination", "/app/party.check.resp")); + } else { + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "success").put("token", token).toString()).header("destination", "/app/party.check.resp")); + } + }); + } else { + if (getPartyContext().getPartyRawMembers().contains(playerName)) { + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "success").put("token", token).toString()).header("destination", "/app/party.check.resp")); + } else if (getPartyContext().isMemberComplete() && getPartyContext().isModeratorComplete() && getPartyContext().getPartyOwner() != null) { + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "failure").put("token", token).toString()).header("destination", "/app/party.check.resp")); + } else { + requestPartyList((pc) -> { + boolean contains = pc.getPartyRawMembers().contains(playerName); + if (!contains) { + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "failure").put("token", token).toString()).header("destination", "/app/party.check.resp")); + } else { + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "success").put("token", token).toString()).header("destination", "/app/party.check.resp")); + } + }); + } + } + } else if ("/user/queue/party.broadcast".equals(stompPayload.headers().get("destination"))) { + try { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: Message Broadcasted from player:: \n" + new JSONObject(stompPayload.payload()).getString("payload"))); + } catch (Exception e) { + e.printStackTrace(); + } + } else if ("/user/queue/party.join".equals(stompPayload.headers().get("destination"))) { + String playerName = object.getString("player"); + String secret = object.getString("secret"); + if (secret.equals(askToJoinSecret) && partyContext != null && getPartyContext().getPartyRawMembers().size() < maxParty && playerInvAntiSpam.getOrDefault(playerName, 0L) < System.currentTimeMillis() - 5000) { + playerInvAntiSpam.put(playerName, System.currentTimeMillis()); + ChatProcessor.INSTANCE.addToChatQueue("/p invite "+playerName,() -> {}, true); + } + } else if ("/user/queue/party.askedtojoin.resp".equals(stompPayload.headers().get("destination"))) { + String invFrom = object.getString("username"); + String token2 = object.getString("token"); + if (!token2.equals(lastToken)) return; + lastToken = null; + ChatProcessor.INSTANCE.addToChatQueue("/p accept "+invFrom, () -> {}, true); + long end = System.currentTimeMillis() + 3000; + ChatProcessor.INSTANCE.subscribe((str, a) -> { + if (!str.contains("§r§ehas invited you to join their party!")) return System.currentTimeMillis() > end ? ChatProcessResult.REMOVE_LISTENER : ChatProcessResult.NONE; + String[] messageSplit = TextUtils.stripColor(str).split(" "); + String inviter = null; + for (String s : messageSplit) { + if (s.startsWith("[")) continue; + if (s.startsWith("-")) continue;; + inviter = s; + break; + } + if (invFrom.equalsIgnoreCase(inviter)) { + ChatProcessor.INSTANCE.addToChatQueue("/p accept "+invFrom, () -> {}, true); + } + return ChatProcessResult.NONE; + }); + } else { + String str = object.getString("status"); + if ("success".equals(str) && partyContext != null) { + getPartyContext().setPartyID(object.getString("partyId")); + if (askToJoinSecret != null) { + updateAskToJoin(); + } + } else if (partyContext != null){ + getPartyContext().setPartyID(null); + } + } + } + + @SubscribeEvent + public void stompConnect(StompConnectedEvent stompConnectedEvent) { + stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder() + .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.resp").build()); + stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder() + .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.check").build()); + stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder() + .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.broadcast").build()); + stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder() + .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.join").build()); + stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder() + .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.askedtojoin.resp").build()); + } + + private String lastToken; + public void joinWithToken(String secret) { + lastToken = secret; + if (partyContext != null && getPartyContext().isPartyExistHypixel()) + ChatProcessor.INSTANCE.addToChatQueue("/p leave", () -> {}, true); + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().method(StompHeader.SEND) + .header("destination", "/app/party.askedtojoin") + .payload(new JSONObject().put("token", secret).toString())); + } + + private void potentialInvitenessChange() { + if (askToJoinSecret != null && !canInvite()) askToJoinSecret = null; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java new file mode 100644 index 00000000..28ce3735 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java @@ -0,0 +1,611 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.commands; + +import com.google.gson.JsonObject; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.events.DungeonEventHolder; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.*; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.chat.PartyContext; +import kr.syeyoung.dungeonsguide.chat.PartyManager; +import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager; +import kr.syeyoung.dungeonsguide.config.guiconfig.GuiConfigV2; +import kr.syeyoung.dungeonsguide.config.guiconfig.NestedCategory; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticsManager; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.MapProcessor; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonSpecificDataProvider; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonSpecificDataProviderRegistry; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoomInfoRegistry; +import kr.syeyoung.dungeonsguide.events.DungeonLeftEvent; +import kr.syeyoung.dungeonsguide.features.AbstractFeature; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.impl.party.playerpreview.FeatureViewPlayerOnJoin; +import kr.syeyoung.dungeonsguide.features.impl.party.api.ApiFetchur; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonRoomEdit; +import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessor; +import kr.syeyoung.dungeonsguide.utils.AhUtils; +import kr.syeyoung.dungeonsguide.utils.MapUtils; +import kr.syeyoung.dungeonsguide.utils.ShortUtils; +import kr.syeyoung.dungeonsguide.wsresource.StaticResourceCache; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.*; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.json.JSONObject; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.vecmath.Vector2d; +import java.awt.*; +import java.io.*; +import java.security.*; +import java.security.cert.CertificateException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.List; +import java.util.regex.Pattern; + +public class CommandDungeonsGuide extends CommandBase { + @Override + public String getCommandName() { + return "assets/dg"; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return "assets/dg"; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + if (args.length == 0) { + openConfig = true; + } else if (args[0].equalsIgnoreCase("saverooms")) { + DungeonRoomInfoRegistry.saveAll(DungeonsGuide.getDungeonsGuide().getConfigDir()); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fSuccessfully saved user generated roomdata")); + } else if (args[0].equalsIgnoreCase("loadrooms")) { + try { + DungeonRoomInfoRegistry.loadAll(DungeonsGuide.getDungeonsGuide().getConfigDir()); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fSuccessfully loaded roomdatas")); + return; + } catch (BadPaddingException e) { + e.printStackTrace(); + } catch (InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cAn error has occurred while loading roomdata")); + } else if (args[0].equalsIgnoreCase("reloadah")) { + try { + AhUtils.loadAuctions(); + } catch (CertificateException e) { + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } catch (KeyStoreException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (KeyManagementException e) { + e.printStackTrace(); + } + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fReloaded Ah data")); + } else if (args[0].equalsIgnoreCase("brand")) { + String serverBrand = Minecraft.getMinecraft().thePlayer.getClientBrand(); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e" + serverBrand)); + } else if (args[0].equalsIgnoreCase("reparty")) { + if (!DungeonsGuide.getDungeonsGuide().getCommandReparty().requestReparty(false)) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCurrently Repartying")); + } + } else if (args[0].equalsIgnoreCase("gui")) { + openConfig = true; + } else if (args[0].equalsIgnoreCase("info")) { + JSONObject obj = DungeonsGuide.getDungeonsGuide().getAuthenticator().getJwtPayload(DungeonsGuide.getDungeonsGuide().getAuthenticator().getRawToken()); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fUser Id§7: §e" + obj.get("userid"))); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fBound to§7: §e" + obj.get("nickname"))); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fBound uuid§7: §e" + obj.get("uuid"))); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fSession Expire§7: §e" + sdf.format(new Date(obj.getLong("exp") * 1000)))); + } else if (args[0].equalsIgnoreCase("pathfind")) { + try { + DungeonContext context = DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext(); + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + if (thePlayer == null) return; + if (context.getBossfightProcessor() != null) context.getBossfightProcessor().tick(); + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + GeneralRoomProcessor grp = (GeneralRoomProcessor) dungeonRoom.getRoomProcessor(); + grp.pathfind("COMMAND", args[1], args[2], FeatureRegistry.SECRET_LINE_PROPERTIES_GLOBAL.getRouteProperties()); + } catch (Throwable t) { + t.printStackTrace(); + } + } else if (args[0].equals("process") && Minecraft.getMinecraft().getSession().getPlayerID().replace("-", "").equals("e686fe0aab804a71ac7011dc8c2b534c")) { + File root = DungeonsGuide.getDungeonsGuide().getConfigDir(); + File dir = new File(root, "processorinput"); + File outsecret = new File(root, "processoroutsecret"); + for (File f : dir.listFiles()) { + if (!f.getName().endsWith(".roomdata")) continue; + try { + InputStream fis = new FileInputStream(f); + ObjectInputStream ois = new ObjectInputStream(fis); + DungeonRoomInfo dri = (DungeonRoomInfo) ois.readObject(); + ois.close(); + fis.close(); + dri.setUserMade(false); + + FileOutputStream fos = new FileOutputStream(new File(outsecret, dri.getUuid().toString() + ".roomdata")); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(dri); + oos.flush(); + oos.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (args[0].equals("check") && Minecraft.getMinecraft().getSession().getPlayerID().replace("-", "").equals("e686fe0aab804a71ac7011dc8c2b534c")) { + File root = DungeonsGuide.getDungeonsGuide().getConfigDir(); + for (File f : root.listFiles()) { + if (!f.getName().endsWith(".roomdata")) continue; + try { + InputStream fis = new FileInputStream(f); + ObjectInputStream ois = new ObjectInputStream(fis); + DungeonRoomInfo dri = (DungeonRoomInfo) ois.readObject(); + ois.close(); + fis.close(); + System.out.println("Starting at " + dri.getName() + " - " + dri.getUuid()); + for (Map.Entry<String, DungeonMechanic> value2 : dri.getMechanics().entrySet()) { + DungeonMechanic value = value2.getValue(); + if (value instanceof DungeonSecret && + (((DungeonSecret) value).getSecretType() == DungeonSecret.SecretType.BAT + || ((DungeonSecret) value).getSecretType() == DungeonSecret.SecretType.CHEST) + && ((DungeonSecret) value).getSecretPoint().getY() == 0) { + OffsetPoint offsetPoint = ((DungeonSecret) value).getSecretPoint(); + if (dri.getBlocks()[offsetPoint.getZ()][offsetPoint.getX()] != -1) { + dri.getBlocks()[offsetPoint.getZ()][offsetPoint.getX()] = -1; + System.out.println("Fixing " + value2.getKey() + " - as secret " + ((DungeonSecret) value).getSecretType() + " - at " + ((DungeonSecret) value).getSecretPoint()); + } + } else if (value instanceof DungeonOnewayDoor) { + for (OffsetPoint offsetPoint : ((DungeonOnewayDoor) value).getSecretPoint().getOffsetPointList()) { + if (offsetPoint.getY() == 0 && dri.getBlocks()[offsetPoint.getZ()][offsetPoint.getX()] != -1) { + dri.getBlocks()[offsetPoint.getZ()][offsetPoint.getX()] = -1; + System.out.println("Fixing " + value2.getKey() + " - o-door - at " + offsetPoint); + } + } + } else if (value instanceof DungeonDoor) { + for (OffsetPoint offsetPoint : ((DungeonDoor) value).getSecretPoint().getOffsetPointList()) { + if (offsetPoint.getY() == 0 && dri.getBlocks()[offsetPoint.getZ()][offsetPoint.getX()] != -1) { + dri.getBlocks()[offsetPoint.getZ()][offsetPoint.getX()] = -1; + System.out.println("Fixing " + value2.getKey() + " - door - at " + offsetPoint); + } + } + } else if (value instanceof DungeonBreakableWall) { + for (OffsetPoint offsetPoint : ((DungeonBreakableWall) value).getSecretPoint().getOffsetPointList()) { + if (offsetPoint.getY() == 0 && dri.getBlocks()[offsetPoint.getZ()][offsetPoint.getX()] != -1) { + dri.getBlocks()[offsetPoint.getZ()][offsetPoint.getX()] = -1; + System.out.println("Fixing " + value2.getKey() + " - wall - at " + offsetPoint); + } + } + } else if (value instanceof DungeonTomb) { + for (OffsetPoint offsetPoint : ((DungeonTomb) value).getSecretPoint().getOffsetPointList()) { + if (offsetPoint.getY() == 0 && dri.getBlocks()[offsetPoint.getZ()][offsetPoint.getX()] != -1) { + dri.getBlocks()[offsetPoint.getZ()][offsetPoint.getX()] = -1; + System.out.println("Fixing " + value2.getKey() + " - crypt - at " + offsetPoint); + } + } + } + } + FileOutputStream fos = new FileOutputStream(f); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(dri); + oos.flush(); + oos.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (args[0].equals("reloaddungeon") && Minecraft.getMinecraft().getSession().getPlayerID().replace("-", "").equals("e686fe0aab804a71ac7011dc8c2b534c")) { + try { + MinecraftForge.EVENT_BUS.post(new DungeonLeftEvent()); + DungeonsGuide.getDungeonsGuide().getSkyblockStatus().setContext(null); + MapUtils.clearMap(); + } catch (Throwable t) { + t.printStackTrace(); + } + } else if (args[0].equalsIgnoreCase("pvall")) { + PartyManager.INSTANCE.requestPartyList((context) -> { + if (context == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cNot in Party")); + return; + } + for (String member : context.getPartyRawMembers()) { + ApiFetchur.fetchUUIDAsync(member) + .thenAccept(a -> { + if (a == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+member+"§f's Profile §cCouldn't fetch uuid")); + } else { + ApiFetchur.fetchMostRecentProfileAsync(a.get(), FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey()); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e" + member + "§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null)))))); + } + }); + } + }); +// } else if (args[0].equals("fixschematic")) { +// File root = new File(e.getDungeonsGuide().getConfigDir(), "schematics"); +// Method method = null; +// try { +// method = NBTTagCompound.class.getDeclaredMethod("write", DataOutput.class); +// method.setAccessible(true); +// } catch (NoSuchMethodException e) { +// e.printStackTrace(); +// return; +// } +// for (File f : root.listFiles()) { +// try { +// NBTTagCompound nbtTagCompound = CompressedStreamTools.readCompressed(new FileInputStream(f)); +// if (nbtTagCompound.getKeySet().isEmpty()) { +// System.out.println("ah"); +// return; +// } +// nbtTagCompound.setString("Materials","Alpha"); +// FileOutputStream fos = new FileOutputStream(f); +// DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(fos))); +// +// try +// { +// dataoutputstream.writeByte(nbtTagCompound.getId()); +// +// dataoutputstream.writeUTF("Schematic"); +// method.invoke(nbtTagCompound, dataoutputstream); +// } +// finally +// { +// dataoutputstream.close(); +// } +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } + } else if (args[0].equalsIgnoreCase("asktojoin") || args[0].equalsIgnoreCase("atj")) { + if (RichPresenceManager.INSTANCE.getLastSetupCode() == -9999) { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cDiscord GameSDK has been disabled, or it failed to load!")); + return; + } + if (!PartyManager.INSTANCE.canInvite()) { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cYou don't have perms in the party to invite people!")); + } else { + PartyManager.INSTANCE.toggleAllowAskToJoin(); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fToggled Ask to join to " + (PartyManager.INSTANCE.getAskToJoinSecret() != null ? "§eon" : "§coff"))); + } + + if (!FeatureRegistry.DISCORD_RICHPRESENCE.isEnabled()) { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cDiscord Rich Presence is disabled! Enable at /dg -> Discord ")); + } + if (!FeatureRegistry.DISCORD_ASKTOJOIN.isEnabled()) { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cDiscord Invite Viewer is disabled! Enable at /dg -> Discord ")); // how + } + } else if (args[0].equalsIgnoreCase("partymax") || args[0].equalsIgnoreCase("pm")) { + if (args.length == 1) { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fCurrent party max is §e" + PartyManager.INSTANCE.getMaxParty())); + } else if (args.length == 2) { + try { + int partyMax = Integer.parseInt(args[1]); + if (partyMax < 2) { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cparty max can't be smaller than 2")); + return; + } + + PartyManager.INSTANCE.setMaxParty(partyMax); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fSuccessfully set partymax to §e" + PartyManager.INSTANCE.getMaxParty())); + } catch (Exception e) { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §c" + args[1] + " is not valid number.")); + return; + } + } + } else if (args[0].equals("partyid")) { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fInternal Party id: " + Optional.ofNullable(PartyManager.INSTANCE.getPartyContext()).map(PartyContext::getPartyID).orElse(null))); + } else if (args[0].equalsIgnoreCase("loc")) { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fYou're in " + DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName())); + } else if (args[0].equalsIgnoreCase("saverun")) { + try { + File f = DungeonsGuide.getDungeonsGuide().getConfigDir(); + File runDir = new File(f, "dungeonruns"); + runDir.mkdirs(); + + File runFile = new File(runDir, UUID.randomUUID() + ".dgrun"); + + DungeonContext dungeonContext = DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext(); + if (dungeonContext == null) { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCouldn't find dungeon to save!")); + return; + } + DungeonEventHolder dungeonEventHolder = new DungeonEventHolder(); + dungeonEventHolder.setDate(dungeonContext.getInit()); + dungeonEventHolder.setPlayers(dungeonContext.getPlayers()); + dungeonEventHolder.setEventDataList(dungeonContext.getEvents()); + + + ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(runFile)); + oos.writeObject(dungeonEventHolder); + oos.flush(); + oos.close(); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fSuccessfully saved dungeon run to " + runFile.getAbsolutePath())); + } catch (Exception e) { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cAn error occured while writing rundata " + e.getMessage())); + e.printStackTrace(); + } + } else if (args[0].equals("pv")) { + try { + ApiFetchur.fetchUUIDAsync(args[1]) + .thenAccept(a -> { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e" + args[1] + "§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null)))))); + }); + } catch (Exception e) { + e.printStackTrace(); + } + } else if (args[0].equals("purge")) { + ApiFetchur.purgeCache(); + CosmeticsManager cosmeticsManager = DungeonsGuide.getDungeonsGuide().getCosmeticsManager(); + cosmeticsManager.requestPerms(); + cosmeticsManager.requestCosmeticsList(); + cosmeticsManager.requestActiveCosmetics(); + StaticResourceCache.INSTANCE.purgeCache(); + FeatureRegistry.DISCORD_ASKTOJOIN.imageMap.clear(); + FeatureRegistry.DISCORD_ASKTOJOIN.futureMap.clear(); + + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fSuccessfully purged API Cache!")); + } else if (args[0].equals("pbroadcast")) { + try { + String[] payload = new String[args.length - 1]; + System.arraycopy(args, 1, payload, 0, payload.length); + String actualPayload = String.join(" ", payload).replace("$C$", "§"); + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().header("destination", "/app/party.broadcast").payload( + new JSONObject().put("partyID", PartyManager.INSTANCE.getPartyContext().getPartyID()) + .put("payload", actualPayload).toString() + )); + } catch (Exception e) { + e.printStackTrace(); + } + } else if (args[0].equals("requeststaticresource")) { + UUID uid = UUID.fromString(args[1]); + StaticResourceCache.INSTANCE.getResource(uid).thenAccept(a -> { + sender.addChatMessage(new ChatComponentText(a.getResourceID() + ": " + a.getValue() + ": " + a.isExists())); + }); + } else if (args[0].equals("createFakeRoom") && Minecraft.getMinecraft().getSession().getPlayerID().replace("-", "").equals("e686fe0aab804a71ac7011dc8c2b534c")) { + + // load schematic + File f = new File(DungeonsGuide.getDungeonsGuide().getConfigDir(), "schematics/new roonm-b2df250c-4af2-4201-963c-0ee1cb6bd3de-5efb1f0c-c05f-4064-bde7-cad0874fdf39.schematic"); + NBTTagCompound compound; + try { + compound = CompressedStreamTools.readCompressed(new FileInputStream(f)); + } catch (IOException e) { + e.printStackTrace(); + return; + } + + byte[] blocks = compound.getByteArray("Blocks"); + byte[] meta = compound.getByteArray("Data"); + for (int x = 0; x < compound.getShort("Width"); x++) { + for (int y = 0; y < compound.getShort("Height"); y++) { + for (int z = 0; z < compound.getShort("Length"); z++) { + int index = x + (y * compound.getShort("Length") + z) * compound.getShort("Width"); + BlockPos pos = new BlockPos(x, y, z); + World w = MinecraftServer.getServer().getEntityWorld(); + w.setBlockState(pos, Block.getBlockById(blocks[index] & 0xFF).getStateFromMeta(meta[index] & 0xFF), 2); + } + } + } + + + DungeonSpecificDataProviderRegistry.doorFinders.put(Pattern.compile("TEST DG"), new DungeonSpecificDataProvider() { + @Override + public BlockPos findDoor(World w, String dungeonName) { + return new BlockPos(0, 0, 0); + } + + @Override + public Vector2d findDoorOffset(World w, String dungeonName) { + return null; + } + + @Override + public BossfightProcessor createBossfightProcessor(World w, String dungeonName) { + return null; + } + + @Override + public boolean isTrapSpawn(String dungeonName) { + return false; + } + + @Override + public double secretPercentage(String dungeonName) { + return 0; + } + + @Override + public int speedSecond(String dungeonName) { + return 0; + } + }); + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + skyblockStatus.setDungeonName("TEST DG"); + DungeonContext fakeContext = new DungeonContext(Minecraft.getMinecraft().theWorld); + skyblockStatus.setContext(fakeContext); + skyblockStatus.setForceIsOnDungeon(true); + MapProcessor mapProcessor = fakeContext.getMapProcessor(); + mapProcessor.setUnitRoomDimension(new Dimension(16, 16)); + mapProcessor.setBugged(false); + mapProcessor.setDoorDimension(new Dimension(4, 4)); + mapProcessor.setTopLeftMapPoint(new Point(0, 0)); + fakeContext.setDungeonMin(new BlockPos(0, 70, 0)); + + DungeonRoom dungeonRoom = new DungeonRoom(Arrays.asList(new Point(0, 0)), ShortUtils.topLeftifyInt((short) 1), (byte) 63, new BlockPos(0, 70, 0), new BlockPos(31, 70, 31), fakeContext, Collections.emptySet()); + + fakeContext.getDungeonRoomList().add(dungeonRoom); + for (Point p : Arrays.asList(new Point(0, 0))) { + fakeContext.getRoomMapper().put(p, dungeonRoom); + } + + EditingContext.createEditingContext(dungeonRoom); + EditingContext.getEditingContext().openGui(new GuiDungeonRoomEdit(dungeonRoom)); + } else if (args[0].equals("CloseContext")) { + DungeonsGuide.getDungeonsGuide().getSkyblockStatus().setForceIsOnDungeon(false); + DungeonsGuide.getDungeonsGuide().getSkyblockStatus().setContext(null); + } else if (args[0].equals("dumpsettings")) { + NestedCategory root = new NestedCategory("ROOT"); + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + String category = abstractFeature.getCategory(); + NestedCategory currentRoot = root; + for (String s : category.split("\\.")) { + NestedCategory finalCurrentRoot = currentRoot; + if (currentRoot.children().containsKey(s)) + currentRoot = currentRoot.children().get(s); + else { + currentRoot.child(currentRoot = new NestedCategory(finalCurrentRoot.categoryFull() + "." + s)); + } + } + } + + StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder2 = new StringBuilder(); + + Stack<Tuple<NestedCategory, Integer>> stak = new Stack<>(); + stak.push(new Tuple<>(root, 0)); + Set<NestedCategory> discovered = new HashSet<>(); + while (!stak.isEmpty()) { + Tuple<NestedCategory, Integer> n = stak.pop(); + if (discovered.contains(n.getFirst())) continue; + discovered.add(n.getFirst()); + for (Map.Entry<String, NestedCategory> stringNestedCategoryEntry : n.getFirst().children().entrySet()) { + stak.push(new Tuple<>(stringNestedCategoryEntry.getValue(), n.getSecond() + 1)); + } + + if (n.getFirst().categoryFull().equals("ROOT")) continue; + + String prefix = ""; + for (int i = 0; i < n.getSecond() - 1; i++) { + prefix += " "; + } + + List<AbstractFeature> abstractFeatureList = FeatureRegistry.getFeaturesByCategory().getOrDefault(n.getFirst().categoryFull().substring(5), Collections.emptyList()); + stringBuilder.append(prefix).append("- C ").append(n.getFirst().categoryFull()).append("\n"); + stringBuilder2.append(n.getFirst().categoryFull()).append("\n"); + for (AbstractFeature abstractFeature : abstractFeatureList) { + stringBuilder.append(prefix).append(" - F ").append(abstractFeature.getName()).append(" / ").append(abstractFeature.getDescription().replace("\n", "$NEW_LINE$")).append("\n"); + } + } + System.out.println(stringBuilder.toString()); + System.out.println(stringBuilder2.toString()); + } else if (args[0].equals("readMap")) { + try { + int fromX = Integer.parseInt(args[1]); + int fromY = Integer.parseInt(args[2]); + sender.addChatMessage(new ChatComponentText(MapUtils.readDigit(MapUtils.getColors(), fromX, fromY)+"-")); +// int cntY = Integer.parseInt(args[3]); +// int target = Integer.parseInt(args[4]); +// StringBuilder sb = new StringBuilder("{"); +// for (int y = fromY; y < fromY + cntY; y++) { +// int curr = 0; +// for (int x = fromX; x < fromX+8; x++) { +// byte clr = MapUtils.getMapColorAt(MapUtils.getColors(), x,y); +// if (clr == target) curr = (curr << 1) | 1; +// else curr <<= 1; +// } +// sb.append("0x").append(Integer.toHexString(curr).toUpperCase()); +// if (y != fromY + cntY - 1) sb.append(", "); +// } +// sb.append("}"); +// System.out.println("\n"+sb.toString()); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg §7-§fOpens configuration gui")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg gui §7-§fOpens configuration gui")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg help §7-§fShows command help")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg saverooms §7-§f Saves usergenerated dungeon roomdata.")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg loadrooms §7-§f Reloads dungeon roomdata.")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg reloadah §7-§f Reloads price data from server.")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg brand §7-§f View server brand.")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg reparty §7-§f Reparty.")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg info §7-§f View Current DG User info.")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg asktojoin or /dg atj §7-§f Toggle ask to join §cRequires Discord Rich Presence enabled. (/dg -> Advanced)")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg partymax [number] or /dg pm [number] §7-§f Sets partymax §7(maximum amount people in party, for discord rpc)")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg pv [ign] §7-§f Profile Viewer")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg pvall §7-§f Profile Viewer For all people on party")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg purge §7-§f Purge api cache.")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg saverun §7-§f Save run to be sent to developer.")); + } + } + + private boolean openConfig = false; + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent e) { + try { + if (openConfig && e.phase == TickEvent.Phase.START ) { + openConfig = false; + Minecraft.getMinecraft().displayGuiScreen(new GuiConfigV2()); + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @Override + public int getRequiredPermissionLevel() { + return 0; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandReparty.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandReparty.java new file mode 100644 index 00000000..c9857b8e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandReparty.java @@ -0,0 +1,103 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.commands; + +import kr.syeyoung.dungeonsguide.chat.ChatProcessor; +import kr.syeyoung.dungeonsguide.chat.PartyManager; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; + +import java.util.stream.Collectors; + +public class CommandReparty extends CommandBase { + private String command; + public CommandReparty() { + command = FeatureRegistry.ETC_REPARTY.<String>getParameter("command").getValue(); + command = command.replace(" ", ""); + } + + @Override + public String getCommandName() { + return command; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return command; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + if (!requestReparty(false)) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCurrently Repartying")); + } + } + + private boolean reparting = false; + + + public boolean requestReparty(boolean noerror) { + if (reparting) { + return false; + } + reparting = true; + + PartyManager.INSTANCE.requestPartyList(pc -> { + if (pc == null) { + if (!noerror) + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cNot in Party")); + reparting = false; + return; + } + if (!pc.hasLeader(Minecraft.getMinecraft().getSession().getUsername())) { + if (!noerror) + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cYou're not leader")); + reparting = false; + return; + } + if (pc.isSelfSolo()) { + if (!noerror) + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cYou can not reparty yourself")); + reparting = false; + return; + } + String members = pc.getPartyRawMembers().stream().filter(a -> !a.equalsIgnoreCase(Minecraft.getMinecraft().getSession().getUsername())).collect(Collectors.joining(" ")); + String command = "/p invite "+members; + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §eDisbanding Party...")); + ChatProcessor.INSTANCE.addToChatQueue("/p disband", () -> { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §eRunning invite command §f"+command)); + ChatProcessor.INSTANCE.addToChatQueue(command, () -> { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §eSuccessfully repartied!§f")); + + reparting = false; + }, false); + }, false); + }); + return true; + } + + @Override + public int getRequiredPermissionLevel() { + return 0; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/Config.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/Config.java new file mode 100644 index 00000000..193b65b6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/Config.java @@ -0,0 +1,65 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import kr.syeyoung.dungeonsguide.features.AbstractFeature; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; + +import java.io.*; + +public class Config { + public static JsonObject configuration; + + public static File f; + + public static void loadConfig(File f) throws IOException { + try { + configuration = (JsonObject) new JsonParser().parse(new InputStreamReader(new FileInputStream(Config.f = f == null ? Config.f : f))); + } catch (Exception e) { + configuration = new JsonObject(); + } + for (AbstractFeature feature : FeatureRegistry.getFeatureList()) { + JsonObject object = configuration.getAsJsonObject(feature.getKey()); + if (object != null) feature.loadConfig(object); + } + + saveConfig(); + } + + public static void saveConfig() throws IOException { + for (AbstractFeature feature : FeatureRegistry.getFeatureList()) { + JsonObject object = feature.saveConfig(); + configuration.add(feature.getKey(), object); + } + + String str = new Gson().toJson(configuration); + FileOutputStream fos = null; + try { + fos = new FileOutputStream(f); + BufferedWriter bos = new BufferedWriter(new OutputStreamWriter(fos)); + bos.write(str); + bos.flush(); + } finally { + fos.close(); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/ConfigPanelCreator.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/ConfigPanelCreator.java new file mode 100644 index 00000000..d02680bf --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/ConfigPanelCreator.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +public class ConfigPanelCreator implements Function<String, MPanel> { + public static final ConfigPanelCreator INSTANCE = new ConfigPanelCreator(); + + public static final Map<String, Supplier<MPanel>> map = new HashMap<String, Supplier<MPanel>>(); + + @Nullable + @Override + public MPanel apply(@Nullable String input) { + if (!map.containsKey(input)) return null; + return map.get(input).get(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/GuiConfigV2.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/GuiConfigV2.java new file mode 100644 index 00000000..d1888283 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/GuiConfigV2.java @@ -0,0 +1,59 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig; + +import kr.syeyoung.dungeonsguide.gui.MGui; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.util.MathHelper; + +import java.awt.*; + +public class GuiConfigV2 extends MGui { + + @Getter + private RootConfigPanel rootConfigPanel; + + public GuiConfigV2() { + rootConfigPanel = new RootConfigPanel(this); + getMainPanel().add(rootConfigPanel); + } + + + @Override + public void initGui() { + super.initGui(); + int dw = Minecraft.getMinecraft().displayWidth; + int dh = Minecraft.getMinecraft().displayHeight; + int width = MathHelper.clamp_int(dw - 200, 1250, 1500), height = MathHelper.clamp_int(dh - 200, 600, 800); + double scale = 2.0; + if (dw <= width || dh <= height) { + width = width/2; height = height/2; + scale = 1.0; + } + rootConfigPanel.setBounds(new Rectangle((dw-width)/2, (dh-height)/2, width,height)); + rootConfigPanel.setScale(scale); + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawDefaultBackground(); + super.drawScreen(mouseX, mouseY, partialTicks); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MCategory.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MCategory.java new file mode 100644 index 00000000..77111fe7 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MCategory.java @@ -0,0 +1,103 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig; + +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; + +public class MCategory extends MPanel { + + private NestedCategory nestedCategory; + private RootConfigPanel rootConfigPanel; + @Getter + @Setter + private Color hover = new Color(94, 94, 94, 255); + public MCategory(NestedCategory nestedCategory, RootConfigPanel rootConfigPanel) { + this.nestedCategory = nestedCategory; + this.rootConfigPanel = rootConfigPanel; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + int border = RenderUtils.blendAlpha(0x141414, 0.12f); + if (!rootConfigPanel.getSearchWord().isEmpty() && (nestedCategory.categoryName().toLowerCase().contains(rootConfigPanel.getSearchWord()))) { + border = 0xFF02EE67; + } + + Gui.drawRect(0,0,getBounds().width, getBounds().height,border); + if (getBounds().height >= 28) + Gui.drawRect(1,18,getBounds().width -1, getBounds().height-1, RenderUtils.blendAlpha(0x141414, 0.15f)); + Gui.drawRect(1,1,getBounds().width-1, 18, RenderUtils.blendAlpha(0x141414, 0.12f)); + + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GlStateManager.pushMatrix(); + GlStateManager.translate(5,5,0); + GlStateManager.scale(1.0,1.0,0); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + + fr.drawString((lastAbsClip.contains(absMousex, absMousey) ? "§n" : "") + nestedCategory.categoryName(), 0,0, 0xFFFFFFFF); + GlStateManager.popMatrix(); + + fr.drawSplitString(FeatureRegistry.getCategoryDescription().getOrDefault(nestedCategory.categoryFull(), ""), 5, 23, getBounds().width -10, 0xFFBFBFBF); + } + + + @Override + public Dimension getPreferredSize() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + int descriptionHeight = + FeatureRegistry.getCategoryDescription().containsKey(nestedCategory.categoryFull()) ? + fr.listFormattedStringToWidth(FeatureRegistry.getCategoryDescription().get(nestedCategory.categoryFull()), Math.max(100, getBounds().width - 10)).size() * fr.FONT_HEIGHT + : -9; + + return new Dimension(100, descriptionHeight + 28); + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (lastAbsClip.contains(absMouseX, absMouseY)) { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + rootConfigPanel.setCurrentPageAndPushHistory(nestedCategory.categoryFull()); + } + } + + @Override + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + if (lastAbsClip.contains(absMouseX, absMouseY)) + setCursor(EnumCursor.POINTING_HAND); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MCategoryElement.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MCategoryElement.java new file mode 100644 index 00000000..22934fca --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MCategoryElement.java @@ -0,0 +1,82 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.util.ResourceLocation; + +import java.awt.*; + +public class MCategoryElement extends MPanel { + private String category; + private Runnable onClick; + private int leftPad = 0; + private int offsetX; + private RootConfigPanel rootConfigPanel; + public MCategoryElement(String category, Runnable onClick, int leftPad, int offsetX, RootConfigPanel rooot) { + this.category = category; + this.onClick = onClick; + this.leftPad = leftPad; + this.offsetX = offsetX; + this.rootConfigPanel = rooot; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + if (rootConfigPanel.getCurrentPage().equals(category)) { + clip(0,scissor.y, Minecraft.getMinecraft().displayWidth, scissor.height); + Gui.drawRect(leftPad - offsetX, 0, getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.13f)); + } else if (lastAbsClip.contains(absMousex, absMousey) && getTooltipsOpen() == 0) { + clip(0,scissor.y, Minecraft.getMinecraft().displayWidth, scissor.height); + Gui.drawRect(leftPad - offsetX, 0, getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.09f)); + } + clip(scissor.x, scissor.y, scissor.width, scissor.height); + + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + String name = category.substring(category.lastIndexOf(".")+1); + fr.drawString(name, leftPad,2,-1); + + } + + @Override + public Dimension getPreferredSize() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + return new Dimension(fr.getStringWidth(category.substring(category.lastIndexOf(".")+1)) + leftPad+10, fr.FONT_HEIGHT+4); + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (!lastAbsClip.contains(absMouseX, absMouseY) || getTooltipsOpen() > 0) { return; } + if (onClick != null) onClick.run(); + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + + } + @Override + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + if (lastAbsClip.contains(absMouseX, absMouseY)) + setCursor(EnumCursor.POINTING_HAND); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MFeature.java new file mode 100644 index 00000000..49f637a5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MFeature.java @@ -0,0 +1,154 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig; + +import kr.syeyoung.dungeonsguide.config.guiconfig.location.GuiGuiLocationConfig; +import kr.syeyoung.dungeonsguide.features.AbstractFeature; +import kr.syeyoung.dungeonsguide.features.GuiFeature; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MToggleButton; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class MFeature extends MPanel { + + @Getter + private final AbstractFeature feature; + + private final List<MPanel> addons = new ArrayList<MPanel>(); + + @Getter @Setter + private Color hover; + + private final RootConfigPanel panel; + + public MFeature(final AbstractFeature abstractFeature, final RootConfigPanel panel) { + this.panel = panel; + this.feature = abstractFeature; + + if (abstractFeature.isDisyllable()) { + final MToggleButton mStringSelectionButton = new MToggleButton(); + mStringSelectionButton.setOnToggle(new Runnable() { + @Override + public void run() { + boolean selected = mStringSelectionButton.isEnabled(); + feature.setEnabled(selected); + } + }); + mStringSelectionButton.setBackground(RenderUtils.blendAlpha(0x141414, 0.07f)); + addons.add(mStringSelectionButton); + mStringSelectionButton.setEnabled(feature.isEnabled()); + mStringSelectionButton.setSize(new Dimension(40, 15)); + add(mStringSelectionButton); + } + if (abstractFeature.getParameters().size() != 0) { + MButton button = new MButton(); + button.setText("Settings"); + button.setOnActionPerformed(new Runnable() { + @Override + public void run() { + panel.setCurrentPageAndPushHistory(abstractFeature.getEditRoute(panel)); + } + }); + button.setBackground(RenderUtils.blendAlpha(0x141414, 0.07f)); + button.setClicked(RenderUtils.blendAlpha(0x141414, 0.17f)); + button.setHover(RenderUtils.blendAlpha(0x141414, 0.17f)); + addons.add(button); + button.setSize(new Dimension(50, 15)); + add(button); + } + if (abstractFeature instanceof GuiFeature) { + MButton button = new MButton(); + button.setText("Relocate"); + button.setOnActionPerformed(new Runnable() { + @Override + public void run() { + Minecraft.getMinecraft().displayGuiScreen(new GuiGuiLocationConfig(Minecraft.getMinecraft().currentScreen, abstractFeature)); + button.setIsclicked(false); + } + }); + button.setBackground(RenderUtils.blendAlpha(0x141414, 0.07f)); + button.setClicked(RenderUtils.blendAlpha(0x141414, 0.17f)); + button.setHover(RenderUtils.blendAlpha(0x141414, 0.17f)); + addons.add(button); + button.setSize(new Dimension(75, 15)); + add(button); + } + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + + int border = RenderUtils.blendAlpha(0x141414, 0.12f); + if (!panel.getSearchWord().isEmpty() && (feature.getName().toLowerCase().contains(panel.getSearchWord()) || feature.getDescription().toLowerCase().contains(panel.getSearchWord()))) { + border = 0xFF02EE67; + } + + Gui.drawRect(0,0,getBounds().width, getBounds().height,border); + Gui.drawRect(1,18,getBounds().width -1, getBounds().height-1, RenderUtils.blendAlpha(0x141414, 0.15f)); + Gui.drawRect(1,1,getBounds().width-1, 18, RenderUtils.blendAlpha(0x141414, 0.12f)); + + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GlStateManager.pushMatrix(); + GlStateManager.translate(5,5,0); + GlStateManager.scale(1.0,1.0,0); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(feature.getName(), 0,0, 0xFFFFFFFF); + GlStateManager.popMatrix(); + + fr.drawSplitString(feature.getDescription(), 5, 23, getBounds().width -10, 0xFFBFBFBF); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setSize(new Dimension(parentWidth, getBounds().height)); + } + + @Override + public Dimension getPreferredSize() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int descriptionHeight = fr.listFormattedStringToWidth(feature.getDescription(), Math.max(100, getBounds().width - 10)).size() * fr.FONT_HEIGHT; + + return new Dimension(100, descriptionHeight + 28); + } + + @Override + public void onBoundsUpdate() { + int x = getBounds().width - 5; + for (MPanel panel : addons) { + panel.setBounds(new Rectangle(x - panel.getPreferredSize().width, 3, panel.getPreferredSize().width, 12)); + x -= panel.getPreferredSize().width + 5; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MFeatureEdit.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MFeatureEdit.java new file mode 100644 index 00000000..22bb60fa --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MFeatureEdit.java @@ -0,0 +1,113 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig; + +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MList; +import kr.syeyoung.dungeonsguide.gui.elements.MModalConfirmation; +import kr.syeyoung.dungeonsguide.features.AbstractFeature; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.gui.MPanel; + +import java.awt.*; +import java.util.HashMap; +import java.util.Map; + +public class MFeatureEdit extends MPanel { + private MList list; + private MButton goBack, resetToDefault; + private RootConfigPanel rootConfigPanel; + private AbstractFeature abstractFeature; + + private Map<String, MPanel> parameterEdits = new HashMap<>(); + + public MFeatureEdit(AbstractFeature abstractFeature, RootConfigPanel rootConfigPanel) { + this.abstractFeature = abstractFeature; + this.rootConfigPanel = rootConfigPanel; + list = new MList(); + list.setGap(5); + list.setDrawLine(false); + add(list); + + goBack = new MButton(); + goBack.setText("< Go Back"); + goBack.setOnActionPerformed(rootConfigPanel::goBack); + add(goBack); + resetToDefault = new MButton(); + resetToDefault.setText("Reset To Default"); + resetToDefault.setForeground(Color.red); + resetToDefault.setOnActionPerformed(() -> { + openResetConfirmation(); + }); + add(resetToDefault); + } + + public void openResetConfirmation() { + MModalConfirmation mModal = new MModalConfirmation("Are you sure?", + "Resetting to default will reset your configuration for the selected feature to default", + () -> { + for (FeatureParameter parameter : abstractFeature.getParameters()) { + parameter.setToDefault(); + } + abstractFeature.onParameterReset(); + rootConfigPanel.invalidatePage(abstractFeature.getEditRoute(rootConfigPanel)); + }, () -> {}); + mModal.setScale(getScale()); + mModal.getYes().setBorder(0xFFFF0000); + mModal.getYes().setText("Yes, Reset it"); + mModal.getNo().setText("Cancel"); + mModal.open(MFeatureEdit.this); + } + + public void addParameterEdit(String name, MPanel paramEdit) { + parameterEdits.put(name, paramEdit); + list.add(paramEdit); + } + public MPanel removeParameterEdit(String name) { + MPanel panel = parameterEdits.remove(name); + list.remove(panel); + return panel; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + super.resize(parentWidth, parentHeight); + setBounds(new Rectangle(0,0,parentWidth,parentHeight)); + Dimension prefSize = getPreferredSize(); + int hei = prefSize.height; + setBounds(new Rectangle(0,0,parentWidth,hei)); + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + goBack.setBounds(new Rectangle(5,5,75,15)); + resetToDefault.setBounds(new Rectangle(bounds.width - 105, 5, 100, 15)); + + list.setBounds(new Rectangle(5,25,bounds.width - 10, bounds.height - 10)); + list.realignChildren(); + + } + + @Override + public Dimension getPreferredSize() { + Dimension listPref = list.getPreferredSize(); + return new Dimension(listPref.width + 10, listPref.height + 30); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MNotFound.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MNotFound.java new file mode 100644 index 00000000..a6ab6821 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MNotFound.java @@ -0,0 +1,38 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; + +import java.awt.*; + +public class MNotFound extends MPanel { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0,0,parentWidth,parentHeight)); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString("404 Not Found", (getBounds().width - fr.getStringWidth("404 Not Found")) / 2, (getBounds().height - fr.FONT_HEIGHT) / 2, -1); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MPanelCategory.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MPanelCategory.java new file mode 100644 index 00000000..1a7cbc74 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MPanelCategory.java @@ -0,0 +1,83 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig; + +import kr.syeyoung.dungeonsguide.gui.elements.MList; +import kr.syeyoung.dungeonsguide.features.AbstractFeature; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.gui.MPanel; + +import java.awt.*; + +public class MPanelCategory extends MPanel { + + private NestedCategory key; + private RootConfigPanel rootConfigPanel; + + private MList list; + + public MPanelCategory(NestedCategory nestedCategory, RootConfigPanel rootConfigPanel) { + this.key = nestedCategory; + this.rootConfigPanel = rootConfigPanel; + + list = new MList(); + list.setDrawLine(false); + list.setGap(5); + add(list); + + for (NestedCategory value : nestedCategory.children().values()) { + list.add(new MCategory(value, rootConfigPanel)); + } + if (nestedCategory.parent() != null) { + String actualCategory = nestedCategory.categoryFull().substring(5); + if (FeatureRegistry.getFeaturesByCategory().containsKey(actualCategory)) + for (AbstractFeature abstractFeature : FeatureRegistry.getFeaturesByCategory().get(actualCategory)) { + MFeature mFeature = new MFeature(abstractFeature, rootConfigPanel); + list.add(mFeature); + mFeature.setHover(new Color(94, 94, 94, 255)); + } + } + list.realignChildren(); + + } + + @Override + public void resize(int parentWidth, int parentHeight) { + super.resize(parentWidth, parentHeight); + setBounds(new Rectangle(0,0,parentWidth,parentHeight)); + Dimension prefSize = getPreferredSize(); + int hei = prefSize.height; + setBounds(new Rectangle(0,0,parentWidth,hei)); + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + list.setBounds(new Rectangle(5,5,bounds.width- 10, bounds.height - 10)); + list.realignChildren(); + } + + @Override + public Dimension getPreferredSize() { + Dimension prefSize = list.getPreferredSize(); + int wid = prefSize.width + 10; + int hei = prefSize.height + 10; + return new Dimension(wid, hei); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MParameterEdit.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MParameterEdit.java new file mode 100644 index 00000000..db223fe9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/MParameterEdit.java @@ -0,0 +1,220 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.features.AbstractFeature; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; + +import java.awt.*; +import java.util.function.Predicate; + +public class MParameterEdit extends MPanel { + private AbstractFeature abstractFeature; + private FeatureParameter featureParameter; + private RootConfigPanel rootConfigPanel; + private MPanel valueEditHolder; + private MPanel valueEdit; + + private Predicate<FeatureParameter> isDisabled ; + + public MParameterEdit(AbstractFeature abstractFeature, FeatureParameter parameter, RootConfigPanel rootConfigPanel) { + this(abstractFeature, parameter, rootConfigPanel, (a) -> false); + } + + public MParameterEdit(AbstractFeature abstractFeature, FeatureParameter parameter, RootConfigPanel rootConfigPanel, Predicate<FeatureParameter> isDisabled ) { + this.abstractFeature = abstractFeature; + this.featureParameter = parameter; + this.rootConfigPanel = rootConfigPanel; + this.isDisabled = isDisabled; + + if (parameter.getValue_type().equals("string")) { + valueEdit = new MTextField() { + @Override + public void edit(String str) { + parameter.setValue(str); + } + }; + ((MTextField)valueEdit).setText((String) parameter.getValue()); + } else if (parameter.getValue_type().equals("integer")) { + valueEdit = new MIntegerSelectionButton((Integer) parameter.getValue()); + ((MIntegerSelectionButton)valueEdit).setOnUpdate(() -> { + parameter.setValue(((MIntegerSelectionButton) valueEdit).getData()); + }); + } else if (parameter.getValue_type().equals("float")) { + valueEdit = new MFloatSelectionButton((Float) parameter.getValue()); + ((MFloatSelectionButton)valueEdit).setOnUpdate(() -> { + parameter.setValue(((MFloatSelectionButton) valueEdit).getData()); + }); + } else if (parameter.getValue_type().equals("acolor")) { + valueEdit = new MEditableAColor(); + ((MEditableAColor)valueEdit).setColor((AColor) parameter.getValue()); + ((MEditableAColor)valueEdit).setEnableEdit(true); + ((MEditableAColor)valueEdit).setOnUpdate(() -> { + parameter.setValue(((MEditableAColor) valueEdit).getColor()); + }); + } else if (parameter.getValue_type().equals("color")) { + valueEdit = new MEditableAColor(); + ((MEditableAColor)valueEdit).setColor(new AColor(((Color) parameter.getValue()).getRGB(), true)); + ((MEditableAColor)valueEdit).setEnableEdit(true); + ((MEditableAColor)valueEdit).setOnUpdate(() -> { + parameter.setValue(((MEditableAColor) valueEdit).getColor()); + }); + } else if (parameter.getValue_type().equals("boolean")) { + valueEdit = new MToggleButton(); + ((MToggleButton)valueEdit).setEnabled((Boolean) parameter.getValue()); + ((MToggleButton)valueEdit).setOnToggle(() -> { + parameter.setValue(((MToggleButton) valueEdit).isEnabled()); + }); + } else if (parameter.getValue_type().equals("keybind")) { + valueEdit = new MKeyEditButton(); + ((MKeyEditButton)valueEdit).setKey((Integer) parameter.getValue()); + ((MKeyEditButton)valueEdit).setOnKeyEdit(() -> { + parameter.setValue(((MKeyEditButton) valueEdit).getKey()); + }); + ((MKeyEditButton)valueEdit).setBorder(RenderUtils.blendTwoColors(0xFF141414,0x7702EE67)); + }else { + valueEdit = new MLabel(); + ((MLabel)valueEdit).setText("????"); + } + + + valueEditHolder = new MPanel() { + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + Dimension dimension = valueEdit.getPreferredSize(); + if (dimension.width <= 0) dimension.width = bounds.width/2; + if (dimension.height <= 0) dimension.height = bounds.height/2; + valueEdit.setBounds(new Rectangle((bounds.width - dimension.width)/2,(bounds.height - dimension.height)/2,dimension.width, dimension.height)); + } + }; + add(valueEditHolder); + valueEditHolder.add(valueEdit); + } + public MParameterEdit(AbstractFeature abstractFeature, FeatureParameter parameter, RootConfigPanel rootConfigPanel, MPanel valueEdit, Predicate<FeatureParameter> isDisabled) { + this.abstractFeature = abstractFeature; + this.featureParameter = parameter; + this.rootConfigPanel = rootConfigPanel; + this.isDisabled = isDisabled; + + + valueEditHolder = new MPanel() { + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + Dimension dimension = valueEdit.getPreferredSize(); + if (dimension.width <= 0) dimension.width = bounds.width/2; + if (dimension.height <= 0) dimension.height = bounds.height/2; + valueEdit.setBounds(new Rectangle((bounds.width - dimension.width)/2,(bounds.height - dimension.height)/2,dimension.width, dimension.height)); + } + }; + add(valueEditHolder); + valueEditHolder.add(valueEdit); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + Gui.drawRect(0,0,getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.12f)); + Gui.drawRect(2*bounds.width / 3,1,getBounds().width -1, getBounds().height-1, RenderUtils.blendAlpha(0x141414, 0.15f)); + Gui.drawRect(4, 15,2*bounds.width / 3-5, 16, RenderUtils.blendAlpha(0x141414, 0.3f)); + + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString(featureParameter.getName(), 5,5, 0xFFFFFFFF); + fr.drawSplitString(featureParameter.getDescription(), 5,18, 2*bounds.width /3-10, 0xFFAAAAAA); + + } + + @Override + public void render0(double scale, Point parentPoint, Rectangle parentClip, int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks) { + super.render0(scale, parentPoint, parentClip, absMousex, absMousey, relMousex0, relMousey0, partialTicks); + if (isDisabled.test(featureParameter)) { + Gui.drawRect(0,0, getBounds().width, getBounds().height, 0x55000000); + } + } + + @Override + public Dimension getPreferredSize() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int descriptionHeight = fr.listFormattedStringToWidth(featureParameter.getDescription(), Math.max(50, 2*bounds.width/3-10)).size() * fr.FONT_HEIGHT; + return new Dimension(100, Math.max(30, descriptionHeight + 23)); + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + valueEditHolder.setBounds(new Rectangle(2*bounds.width / 3, 0, bounds.width / 3, bounds.height)); + } + + @Override + public void keyPressed0(char typedChar, int keyCode) { + if (isDisabled.test(featureParameter)) return; + super.keyPressed0(typedChar, keyCode); + } + + @Override + public void keyHeld0(char typedChar, int keyCode) { + if (isDisabled.test(featureParameter)) return; + super.keyHeld0(typedChar, keyCode); + } + + @Override + public void keyReleased0(char typedChar, int keyCode) { + if (isDisabled.test(featureParameter)) return; + super.keyReleased0(typedChar, keyCode); + } + + @Override + public boolean mouseClicked0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int mouseButton) { + if (isDisabled.test(featureParameter)) return false; + return super.mouseClicked0(absMouseX, absMouseY, relMouseX0, relMouseY0, mouseButton); + } + + @Override + public void mouseReleased0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int state) { + if (isDisabled.test(featureParameter)) return ; + super.mouseReleased0(absMouseX, absMouseY, relMouseX0, relMouseY0, state); + } + + @Override + public void mouseClickMove0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int clickedMouseButton, long timeSinceLastClick) { + if (isDisabled.test(featureParameter)) return ; + super.mouseClickMove0(absMouseX, absMouseY, relMouseX0, relMouseY0, clickedMouseButton, timeSinceLastClick); + } + + @Override + public void mouseScrolled0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (isDisabled.test(featureParameter)) return ; + super.mouseScrolled0(absMouseX, absMouseY, relMouseX0, relMouseY0, scrollAmount); + } + + @Override + public void mouseMoved0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + if (isDisabled.test(featureParameter)) return ; + super.mouseMoved0(absMouseX, absMouseY, relMouseX0, relMouseY0); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/NestedCategory.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/NestedCategory.java new file mode 100644 index 00000000..aaa401bf --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/NestedCategory.java @@ -0,0 +1,54 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.util.LinkedHashMap; +import java.util.Map; + +@Data +@Accessors(chain = true, fluent = true) +public +class NestedCategory { + private final String categoryFull; + @EqualsAndHashCode.Exclude + private String categoryName; + @EqualsAndHashCode.Exclude + @ToString.Exclude + private NestedCategory parent; + + public NestedCategory(String categoryFull) { + this.categoryFull = categoryFull; + this.categoryName = categoryFull.substring(categoryFull.lastIndexOf(".") + 1); + } + + @EqualsAndHashCode.Exclude + @ToString.Exclude + private Map<String, NestedCategory> children = new LinkedHashMap<>(); + + public NestedCategory child(NestedCategory child) { + this.children.put(child.categoryName, child); + child.parent = this; + return this; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/RootConfigPanel.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/RootConfigPanel.java new file mode 100644 index 00000000..f7eed53b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/RootConfigPanel.java @@ -0,0 +1,306 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig; + +import com.google.common.base.Function; +import kr.syeyoung.dungeonsguide.config.guiconfig.location.GuiGuiLocationConfig; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.features.AbstractFeature; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; + +import java.awt.*; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; + +public class RootConfigPanel extends MPanelScaledGUI { + private MScrollablePanel navigationScroll; + + private MList navigation = new MList(); + + private MScrollablePanel contentScroll; + + + private final Map<String, MPanel> pages = new HashMap<String, MPanel>(); + @Getter + @Setter + private Function<String, MPanel> pageGenerator = ConfigPanelCreator.INSTANCE; + @Getter + private String currentPage = ""; + + private GuiConfigV2 gui; + + private long lastPageSet = System.currentTimeMillis(); + + private MTextField search; + private MButton guiRelocate; + + private MButton github, discord; + + private final Stack<String> history = new Stack<String>(); + + public String getSearchWord() { + return search.getText().trim().toLowerCase(); + } + + public RootConfigPanel(GuiConfigV2 guiConfigV2) { + this.gui = guiConfigV2; + + search = new MTextField() { + @Override + public void edit(String str) { + setupNavigation(); + + setCurrentPageAndPushHistory(""); + if (!categoryMap.containsKey(lastOpenCategory)) { + for (Map.Entry<NestedCategory, MPanel> nestedCategoryMPanelEntry : categoryMap.entrySet()) { + if (nestedCategoryMPanelEntry.getValue() instanceof MCategoryElement) { + setCurrentPageAndPushHistory(nestedCategoryMPanelEntry.getKey().categoryFull()); + lastOpenCategory = nestedCategoryMPanelEntry.getKey(); + break; + } + } + } + for (Map.Entry<NestedCategory, MPanel> nestedCategoryMPanelEntry : categoryMap.entrySet()) { + if (nestedCategoryMPanelEntry.getValue() instanceof MCollapsable) { + ((MCollapsable) nestedCategoryMPanelEntry.getValue()).setCollapsed(false); + } + } + rePlaceElements(); + } + }; + search.setPlaceHolder("Search..."); + add(search); + guiRelocate = new MButton(); + guiRelocate.setText("Edit Gui Locations"); + guiRelocate.setOnActionPerformed(() -> { + Minecraft.getMinecraft().displayGuiScreen(new GuiGuiLocationConfig(gui, null)); + guiRelocate.setIsclicked(false); + }); + guiRelocate.setBorder(RenderUtils.blendTwoColors(0xFF141414,0x7702EE67)); + add(guiRelocate); + + discord = new MButton(); github = new MButton(); + discord.setText("Discord"); github.setText("Github"); + discord.setBorder(RenderUtils.blendTwoColors(0xFF141414,0x7702EE67)); + github.setBorder(RenderUtils.blendTwoColors(0xFF141414,0x7702EE67)); + github.setOnActionPerformed(() -> { + try { + Desktop.getDesktop().browse(new URI("https://github.com/Dungeons-Guide/Skyblock-Dungeons-Guide/")); + } catch (IOException | URISyntaxException e) { + e.printStackTrace(); + } + }); + discord.setOnActionPerformed(() -> { + try { + Desktop.getDesktop().browse(new URI("https://discord.gg/VuxayCWGE8")); + } catch (IOException | URISyntaxException e) { + e.printStackTrace(); + } + }); + add(discord); add(github); + + navigationScroll = new MScrollablePanel(1); + navigationScroll.setHideScrollBarWhenNotNecessary(false); + + + add(navigationScroll); + navigationScroll.add(navigation); + + contentScroll = new MScrollablePanel(3); + contentScroll.setHideScrollBarWhenNotNecessary(true); + add(contentScroll); + + setupNavigation(); + navigation.setGap(0); + navigation.setDrawLine(false); + + setCurrentPageAndPushHistory("ROOT"); + rePlaceElements(); + + search.setFocused(true); + } + + + private Map<NestedCategory, MPanel> categoryMap = new HashMap<>(); + private NestedCategory lastOpenCategory; + private void setupNavigation() { + categoryMap.clear(); + for (MPanel childComponent : navigation.getChildComponents()) { + navigation.remove(childComponent); + } + NestedCategory root = new NestedCategory("ROOT"); + Set<String> categoryAllowed = new HashSet<>(); + String search = this.search.getText().trim().toLowerCase(); + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (search.isEmpty()) { + categoryAllowed.add("ROOT."+abstractFeature.getCategory()+"."); + } else if (abstractFeature.getName().toLowerCase().contains(search)) { + categoryAllowed.add("ROOT."+abstractFeature.getCategory()+"."); + } else if (abstractFeature.getDescription().toLowerCase().contains(search)) { + categoryAllowed.add("ROOT."+abstractFeature.getCategory()+"."); + } + } + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + String category = abstractFeature.getCategory(); + boolean test =false; + for (String s : categoryAllowed) { + if (s.startsWith("ROOT."+category+".")) { + test = true; + break; + } + } + if (!test) continue; + + NestedCategory currentRoot = root; + for (String s : category.split("\\.")) { + NestedCategory finalCurrentRoot = currentRoot; + if (currentRoot.children().containsKey(s)) + currentRoot = currentRoot.children().get(s); + else { + currentRoot.child(currentRoot = new NestedCategory(finalCurrentRoot.categoryFull()+"."+s)); + } + } + + } + + for (NestedCategory value : root.children().values()) { + setupNavigationRecursive(value, navigation, 0, 17); + } + ConfigPanelCreator.map.put("ROOT", () -> new MPanelCategory(root, this)); + } + private void setupNavigationRecursive(NestedCategory nestedCategory, MPanel parent, int depth, int offset) { + ConfigPanelCreator.map.put(nestedCategory.categoryFull(), () -> new MPanelCategory(nestedCategory, this)); + + if (nestedCategory.children().size() == 0) { + MCategoryElement current = new MCategoryElement(nestedCategory.categoryFull(),() -> { + setCurrentPageAndPushHistory(nestedCategory.categoryFull()); + lastOpenCategory = nestedCategory; + }, 13 * depth + 17, offset, this); + parent.add(current); + categoryMap.put(nestedCategory, current); + } else { + MCategoryElement current = new MCategoryElement(nestedCategory.categoryFull(),() -> { + setCurrentPageAndPushHistory(nestedCategory.categoryFull()); + lastOpenCategory = nestedCategory; + }, 3,offset, this); + MCollapsable mCollapsable = new MCollapsable(current, this::rePlaceElements); + mCollapsable.setLeftPad(offset-13); + mCollapsable.getLowerElements().setDrawLine(false); + mCollapsable.getLowerElements().setGap(0); + mCollapsable.setLeftPadElements(0); + parent.add(mCollapsable); + categoryMap.put(nestedCategory, mCollapsable); + + for (NestedCategory value : nestedCategory.children().values()) { + setupNavigationRecursive(value, mCollapsable, depth+1, offset+13); + } + } + } + + + public void setCurrentPageAndPushHistory(String currentPage) { + if (!this.currentPage.equals(currentPage)) + history.push(this.currentPage); + lastOpenCategory = null; + this.currentPage = currentPage; + setupPage(); + } + public void goBack() { + if (history.size() == 0) return; + this.currentPage = history.pop(); + setupPage(); + } + + private void setupPage() { + contentScroll.getContentArea().getChildComponents().forEach(contentScroll.getContentArea()::remove); + if (!pages.containsKey(currentPage)) { + MPanel page = pageGenerator.apply(currentPage); + if (page == null) page = new MNotFound(); + pages.put(currentPage, page); + } + contentScroll.getContentArea().add(pages.get(currentPage)); + rePlaceElements(); + } + + public void invalidatePage(String page) { + pages.remove(page); + if (page.equals(currentPage)) + setupPage(); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + Dimension effectiveDim = getEffectiveDimension(); + Gui.drawRect(0,0, (int) (effectiveDim.width), (int) (effectiveDim.height), RenderUtils.blendAlpha(0x141414, 0.00f)); + Gui.drawRect(0,0, (int) (effectiveDim.width), 25, RenderUtils.blendAlpha(0x0, 0.20f)); +// Gui.drawRect(navigationScroll.getBounds().x + navigationScroll.getBounds().width - 10, 25, navigationScroll.getBounds().x + navigationScroll.getBounds().width , 50, RenderUtils.blendAlpha(0xFF141414, 0.04f)); + Gui.drawRect(0, 25,navigationScroll.getBounds().x + navigationScroll.getBounds().width , 50, RenderUtils.blendAlpha(0xFF141414, 0.08f)); + + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString("DungeonsGuide By syeyoung", (effectiveDim.width - fr.getStringWidth("DungeonsGuide By syeyoung"))/2, (25 - fr.FONT_HEIGHT)/2, 0xFF02EE67); + } + + @Override + public void render0(double parentScale, Point parentPoint, Rectangle parentClip, int absMousex0, int absMousey0, int relMousex0, int relMousey0, float partialTicks) { + super.render0(parentScale, parentPoint, parentClip, absMousex0, absMousey0, relMousex0, relMousey0, partialTicks); + Dimension effectiveDim = getEffectiveDimension(); + Gui.drawRect(0,24, (int) (Double.min(1, (System.currentTimeMillis() - lastPageSet)/1000.0) * effectiveDim.width), 25, 0xFF02EE67); + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + rePlaceElements(); + } + + @Override + public void setScale(double scale) { + super.setScale(scale); + rePlaceElements(); + } + + private void rePlaceElements() { + Dimension effectiveDim = getEffectiveDimension(); + + navigation.setBounds(new Rectangle(new Point(0,1), new Dimension(Math.max(100, Math.max(navigation.getPreferredSize().width, navigationScroll.getBounds().width-10)), navigation.getPreferredSize().height))); + navigation.realignChildren(); + + navigationScroll.evalulateContentArea(); + Rectangle navBound; + navigationScroll.setBounds(navBound = new Rectangle(0,50, navigation.getBounds().width+10, effectiveDim.height-50)); + contentScroll.setBounds(new Rectangle(navBound.x + navBound.width, 25, effectiveDim.width - navBound.x - navBound.width, effectiveDim.height-25)); + + search.setBounds(new Rectangle(5,30,navBound.x + navBound.width - 10,15)); + + guiRelocate.setBounds(new Rectangle(5,5,100,15)); + github.setBounds(new Rectangle(effectiveDim.width - 80,5,75,15)); + discord.setBounds(new Rectangle(effectiveDim.width - 160,5,75,15)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/location/GuiGuiLocationConfig.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/location/GuiGuiLocationConfig.java new file mode 100755 index 00000000..48c046c3 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/location/GuiGuiLocationConfig.java @@ -0,0 +1,166 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig.location; + +import kr.syeyoung.dungeonsguide.features.AbstractFeature; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.GuiFeature; +import kr.syeyoung.dungeonsguide.gui.MGui; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.Vec3; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.io.IOException; +import java.util.*; +import java.util.List; + +public class GuiGuiLocationConfig extends MGui { + + @Getter + private final GuiScreen before; + + @Getter + private TreeMap<Integer, List<Marker>> markerTreeMapByX = new TreeMap<>(); + @Getter + private TreeMap<Integer, List<Marker>> markerTreeMapByY = new TreeMap<>(); + @Getter + private Set<Marker> markerSet = new HashSet<>(); + + + Marker[] markers = new Marker[4]; + + + public GuiGuiLocationConfig(final GuiScreen before, AbstractFeature featureWhitelist) { + this.before = before; + for (AbstractFeature feature : FeatureRegistry.getFeatureList()) { + if (feature instanceof GuiFeature && feature.isEnabled()) { + getMainPanel().add(new PanelDelegate((GuiFeature) feature, featureWhitelist == null || feature == featureWhitelist, this)); + } + } + + getMainPanel().setBackgroundColor(new Color(0,0,0, 100)); + } + + public static final Vec3[] facing = new Vec3[] { + new Vec3(0, 0.5, 2), + new Vec3(0.5, 0, 1), + new Vec3(0.5, 1, 3), + new Vec3(1, 0.5, 4), + }; + + public void removeAndAddMarker(Marker prev, Marker newM) { + if (prev != null) { + markerTreeMapByX.computeIfPresent(prev.getX(),(k,v) -> { + v.remove(prev); + if (v.isEmpty()) return null; + else return v; + }); + markerTreeMapByY.computeIfPresent(prev.getY(),(k,v) -> { + v.remove(prev); + if (v.isEmpty()) return null; + else return v; + }); + markerSet.remove(prev); + } + if (newM != null) { + markerTreeMapByX.compute(newM.getX(), (k,v) -> { + if (v == null) { + return new ArrayList<>(Arrays.asList(newM)); + } else { + v.add(newM); + return v; + } + }); + markerTreeMapByY.compute(newM.getY(), (k,v) -> { + if (v == null) { + return new ArrayList<>(Arrays.asList(newM)); + } else { + v.add(newM); + return v; + } + }); + markerSet.add(newM); + } + } + + public void setupMarkers() { + for (int i1 = 0; i1 < markers.length; i1++) { + Marker orig = markers[i1]; + Vec3 pt = facing[i1]; + markers[i1] = new Marker((int) (pt.xCoord * getMainPanel().getBounds().width), (int) (pt.yCoord * getMainPanel().getBounds().height), (int) pt.zCoord, this); + + removeAndAddMarker(orig, markers[i1]); + } + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + GlStateManager.pushMatrix(); + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + GlStateManager.translate(scaledResolution.getScaledWidth()/2, scaledResolution.getScaledHeight()/2, 0); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); + GlStateManager.color(1, 1, 1, 1); + fr.drawString("Right Click On Elements to Open Popup Menu", + -fr.getStringWidth("Right Click On Elements to Open Popup Menu")/2 + ,-fr.FONT_HEIGHT/2, -1); + GlStateManager.popMatrix(); + super.drawScreen(mouseX, mouseY, partialTicks); + } + + @Override + public void keyTyped(char typedChar, int keyCode) throws IOException { + try { + getMainPanel().keyPressed0(typedChar, keyCode); + + if (keyCode == 1) { + Minecraft.getMinecraft().displayGuiScreen(before); + } + } catch (Throwable e) { + if (!e.getMessage().contains("hack to stop")) + e.printStackTrace(); + } + } + + @Override + public void initGui() { + super.initGui(); + getMainPanel().setBounds(new Rectangle(0,0,Minecraft.getMinecraft().displayWidth,Minecraft.getMinecraft().displayHeight)); + markerTreeMapByX.clear(); + markerTreeMapByY.clear(); + markerSet.clear(); + setupMarkers(); + for (MPanel childComponent : getMainPanel().getChildComponents()) { + if (childComponent instanceof PanelDelegate) { + ((PanelDelegate) childComponent).rebuildMarker(); + } + } + + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/location/Marker.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/location/Marker.java new file mode 100644 index 00000000..7a0b9c58 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/location/Marker.java @@ -0,0 +1,45 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig.location; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +@Getter +@ToString +@AllArgsConstructor +public class Marker { + private final int x; + private final int y; + /** + * 0xABCDEFGH + * A: ? + * B: ? + * C: ? + * D: ? + * EF: 0~3 (TC 0x00 CL 0x01 BC 0x10 CR 0x11) + */ + private final int type; + private final Object parent; + + public int distanceSQ(Marker m2) { + return (m2.x - x)*(m2.x - x) + (m2.y - y)*(m2.y - y); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/location/PanelDelegate.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/location/PanelDelegate.java new file mode 100644 index 00000000..d9c402ba --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/guiconfig/location/PanelDelegate.java @@ -0,0 +1,403 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.guiconfig.location; + +import kr.syeyoung.dungeonsguide.config.types.GUIRectangle; +import kr.syeyoung.dungeonsguide.gui.elements.MPopupMenu; +import kr.syeyoung.dungeonsguide.gui.elements.MTooltip; +import kr.syeyoung.dungeonsguide.features.GuiFeature; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Tuple; +import net.minecraft.util.Vec3; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class PanelDelegate extends MPanel { + private final GuiFeature guiFeature; + private boolean draggable = false; + private GuiGuiLocationConfig guiGuiLocationConfig; + + private Set<Marker> markerSet = new HashSet<>(); + public PanelDelegate(GuiFeature guiFeature, boolean draggable, GuiGuiLocationConfig guiGuiLocationConfig) { + this.guiFeature = guiFeature; + this.draggable = draggable; + this.guiGuiLocationConfig = guiGuiLocationConfig; + } + + public void rebuildMarker() { + internallyThinking = guiFeature.getFeatureRect().getRectangleNoScale(); + applyConstraint(); + } + + @Override + public Rectangle getBounds() { + Rectangle rectangle = guiFeature.getFeatureRect().getRectangle(); + return new Rectangle(rectangle.x, rectangle.y, rectangle.width, rectangle.height); + } + + @Override + public void render(int absMousex, int absMousey, int relMouseX, int relMouseY, float partialTicks, Rectangle scissor) { + if (!guiFeature.isEnabled()) return; + + GlStateManager.pushMatrix(); + guiFeature.drawDemo(partialTicks); + GlStateManager.popMatrix(); + if (!draggable) return; + Gui.drawRect(0,0, 4, 4, 0xFFBBBBBB); + Gui.drawRect(0, getBounds().height - 4, 4, getBounds().height, 0xFFBBBBBB); + Gui.drawRect(getBounds().width - 4,0, getBounds().width, 4, 0xFFBBBBBB); + Gui.drawRect(getBounds().width - 4,getBounds().height - 4, getBounds().width, getBounds().height, 0xFFBBBBBB); + if (lastAbsClip.contains(absMousex, absMousey)) { + if (relMouseX < 4 && relMouseY < 4) { + Gui.drawRect(0,0, 4, 4, 0x55FFFFFF); + } else if (relMouseX < 4 && relMouseY > getBounds().height - 4) { + Gui.drawRect(0, getBounds().height - 4, 4, getBounds().height, 0x55FFFFFF); + } else if (relMouseX > getBounds().width - 4 && relMouseY > getBounds().height - 4) { + Gui.drawRect(getBounds().width - 4,getBounds().height - 4, getBounds().width, getBounds().height, 0x55FFFFFF); + } else if (relMouseX > getBounds().width - 4 && relMouseY < 4) { + Gui.drawRect(getBounds().width - 4,0, getBounds().width, 4, 0x55FFFFFF); + } else if (selectedPart == -2){ + Gui.drawRect(0,0, getBounds().width, getBounds().height, 0x55FFFFFF); + } + } + GlStateManager.enableBlend(); + } + + @Override + public void render0(double scale, Point parentPoint, Rectangle parentClip, int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks) { + GlStateManager.pushMatrix(); + super.render0(scale, parentPoint, parentClip, absMousex, absMousey, relMousex0, relMousey0, partialTicks); + GlStateManager.popMatrix(); + + if (snapped != null && selectedPart != -2) { + Tessellator tessellator = Tessellator.getInstance(); + GlStateManager.disableTexture2D(); + WorldRenderer worldRenderer = tessellator.getWorldRenderer(); + worldRenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); + GL11.glLineWidth(1); + for (Tuple<Marker[], EnumFacing.Axis> markerAxisTuple : snapped) { + if (markerAxisTuple.getSecond() == EnumFacing.Axis.X) { + worldRenderer.pos(markerAxisTuple.getFirst()[0].getX(), 0, 0).color(0,255,0,255).endVertex(); + worldRenderer.pos(markerAxisTuple.getFirst()[0].getX(), Minecraft.getMinecraft().displayHeight, 0).color(0,255,0,255).endVertex(); + } else { + worldRenderer.pos(0, markerAxisTuple.getFirst()[0].getY(), 0).color(0,255,0,255).endVertex(); + worldRenderer.pos(Minecraft.getMinecraft().displayWidth, markerAxisTuple.getFirst()[0].getY(), 0).color(0,255,0,255).endVertex(); + } + } + tessellator.draw(); + for (Marker marker : guiGuiLocationConfig.getMarkerSet()) { + Gui.drawRect(marker.getX(),marker.getY(), marker.getX()+1, marker.getY()+1, 0xFFFF0000); + } + } + } + + private int selectedPart = -2; + + private int lastX = 0; + private int lastY = 0; + + private Rectangle internallyThinking; + private Rectangle constraintApplied; + + private Set<Tuple<Marker[], EnumFacing.Axis>> snapped = new HashSet<>(); + + public void applyConstraint() { + constraintApplied = internallyThinking.getBounds(); + + // SNAP Moving Point. + snapped.clear(); + int scailingThreshold = 5; + if (selectedPart == 0){ + Point snapPt = new Point(constraintApplied.x +constraintApplied.width, constraintApplied.y + constraintApplied.height); + Optional<Marker> snapX, snapY; + SortedMap<Integer, List<Marker>> markerSortedMap = guiGuiLocationConfig.getMarkerTreeMapByX().subMap(snapPt.x-scailingThreshold, snapPt.x +scailingThreshold); + snapX = markerSortedMap.values().stream() + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .filter(a -> a.getParent() != this) + .min(Comparator.comparingInt(a -> (int) snapPt.distanceSq(a.getX(), a.getY()))); + markerSortedMap = guiGuiLocationConfig.getMarkerTreeMapByY().subMap(snapPt.y-scailingThreshold, snapPt.y +scailingThreshold); + snapY = markerSortedMap.values().stream() + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .filter(a -> a.getParent() != this) + .min(Comparator.comparingInt(a -> (int) snapPt.distanceSq(a.getX(), a.getY()))); + snapX.ifPresent(a -> { + snapPt.x = a.getX(); + }); + snapY.ifPresent(a -> { + snapPt.y = a.getY(); + }); + + constraintApplied = new Rectangle(constraintApplied.x, constraintApplied.y, snapPt.x - constraintApplied.x, snapPt.y - constraintApplied.y); + + + + int minWidth; + int minHeight; + if (guiFeature.isKeepRatio()) { + if (guiFeature.getDefaultRatio() >= 1) { + minHeight = constraintApplied.height < 0 ? -8 : 8; + minWidth = (int) (guiFeature.getDefaultRatio() * minHeight); + } else { + minWidth = constraintApplied.width < 0 ? -8 : 8; + minHeight = (int) (minWidth / guiFeature.getDefaultRatio()); + } + } else { + minWidth = constraintApplied.width < 0 ? -8 : 8; + minHeight = constraintApplied.height < 0 ? -8 : 8; + } + + + constraintApplied.width = Math.abs(constraintApplied.width) > Math.abs(minWidth) ? constraintApplied.width : + Math.abs(internallyThinking.width) > Math.abs(minWidth) ? internallyThinking.width : minWidth; + constraintApplied.height = Math.abs(constraintApplied.height) > Math.abs(minHeight) ? constraintApplied.height : + Math.abs(internallyThinking.height) > Math.abs(minHeight) ? internallyThinking.height : minHeight; + + if (guiFeature.isKeepRatio()) { + double ratio = guiFeature.getDefaultRatio(); + + int heightWhenWidthFix = (int) Math.abs(constraintApplied.width / ratio); + int widthWhenHeightFix = (int) Math.abs(ratio * constraintApplied.height); + if (Math.abs(heightWhenWidthFix) <= Math.abs(constraintApplied.height)) { + constraintApplied.height = constraintApplied.height < 0 ? -heightWhenWidthFix : heightWhenWidthFix; + } else if (Math.abs(widthWhenHeightFix) <= Math.abs(constraintApplied.width)) { + constraintApplied.width =constraintApplied.width < 0 ? - widthWhenHeightFix : widthWhenHeightFix; + } + } + + + snapX.ifPresent(a -> { + if (snapPt.x - constraintApplied.x == constraintApplied.width) { + Marker m = new Marker((int) (GuiGuiLocationConfig.facing[3].xCoord * constraintApplied.width) + constraintApplied.x, (int) (GuiGuiLocationConfig.facing[3].yCoord * constraintApplied.height) + constraintApplied.y, (int) GuiGuiLocationConfig.facing[3].zCoord, this); + snapped.add(new Tuple<>(new Marker[]{a, m}, EnumFacing.Axis.X)); + } + }); + snapY.ifPresent(a -> { + if (snapPt.y - constraintApplied.y == constraintApplied.height) { + Marker m = new Marker((int) (GuiGuiLocationConfig.facing[2].xCoord * constraintApplied.width) + constraintApplied.x, (int) (GuiGuiLocationConfig.facing[2].yCoord * constraintApplied.height) + constraintApplied.y, (int) GuiGuiLocationConfig.facing[2].zCoord, this); + snapped.add(new Tuple<>(new Marker[]{a, m}, EnumFacing.Axis.Y)); + } + }); + + if (constraintApplied.height < 0) { + constraintApplied.height = -constraintApplied.height; + constraintApplied.y -= constraintApplied.height; + } + + if (constraintApplied.width < 0) { + constraintApplied.width = -constraintApplied.width; + constraintApplied.x -= constraintApplied.width; + } + } else if (selectedPart == -1) { + for (int i : Arrays.asList(0,3,1,2)) { + Vec3 pt = GuiGuiLocationConfig.facing[i]; + Marker m = new Marker((int) (pt.xCoord * constraintApplied.width) + constraintApplied.x, (int) (pt.yCoord * constraintApplied.height) + constraintApplied.y, (int) pt.zCoord, this); + Optional<Marker> result = guiGuiLocationConfig.getMarkerTreeMapByX().subMap(m.getX()-scailingThreshold, m.getX() +scailingThreshold).values().stream() + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .filter(a -> a.getParent() != this) + .filter(a -> Math.abs(a.getX() - m.getX()) < scailingThreshold) + .filter(a -> ((a.getX() - pt.xCoord * constraintApplied.width) >= 0 + && (a.getX() - pt.xCoord * constraintApplied.width + constraintApplied.width) <= Minecraft.getMinecraft().displayWidth)) + .min(Comparator.comparingInt(a -> a.distanceSQ(m))); + if (result.isPresent()) { + int x = result.get().getX(); + constraintApplied.x = (int) (x - pt.xCoord * constraintApplied.width); + + snapped.add(new Tuple<>(new Marker[] {result.get(), m}, EnumFacing.Axis.X)); + break; + } + } + for (int i : Arrays.asList(1,2,0,3)) { + Vec3 pt = GuiGuiLocationConfig.facing[i]; + Marker m = new Marker((int) (pt.xCoord * constraintApplied.width) + constraintApplied.x, (int) (pt.yCoord * constraintApplied.height) + constraintApplied.y, (int) pt.zCoord, this); + Optional<Marker> result = guiGuiLocationConfig.getMarkerTreeMapByY().subMap(m.getY()-scailingThreshold, m.getY() +scailingThreshold).values().stream() + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .filter(a -> a.getParent() != this) + .filter(a -> Math.abs(a.getY() - m.getY()) < scailingThreshold) + .filter(a -> ((a.getY() - pt.yCoord * constraintApplied.height) >= 0 + && (a.getY() - pt.yCoord * constraintApplied.height+ constraintApplied.height) <= Minecraft.getMinecraft().displayHeight)) + .min(Comparator.comparingInt(a -> a.distanceSQ(m))); + if (result.isPresent()) { + int y = result.get().getY(); + constraintApplied.y = (int) (y - pt.yCoord * constraintApplied.height); + snapped.add(new Tuple<>(new Marker[] {result.get(), m}, EnumFacing.Axis.Y)); + break; + } + } + } + + if (constraintApplied.x < 0) constraintApplied.x = 0; + if (constraintApplied.y < 0) constraintApplied.y = 0; + if (constraintApplied.x + constraintApplied.width + 1 >=Minecraft.getMinecraft().displayWidth) constraintApplied.x = Minecraft.getMinecraft().displayWidth - constraintApplied.width - 1; + if (constraintApplied.y + constraintApplied.height + 1>= Minecraft.getMinecraft().displayHeight) constraintApplied.y = Minecraft.getMinecraft().displayHeight - constraintApplied.height - 1; + + + setupMarkers(); + } + + Marker[] markers = new Marker[4]; + public void setupMarkers() { + for (int i1 = 0; i1 < markers.length; i1++) { + Marker orig = markers[i1]; + + Vec3 pt = GuiGuiLocationConfig.facing[i1]; + markers[i1] = new Marker((int) (pt.xCoord * constraintApplied.width) + constraintApplied.x, (int) (pt.yCoord * constraintApplied.height) + constraintApplied.y, (int) pt.zCoord, this); + + guiGuiLocationConfig.removeAndAddMarker(orig, markers[i1]); + } + } + + MTooltip mTooltip; + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (!draggable) return; + if (!guiFeature.isEnabled()) return; + if (getTooltipsOpen() > 0) return; + if (!lastAbsClip.contains(absMouseX, absMouseY)) return; + if (mouseButton == 0) { + internallyThinking = guiFeature.getFeatureRect().getRectangleNoScale(); + if (relMouseX < 4 && relMouseY < 4) { // TL + selectedPart = 0; + internallyThinking.y += internallyThinking.height; + internallyThinking.height = -internallyThinking.height; + internallyThinking.x += internallyThinking.width; + internallyThinking.width = -internallyThinking.width; + } else if (relMouseX < 4 && relMouseY > getBounds().height - 4) { // BL + selectedPart = 0; + internallyThinking.x += internallyThinking.width; + internallyThinking.width = -internallyThinking.width; + } else if (relMouseX > getBounds().width - 4 && relMouseY > getBounds().height - 4) { // BR + selectedPart = 0; + } else if (relMouseX > getBounds().width - 4 && relMouseY < 4) { // TR + selectedPart = 0; + internallyThinking.y += internallyThinking.height; + internallyThinking.height = -internallyThinking.height; + } else { + selectedPart = -1; + } + lastX = absMouseX; + lastY = absMouseY; + applyConstraint(); + + } else if (getTooltipsOpen() == 0){ + if (mTooltip != null) mTooltip.close(); + mTooltip = new MPopupMenu(absMouseX, absMouseY, guiFeature.getTooltipForEditor(guiGuiLocationConfig)); + mTooltip.setScale(2.0f); + mTooltip.open(this); + } + throw new IllegalArgumentException("bruh, a hack to stop event progress"); + } + + @Override + public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) { + if (!draggable) return; + if (!guiFeature.isEnabled()) return; + if (selectedPart >= -1) { + guiFeature.setFeatureRect(new GUIRectangle(constraintApplied)); + } + + selectedPart = -2; + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + if (!draggable) return; + if (!guiFeature.isEnabled()) return; + int dx = (absMouseX - lastX); + int dy = (absMouseY - lastY); + if (selectedPart >= 0) { + Rectangle rectangle = internallyThinking; + + int prevWidth = rectangle.width; + int prevHeight= rectangle.height; + + rectangle.width = prevWidth + dx; + rectangle.height = prevHeight + dy; + + if (rectangle.height * prevHeight <= 0 && prevHeight != rectangle.height) { + rectangle.height += prevHeight < 0 ? 4 : -4; + } + if (rectangle.width * prevWidth <= 0 && prevWidth != rectangle.width) { + rectangle.width += prevWidth < 0 ? 4 : -4; + } + + + applyConstraint(); + guiFeature.setFeatureRect(new GUIRectangle(constraintApplied)); + lastX = absMouseX; + lastY = absMouseY; + throw new IllegalArgumentException("bruh, a hack to stop event progress"); + } else if (selectedPart == -1){ + Rectangle rectangle = internallyThinking; + rectangle.translate(dx, dy); + applyConstraint(); + guiFeature.setFeatureRect(new GUIRectangle(constraintApplied)); + lastX = absMouseX; + lastY = absMouseY; + } + } + + @Override + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX, int relMouseY) { + if (!draggable) return; + if (!guiFeature.isEnabled()) return; + if (getTooltipsOpen() > 0) return; + + if (selectedPart == -1) { + setCursor(EnumCursor.CLOSED_HAND); + } else if (selectedPart >= 0) { + if (internallyThinking.width < 0 && internallyThinking.height < 0) { + setCursor(EnumCursor.RESIZE_TL); + } else if (internallyThinking.width < 0 && internallyThinking.height >= 0) { + setCursor(EnumCursor.RESIZE_DL); + } else if (internallyThinking.width >= 0 && internallyThinking.height >= 0) { + setCursor(EnumCursor.RESIZE_DR); + } else if (internallyThinking.width >= 0 && internallyThinking.height < 0) { + setCursor(EnumCursor.RESIZE_TR); + } + } else if (lastAbsClip.contains(absMouseX, absMouseY)) { + if (relMouseX < 4 && relMouseY < 4) { + setCursor(EnumCursor.RESIZE_TL); + } else if (relMouseX < 4 && relMouseY > getBounds().height - 4) { + setCursor(EnumCursor.RESIZE_DL); + } else if (relMouseX > getBounds().width - 4 && relMouseY > getBounds().height - 4) { + setCursor(EnumCursor.RESIZE_DR); + } else if (relMouseX > getBounds().width - 4 && relMouseY < 4) { + setCursor(EnumCursor.RESIZE_TR); + } else { + setCursor(EnumCursor.OPEN_HAND); + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/AColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/AColor.java new file mode 100644 index 00000000..cdf86be4 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/AColor.java @@ -0,0 +1,63 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import lombok.Getter; +import lombok.Setter; + +import java.awt.*; + +@Getter +@Setter +public class AColor extends Color { + private boolean chroma; + private float chromaSpeed; + + public AColor(int r, int g, int b, int a) { + super(r, g, b, a); + } + + public AColor(int rgba, boolean hasalpha) { + super(rgba, hasalpha); + } + + public AColor(AColor clone) { + super(clone.getRGB(), true); + chroma = clone.isChroma(); + chromaSpeed = clone.getChromaSpeed(); + } + + public AColor multiplyAlpha(double multiplier) { + AColor aColor = new AColor(getRed(), getGreen(), getBlue(), (int) (getAlpha() * multiplier)); + aColor.chroma = this.chroma; + aColor.chromaSpeed = this.chromaSpeed; + return aColor; + } + + @Override + public String toString() { + return "AColor{" + + ", r="+getRed()+ + ", g="+getGreen()+ + ", b="+getBlue()+ + ", a="+getAlpha()+ + ", chromaSpeed=" + chromaSpeed + + '}'; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/GUIRectangle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/GUIRectangle.java new file mode 100644 index 00000000..4ee947b3 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/GUIRectangle.java @@ -0,0 +1,81 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import net.minecraft.client.Minecraft; + +import java.awt.*; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class GUIRectangle { + public GUIRectangle(Rectangle rectangle) { + if (rectangle.x < Minecraft.getMinecraft().displayWidth / 2) { + this.x = rectangle.x; + this.width = rectangle.width; + } else { + this.x = rectangle.x + rectangle.width - Minecraft.getMinecraft().displayWidth; + this.width = -rectangle.width; + } + + if (rectangle.y < Minecraft.getMinecraft().displayHeight / 2) { + this.y = rectangle.y; + this.height = rectangle.height; + } else { + this.y = rectangle.y +rectangle.height - Minecraft.getMinecraft().displayHeight; + this.height = -rectangle.height; + } + } + + private int x; + private int y; + private int width; + private int height; + + public Rectangle getRectangle() { + return getRectangleNoScale(); + } +// public Rectangle getRectangle(ScaledResolution scaledResolution) { +// double realX = (int) (x < 0 ? scaledResolution.getScaledWidth() + x : x); +// double realY = (int) (y < 0 ? scaledResolution.getScaledHeight() + y : y); +// +// return new Rectangle((int)Math.min(realX + width, realX), (int)Math.min(realY + height, realY), +// (int)Math.abs(width), (int)Math.abs(height)); +// } + public Rectangle getRectangleNoScale() { + int x = this.x, y = this.y; + if (Math.abs(x) > Minecraft.getMinecraft().displayWidth / 2) { + x = x < 0 ? -Minecraft.getMinecraft().displayWidth/2 : Minecraft.getMinecraft().displayWidth/2; + } + if (Math.abs(y) > Minecraft.getMinecraft().displayHeight / 2) { + y = y < 0 ? -Minecraft.getMinecraft().displayHeight/2 : Minecraft.getMinecraft().displayHeight/2; + } + + + double realX = (int) (x < 0 ? Minecraft.getMinecraft().displayWidth + x : x); + double realY = (int) (y < 0 ? Minecraft.getMinecraft().displayHeight + y : y); + + return new Rectangle((int)Math.min(realX + width, realX), (int)Math.min(realY + height, realY), + (int)Math.abs(width), (int)Math.abs(height)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCAColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCAColor.java new file mode 100644 index 00000000..49b162c0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCAColor.java @@ -0,0 +1,51 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +public class TCAColor implements TypeConverter<AColor> { + @Override + public String getTypeString() { + return "acolor"; + } + + @Override + public AColor deserialize(JsonElement element) { + if (element instanceof JsonPrimitive) + return new AColor(element.getAsInt(), true); + + JsonObject object = element.getAsJsonObject(); + AColor color = new AColor(object.get("color").getAsInt(), true); + color.setChroma(object.get("chroma").getAsBoolean()); + color.setChromaSpeed(object.get("chromaSpeed").getAsFloat()); + return color; + } + + @Override + public JsonElement serialize(AColor element) { + JsonObject object = new JsonObject(); + object.addProperty("color", element.getRGB()); + object.addProperty("chroma", element.isChroma()); + object.addProperty("chromaSpeed", element.getChromaSpeed()); + return object; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCBoolean.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCBoolean.java new file mode 100644 index 00000000..344984e2 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCBoolean.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +public class TCBoolean implements TypeConverter<Boolean> { + @Override + public String getTypeString() { + return "boolean"; + } + + @Override + public Boolean deserialize(JsonElement element) { + return element.getAsBoolean(); + } + + @Override + public JsonElement serialize(Boolean element) { + return new JsonPrimitive(element); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCColor.java new file mode 100644 index 00000000..d91b75be --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCColor.java @@ -0,0 +1,41 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +import java.awt.*; + +public class TCColor implements TypeConverter<Color> { + @Override + public String getTypeString() { + return "color"; + } + + @Override + public Color deserialize(JsonElement element) { + return new Color(element.getAsInt()); + } + + @Override + public JsonElement serialize(Color element) { + return new JsonPrimitive(element.getRGB()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCFloat.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCFloat.java new file mode 100644 index 00000000..6fc10b7d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCFloat.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +public class TCFloat implements TypeConverter<Float> { + @Override + public String getTypeString() { + return "float"; + } + + @Override + public Float deserialize(JsonElement element) { + return element.getAsFloat(); + } + + @Override + public JsonElement serialize(Float element) { + return new JsonPrimitive(element); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCGUIRectangle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCGUIRectangle.java new file mode 100644 index 00000000..61d21c93 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCGUIRectangle.java @@ -0,0 +1,50 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +public class TCGUIRectangle implements TypeConverter<GUIRectangle> { + @Override + public String getTypeString() { + return "guirect"; + } + + @Override + public GUIRectangle deserialize(JsonElement element) { + if (element == null) return null; + GUIRectangle rectangle = new GUIRectangle(); + rectangle.setX(((JsonObject)element).get("x").getAsInt()); + rectangle.setY(((JsonObject)element).get("y").getAsInt()); + rectangle.setWidth(((JsonObject)element).get("width").getAsInt()); + rectangle.setHeight(((JsonObject)element).get("height").getAsInt()); + return rectangle; + } + + @Override + public JsonElement serialize(GUIRectangle element) { + JsonObject object = new JsonObject(); + object.addProperty("x", element.getX()); + object.addProperty("y", element.getY()); + object.addProperty("width", element.getWidth()); + object.addProperty("height", element.getHeight()); + return object; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCInteger.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCInteger.java new file mode 100644 index 00000000..e407815c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCInteger.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +public class TCInteger implements TypeConverter<Integer> { + @Override + public String getTypeString() { + return "integer"; + } + + @Override + public Integer deserialize(JsonElement element) { + return element.getAsInt(); + } + + @Override + public JsonElement serialize(Integer element) { + return new JsonPrimitive(element); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCKeybind.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCKeybind.java new file mode 100644 index 00000000..4ae89395 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCKeybind.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +public class TCKeybind implements TypeConverter<Integer> { + @Override + public String getTypeString() { + return "keybind"; + } + + @Override + public Integer deserialize(JsonElement element) { + return element.getAsInt(); + } + + @Override + public JsonElement serialize(Integer element) { + return new JsonPrimitive(element); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCRectangle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCRectangle.java new file mode 100644 index 00000000..4d42de4d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCRectangle.java @@ -0,0 +1,51 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.awt.*; + +public class TCRectangle implements TypeConverter<Rectangle> { + @Override + public String getTypeString() { + return "rect"; + } + + @Override + public Rectangle deserialize(JsonElement element) { + Rectangle rectangle = new Rectangle(); + rectangle.x = ((JsonObject)element).get("x").getAsInt(); + rectangle.y = ((JsonObject)element).get("y").getAsInt(); + rectangle.width = ((JsonObject)element).get("width").getAsInt(); + rectangle.height = ((JsonObject)element).get("height").getAsInt(); + return rectangle; + } + + @Override + public JsonElement serialize(Rectangle element) { + JsonObject object = new JsonObject(); + object.addProperty("x", element.x); + object.addProperty("y", element.y); + object.addProperty("width", element.width); + object.addProperty("height", element.height); + return object; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCString.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCString.java new file mode 100644 index 00000000..d09ae81f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCString.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +public class TCString implements TypeConverter<String> { + @Override + public String getTypeString() { + return "string"; + } + + @Override + public String deserialize(JsonElement element) { + return element.getAsString(); + } + + @Override + public JsonElement serialize(String element) { + return new JsonPrimitive(element); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCStringList.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCStringList.java new file mode 100644 index 00000000..58bf838d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCStringList.java @@ -0,0 +1,51 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +import java.util.ArrayList; +import java.util.List; + +public class TCStringList implements TypeConverter<List<String>> { + @Override + public String getTypeString() { + return "stringlist"; + } + + @Override + public List<String> deserialize(JsonElement element) { + List<String> strList = new ArrayList<>(); + for (JsonElement jsonElement : element.getAsJsonArray()) { + strList.add(jsonElement.getAsString()); + } + return strList; + } + + @Override + public JsonElement serialize(List<String> element) { + JsonArray jsonElements = new JsonArray(); + for (String s : element) { + jsonElements.add(new JsonPrimitive(s)); + } + return jsonElements; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCTextStyle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCTextStyle.java new file mode 100644 index 00000000..9589b12b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCTextStyle.java @@ -0,0 +1,52 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; + +public class TCTextStyle implements TypeConverter<TextStyle> { + @Override + public String getTypeString() { + return "textstyle"; + } + + @Override + public TextStyle deserialize(JsonElement element) { + TextStyle textStyle = new TextStyle(); + textStyle.setColor(TypeConverterRegistry.getTypeConverter("acolor", AColor.class).deserialize(element.getAsJsonObject().get("color"))); + textStyle.setBackground(element.getAsJsonObject().has("background") ? TypeConverterRegistry.getTypeConverter("acolor", AColor.class).deserialize(element.getAsJsonObject().get("background")) + : new AColor(0x00777777, true)); + textStyle.setGroupName(element.getAsJsonObject().get("group").getAsString()); + if (element.getAsJsonObject().has("shadow")) + textStyle.setShadow(element.getAsJsonObject().get("shadow").getAsBoolean()); + return textStyle; + } + + @Override + public JsonElement serialize(TextStyle element) { + JsonObject jsonObject = new JsonObject(); + jsonObject.add("color", TypeConverterRegistry.getTypeConverter("acolor", AColor.class).serialize(element.getColor())); + jsonObject.add("background", TypeConverterRegistry.getTypeConverter("acolor", AColor.class).serialize(element.getBackground())); + jsonObject.addProperty("group", element.getGroupName()); + jsonObject.addProperty("shadow", element.isShadow()); + return jsonObject; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCTextStyleList.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCTextStyleList.java new file mode 100644 index 00000000..22068453 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TCTextStyleList.java @@ -0,0 +1,54 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; + +import java.util.ArrayList; +import java.util.List; + +public class TCTextStyleList implements TypeConverter<List<TextStyle>> { + @Override + public String getTypeString() { + return "list_textStyle"; + } + + @Override + public List<TextStyle> deserialize(JsonElement element) { + JsonArray arr = element.getAsJsonArray(); + TypeConverter<TextStyle> conv = TypeConverterRegistry.getTypeConverter("textstyle", TextStyle.class); + List<TextStyle> texts = new ArrayList<TextStyle>(); + for (JsonElement element2:arr) { + texts.add(conv.deserialize(element2)); + } + return texts; + } + + @Override + public JsonElement serialize(List<TextStyle> element) { + JsonArray array = new JsonArray(); + TypeConverter<TextStyle> conv = TypeConverterRegistry.getTypeConverter("textstyle", TextStyle.class); + for (TextStyle st:element) { + array.add(conv.serialize(st)); + } + return array; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TypeConverter.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TypeConverter.java new file mode 100644 index 00000000..0c954e7d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TypeConverter.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import com.google.gson.JsonElement; + +public interface TypeConverter<T> { + String getTypeString(); + + T deserialize(JsonElement element); + + JsonElement serialize(T element); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TypeConverterRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TypeConverterRegistry.java new file mode 100644 index 00000000..cadc71cc --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/config/types/TypeConverterRegistry.java @@ -0,0 +1,52 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.config.types; + +import java.util.HashMap; +import java.util.Map; + +public class TypeConverterRegistry { + private static final Map<String, TypeConverter> typeConverterMap = new HashMap<String, TypeConverter>(); + + public static void register(TypeConverter typeConverter) { + typeConverterMap.put(typeConverter.getTypeString(), typeConverter); + } + + public static TypeConverter getTypeConverter(String type_string) { + return typeConverterMap.get(type_string); + } + public static <T> TypeConverter<T> getTypeConverter(String type_string, Class<T> t) { + return (TypeConverter<T>)typeConverterMap.get(type_string); + } + + static { + register(new TCBoolean()); + register(new TCInteger()); + register(new TCRectangle()); + register(new TCGUIRectangle()); + register(new TCString()); + register(new TCColor()); + register(new TCFloat()); + register(new TCAColor()); + register(new TCTextStyleList()); + register(new TCTextStyle()); + register(new TCStringList()); + register(new TCKeybind()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/ActiveCosmetic.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/ActiveCosmetic.java new file mode 100644 index 00000000..c88bbbbc --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/ActiveCosmetic.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics; + +import lombok.Data; +import java.util.UUID; + +@Data +public class ActiveCosmetic { + private UUID activityUID; + private UUID playerUID; + private UUID cosmeticData; + private String username; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CosmeticData.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CosmeticData.java new file mode 100644 index 00000000..8b3ac3b4 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CosmeticData.java @@ -0,0 +1,32 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics; + + +import lombok.Data; + +import java.util.UUID; + +@Data +public class CosmeticData { + private UUID id; + private String cosmeticType; + private String reqPerm; + private String data; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CosmeticsManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CosmeticsManager.java new file mode 100644 index 00000000..c91a0895 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CosmeticsManager.java @@ -0,0 +1,292 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics; + +import kr.syeyoung.dungeonsguide.cosmetics.chatreplacers.*; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.cosmetics.chatreplacers.*; +import kr.syeyoung.dungeonsguide.events.PlayerListItemPacketEvent; +import kr.syeyoung.dungeonsguide.events.StompConnectedEvent; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.network.play.server.S38PacketPlayerListItem; +import net.minecraftforge.client.event.ClientChatReceivedEvent; +import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.ReflectionHelper; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; + +public class CosmeticsManager implements StompMessageHandler { + @Getter + private Map<UUID, CosmeticData> cosmeticDataMap = new ConcurrentHashMap<>(); + @Getter + private Map<UUID, ActiveCosmetic> activeCosmeticMap = new ConcurrentHashMap<>(); + @Getter + private Map<String, List<ActiveCosmetic>> activeCosmeticByType = new ConcurrentHashMap<>(); + @Getter + private Map<UUID, List<ActiveCosmetic>> activeCosmeticByPlayer = new ConcurrentHashMap<>(); + @Getter + private Map<String, List<ActiveCosmetic>> activeCosmeticByPlayerNameLowerCase = new ConcurrentHashMap<>(); + @Getter + private Set<String> perms = new CopyOnWriteArraySet<>(); + + public void requestActiveCosmetics() { + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload() + .method(StompHeader.SEND) + .header("destination", "/app/cosmetic.activelist") + ); + } + public void requestCosmeticsList() { + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload() + .method(StompHeader.SEND) + .header("destination", "/app/cosmetic.list") + ); + } + public void requestPerms() { + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload() + .method(StompHeader.SEND) + .header("destination", "/app/user.perms") + ); + } + public void setCosmetic(CosmeticData cosmetic) { + if (!perms.contains(cosmetic.getReqPerm())) return; + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload() + .method(StompHeader.SEND) + .header("destination", "/app/cosmetic.set") + .payload(cosmetic.getId().toString()) + ); + } + public void removeCosmetic(ActiveCosmetic activeCosmetic) { + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload() + .method(StompHeader.SEND) + .header("destination", "/app/cosmetic.remove") + .payload(activeCosmetic.getActivityUID().toString()) + ); + } + + @Override + public void handle(StompInterface stompInterface, StompPayload stompPayload) { + String destination = stompPayload.headers().get("destination"); + if (destination.equals("/topic/cosmetic.set")) { + JSONObject jsonObject = new JSONObject(stompPayload.payload()); + ActiveCosmetic activeCosmetic = new ActiveCosmetic(); + activeCosmetic.setActivityUID(UUID.fromString(jsonObject.getString("activityUID"))); + activeCosmetic.setPlayerUID(UUID.fromString(jsonObject.getString("playerUID"))); + if (jsonObject.isNull("cosmeticUID")) { + ActiveCosmetic activeCosmetic1 = activeCosmeticMap.remove(activeCosmetic.getActivityUID()); + + List<ActiveCosmetic> activeCosmetics = activeCosmeticByPlayer.computeIfAbsent(activeCosmetic.getPlayerUID(), a-> new CopyOnWriteArrayList<>()); + activeCosmetics.remove(activeCosmetic1); + + activeCosmetics = activeCosmeticByPlayerNameLowerCase.computeIfAbsent(activeCosmetic1.getUsername().toLowerCase(), a-> new CopyOnWriteArrayList<>()); + activeCosmetics.remove(activeCosmetic1); + + CosmeticData cosmeticData = cosmeticDataMap.get(activeCosmetic.getCosmeticData()); + if (cosmeticData != null) { + List<ActiveCosmetic> cosmeticsByTypeList = activeCosmeticByType.computeIfAbsent(cosmeticData.getCosmeticType(), a-> new CopyOnWriteArrayList<>()); + cosmeticsByTypeList.remove(activeCosmetic1); + } + } else { + activeCosmetic.setCosmeticData(UUID.fromString(jsonObject.getString("cosmeticUID"))); + activeCosmetic.setUsername(jsonObject.getString("username")); + + ActiveCosmetic previousThing = activeCosmeticMap.get(activeCosmetic.getActivityUID()); + activeCosmeticMap.put(activeCosmetic.getActivityUID(), activeCosmetic); + + CosmeticData cosmeticData = cosmeticDataMap.get(activeCosmetic.getCosmeticData()); + if (cosmeticData != null) { + List<ActiveCosmetic> cosmeticsByTypeList = activeCosmeticByType.computeIfAbsent(cosmeticData.getCosmeticType(), a-> new CopyOnWriteArrayList<>()); + cosmeticsByTypeList.add(activeCosmetic); + cosmeticsByTypeList.remove(previousThing); + } + List<ActiveCosmetic> activeCosmetics = activeCosmeticByPlayer.computeIfAbsent(activeCosmetic.getPlayerUID(), a-> new CopyOnWriteArrayList<>()); + activeCosmetics.add(activeCosmetic); + activeCosmetics.remove(previousThing); + + activeCosmetics = activeCosmeticByPlayerNameLowerCase.computeIfAbsent(activeCosmetic.getUsername().toLowerCase(), a-> new CopyOnWriteArrayList<>()); + activeCosmetics.add(activeCosmetic); + activeCosmetics.remove(previousThing); + } + + try { + if (Minecraft.getMinecraft().theWorld != null) { + EntityPlayer entityPlayer = Minecraft.getMinecraft().theWorld.getPlayerEntityByUUID(activeCosmetic.getPlayerUID()); + if (entityPlayer != null) entityPlayer.refreshDisplayName(); + } + } catch (Exception e) {e.printStackTrace();} + + } else if (destination.equals("/user/queue/reply/user.perms")) { + JSONArray object = new JSONArray(stompPayload.payload()); + Set<String> cache = new HashSet<>(); + for (Object o : object) { + cache.add((String) o); + } + this.perms = cache; + } else if (destination.equals("/user/queue/reply/cosmetic.activelist")) { + Map<UUID, ActiveCosmetic> activeCosmeticMap = new HashMap<>(); + JSONArray object = new JSONArray(stompPayload.payload()); + for (Object o : object) { + JSONObject jsonObject = (JSONObject) o; + ActiveCosmetic cosmeticData = new ActiveCosmetic(); + cosmeticData.setActivityUID(UUID.fromString(jsonObject.getString("activityUID"))); + cosmeticData.setPlayerUID(UUID.fromString(jsonObject.getString("playerUID"))); + cosmeticData.setCosmeticData(UUID.fromString(jsonObject.getString("cosmeticUID"))); + cosmeticData.setUsername(jsonObject.getString("username")); + + activeCosmeticMap.put(cosmeticData.getActivityUID(), cosmeticData); + try { + if (Minecraft.getMinecraft().theWorld != null) { + EntityPlayer entityPlayer = Minecraft.getMinecraft().theWorld.getPlayerEntityByUUID(cosmeticData.getPlayerUID()); + if (entityPlayer != null) entityPlayer.refreshDisplayName(); + } + } catch (Exception e) {e.printStackTrace();} + } + this.activeCosmeticMap = activeCosmeticMap; + rebuildCaches(); + } else if (destination.equals("/user/queue/reply/cosmetic.list")) { + JSONArray object = new JSONArray(stompPayload.payload()); + Map<UUID, CosmeticData> newCosmeticList = new HashMap<>(); + for (Object o : object) { + JSONObject jsonObject = (JSONObject) o; + CosmeticData cosmeticData = new CosmeticData(); + cosmeticData.setCosmeticType(jsonObject.getString("cosmeticType")); + cosmeticData.setReqPerm(jsonObject.getString("reqPerm")); + cosmeticData.setData(jsonObject.getString("data")); + cosmeticData.setId(UUID.fromString(jsonObject.getString("id"))); + + newCosmeticList.put(cosmeticData.getId(), cosmeticData); + } + + cosmeticDataMap = newCosmeticList; + rebuildCaches(); + } + } + + private void rebuildCaches() { + Map<String, List<ActiveCosmetic>> activeCosmeticByType = new HashMap<>(); + Map<UUID, List<ActiveCosmetic>> activeCosmeticByPlayer = new HashMap<>(); + Map<String, List<ActiveCosmetic>> activeCosmeticByPlayerName = new HashMap<>(); + for (ActiveCosmetic value : activeCosmeticMap.values()) { + CosmeticData cosmeticData = cosmeticDataMap.get(value.getCosmeticData()); + if (cosmeticData != null) { + List<ActiveCosmetic> cosmeticsByTypeList = activeCosmeticByType.computeIfAbsent(cosmeticData.getCosmeticType(), a-> new CopyOnWriteArrayList<>()); + cosmeticsByTypeList.add(value); + } + List<ActiveCosmetic> activeCosmetics = activeCosmeticByPlayer.computeIfAbsent(value.getPlayerUID(), a-> new CopyOnWriteArrayList<>()); + activeCosmetics.add(value); + activeCosmetics = activeCosmeticByPlayerName.computeIfAbsent(value.getUsername().toLowerCase(), a-> new CopyOnWriteArrayList<>()); + activeCosmetics.add(value); + } + + this.activeCosmeticByPlayerNameLowerCase = activeCosmeticByPlayerName; + this.activeCosmeticByPlayer = activeCosmeticByPlayer; + this.activeCosmeticByType = activeCosmeticByType; + } + + @SubscribeEvent + public void stompConnect(StompConnectedEvent stompConnectedEvent) { + stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder() + .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/topic/cosmetic.set").build()); + stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder() + .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/reply/user.perms").build()); + stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder() + .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/reply/cosmetic.activelist").build()); + stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder() + .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/reply/cosmetic.list").build()); + + requestCosmeticsList(); + requestActiveCosmetics(); + requestPerms(); + } + @Getter @Setter + private static List<IChatReplacer> iChatReplacers = new ArrayList<>(); + static { + iChatReplacers.add(new ChatReplacerViewProfile()); + iChatReplacers.add(new ChatReplacerPV()); + iChatReplacers.add(new ChatReplacerSocialOptions()); + iChatReplacers.add(new ChatReplacerCoop()); + iChatReplacers.add(new ChatReplacerMessage()); + iChatReplacers.add(new ChatReplacerChatByMe()); + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + try { + if (clientChatReceivedEvent.type == 2) return; + for (IChatReplacer iChatReplacer : iChatReplacers) { + if (iChatReplacer.isAcceptable(clientChatReceivedEvent)) { + iChatReplacer.translate(clientChatReceivedEvent, this); + return; + } + } + } catch (Throwable t) { + System.out.println(clientChatReceivedEvent.message); + t.printStackTrace(); + } + } + + + @SubscribeEvent + public void onTabList(PlayerListItemPacketEvent packetPlayerListItem) { + S38PacketPlayerListItem asd = packetPlayerListItem.getPacketPlayerListItem(); + if (asd.getAction() == S38PacketPlayerListItem.Action.ADD_PLAYER) { + if (Minecraft.getMinecraft().getNetHandler() == null) return; + + Map<UUID, NetworkPlayerInfo> playerInfoMap = ReflectionHelper.getPrivateValue(NetHandlerPlayClient.class, Minecraft.getMinecraft().getNetHandler(), "playerInfoMap", "field_147310_i","i"); + for (S38PacketPlayerListItem.AddPlayerData entry : asd.getEntries()) { + playerInfoMap.remove(entry.getProfile().getId()); + playerInfoMap.put(entry.getProfile().getId(), new CustomNetworkPlayerInfo(entry)); + } + } + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public void nameFormat(PlayerEvent.NameFormat nameFormat) { + List<ActiveCosmetic> activeCosmetics = activeCosmeticByPlayer.get(nameFormat.entityPlayer.getGameProfile().getId()); + if (activeCosmetics == null) return; + CosmeticData color=null, prefix=null; + for (ActiveCosmetic activeCosmetic : activeCosmetics) { + CosmeticData cosmeticData = cosmeticDataMap.get(activeCosmetic.getCosmeticData()); + if (cosmeticData !=null && cosmeticData.getCosmeticType().equals("color")) { + color = cosmeticData; + } else if (cosmeticData != null && cosmeticData.getCosmeticType().equals("prefix")) { + prefix = cosmeticData; + } + } + + + if (color != null) + nameFormat.displayname = color.getData().replace("&","§")+nameFormat.username; + + if (prefix != null) + nameFormat.displayname = prefix.getData().replace("&","§")+" "+nameFormat.displayname; + + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CustomNetworkPlayerInfo.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CustomNetworkPlayerInfo.java new file mode 100644 index 00000000..cfbf1fc0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CustomNetworkPlayerInfo.java @@ -0,0 +1,103 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics; + +import com.mojang.authlib.GameProfile; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.network.play.server.S38PacketPlayerListItem; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; + +import java.util.List; + +public class CustomNetworkPlayerInfo extends NetworkPlayerInfo { + public CustomNetworkPlayerInfo(GameProfile p_i46294_1_) { + super(p_i46294_1_); + } + + public CustomNetworkPlayerInfo(S38PacketPlayerListItem.AddPlayerData p_i46295_1_) { + super(p_i46295_1_); + setDisplayName(super.getDisplayName()); + } + + + private IChatComponent displayName; + private String playernameLowercase; + private String unformatted; + private String actualName; + @Override + public void setDisplayName(IChatComponent displayNameIn) { + displayName = displayNameIn; + if (displayName == null) { + playernameLowercase = null; + unformatted = null; + return; + } + + unformatted = displayName.getUnformattedText(); + + + actualName = ""; + for (String s : unformatted.split(" ")) { + String strippped = TextUtils.stripColor(s); + if (strippped.startsWith("[")) continue; + actualName = strippped; + break; + } + playernameLowercase = actualName.toLowerCase(); + } + + public IChatComponent getDisplayName() + { + + String semi_name; + String actualName; + List<ActiveCosmetic> activeCosmetics; + if (playernameLowercase != null) { + activeCosmetics = DungeonsGuide.getDungeonsGuide().getCosmeticsManager().getActiveCosmeticByPlayerNameLowerCase().get(playernameLowercase); + semi_name = unformatted; + actualName = this.actualName; + } else { + semi_name = ScorePlayerTeam.formatPlayerName(super.getPlayerTeam(), super.getGameProfile().getName()); + actualName = ""; + for (String s : semi_name.split(" ")) { + String strippped = TextUtils.stripColor(s); + if (strippped.startsWith("[")) continue; + actualName = strippped; + break; + } + activeCosmetics = DungeonsGuide.getDungeonsGuide().getCosmeticsManager().getActiveCosmeticByPlayerNameLowerCase().get(actualName.toLowerCase()); + } + + + if (activeCosmetics == null) return displayName; + CosmeticData color=null; + for (ActiveCosmetic activeCosmetic : activeCosmetics) { + CosmeticData cosmeticData = DungeonsGuide.getDungeonsGuide().getCosmeticsManager().getCosmeticDataMap().get(activeCosmetic.getCosmeticData()); + if (cosmeticData.getCosmeticType().equals("color")) color = cosmeticData; + } + + if (color != null) semi_name = semi_name.replace(actualName, color.getData()+actualName); + + return new ChatComponentText(semi_name); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CustomPacketPlayerListItem.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CustomPacketPlayerListItem.java new file mode 100644 index 00000000..1aa71d58 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/CustomPacketPlayerListItem.java @@ -0,0 +1,38 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics; + +import kr.syeyoung.dungeonsguide.events.PlayerListItemPacketEvent; +import net.minecraft.network.play.INetHandlerPlayClient; +import net.minecraft.network.play.server.S38PacketPlayerListItem; +import net.minecraftforge.common.MinecraftForge; + +public class CustomPacketPlayerListItem extends S38PacketPlayerListItem { + public CustomPacketPlayerListItem(S38PacketPlayerListItem packet) { + super(packet.getAction()); + getEntries().addAll(packet.getEntries()); + } + + @Override + public void processPacket(INetHandlerPlayClient handler) { + super.processPacket(handler); + + MinecraftForge.EVENT_BUS.post(new PlayerListItemPacketEvent(this)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/IChatReplacer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/IChatReplacer.java new file mode 100644 index 00000000..b2bcfc0e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/IChatReplacer.java @@ -0,0 +1,26 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics; + +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +public interface IChatReplacer { + boolean isAcceptable(ClientChatReceivedEvent event); + void translate(ClientChatReceivedEvent event, CosmeticsManager cosmeticsManager); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerChatByMe.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerChatByMe.java new file mode 100644 index 00000000..8c99847a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerChatByMe.java @@ -0,0 +1,106 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics.chatreplacers; + +import kr.syeyoung.dungeonsguide.cosmetics.ActiveCosmetic; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticData; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticsManager; +import kr.syeyoung.dungeonsguide.cosmetics.IChatReplacer; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatStyle; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.Tuple; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.ArrayList; +import java.util.List; + +public class ChatReplacerChatByMe implements IChatReplacer { + @Override + public boolean isAcceptable(ClientChatReceivedEvent event) { + for (IChatComponent sibling : event.message.getSiblings()) { + if (sibling.getUnformattedTextForChat().startsWith(": ")) return true; + } + return false; + } + + @Override + public void translate(ClientChatReceivedEvent event, CosmeticsManager cosmeticsManager) { + List<Tuple<IChatComponent, IChatComponent>> replaceMents = new ArrayList<>(); + List<IChatComponent> iChatComponents = new ArrayList<>( event.message.getSiblings() ); + List<IChatComponent> hasMsg = new ArrayList<>(); + for (IChatComponent sibling : iChatComponents) { + if (sibling.getUnformattedTextForChat().startsWith(": ")) break; + hasMsg.add(sibling); + } + iChatComponents.removeAll(hasMsg); + + ChatComponentText chatComponents = new ChatComponentText(""); + chatComponents.getSiblings().addAll(hasMsg); + ChatStyle origStyle = hasMsg.get(0).getChatStyle(); + String name = chatComponents.getFormattedText(); + + String[] splited = name.split(" "); + String actualName = splited[splited.length-1]; + + List<ActiveCosmetic> cDatas = cosmeticsManager.getActiveCosmeticByPlayerNameLowerCase().get(TextUtils.stripColor(actualName).toLowerCase()); + if (cDatas == null) return; + CosmeticData color=null, prefix=null; + for (ActiveCosmetic activeCosmetic : cDatas) { + CosmeticData cosmeticData = cosmeticsManager.getCosmeticDataMap().get(activeCosmetic.getCosmeticData()); + if (cosmeticData !=null && cosmeticData.getCosmeticType().equals("color")) { + color = cosmeticData; + } else if (cosmeticData != null && cosmeticData.getCosmeticType().equals("prefix")) { + prefix = cosmeticData; + } + } + + String building = ""; + if (prefix != null) building += prefix.getData().replace("&", "§") + " "; + for (int i = 0; i < splited.length-1; i++) { + building += splited[i] +" "; + } + + if (color != null) { + String nick = splited[splited.length-1]; + building += color.getData().replace("&","§"); + boolean foundLegitChar = false; + boolean foundColor = false; + for (char c : nick.toCharArray()) { + if (foundColor) { + foundColor = false; continue; + } + if (c == '§' && !foundLegitChar) foundColor = true; + else { + foundLegitChar = true; + building += c; + } + } + } else { + building += splited[splited.length-1] ; + } + + ChatComponentText chatComponents1 = new ChatComponentText(building); + chatComponents1.setChatStyle(origStyle); + event.message.getSiblings().clear(); + event.message.getSiblings().add(chatComponents1); + event.message.getSiblings().addAll(iChatComponents); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerCoop.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerCoop.java new file mode 100644 index 00000000..a1491dd5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerCoop.java @@ -0,0 +1,119 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics.chatreplacers; + +import kr.syeyoung.dungeonsguide.cosmetics.ActiveCosmetic; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticData; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticsManager; +import kr.syeyoung.dungeonsguide.cosmetics.IChatReplacer; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.Tuple; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.ArrayList; +import java.util.List; + +public class ChatReplacerCoop implements IChatReplacer { + @Override + public boolean isAcceptable(ClientChatReceivedEvent event) { + for (IChatComponent sibling : event.message.getSiblings()) { + if (sibling.getUnformattedTextForChat().startsWith("§bCo-op > ")) return true; + } + return false; + } + + @Override + public void translate(ClientChatReceivedEvent event, CosmeticsManager cosmeticsManager) { + List<Tuple<IChatComponent, IChatComponent>> replaceMents = new ArrayList<>(); + List<IChatComponent> iChatComponents = new ArrayList<>( event.message.getSiblings() ); + IChatComponent sibling = iChatComponents.get(0); iChatComponents.remove(sibling); + + + String[] splitInto = sibling.getUnformattedTextForChat().split(" "); + int lastValidNickname = -1; + int lastprefix = -1; + for (int i = 0; i < splitInto.length; i++) { + String s = TextUtils.stripColor(splitInto[i]); + char c = s.charAt(0); + if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-') { + lastValidNickname = i; + } + } + if (lastValidNickname == -1) return; + + if (lastValidNickname -1 >= 0 && TextUtils.stripColor(splitInto[lastValidNickname - 1]).charAt(0) == '[') lastprefix = lastValidNickname -1; + else lastprefix = lastValidNickname; + + + List<ActiveCosmetic> cDatas = cosmeticsManager.getActiveCosmeticByPlayerNameLowerCase().get(TextUtils.stripColor(splitInto[lastValidNickname].substring(0, splitInto[lastValidNickname].length()-1)).toLowerCase()); + + if (cDatas == null) return; + + CosmeticData color = null, prefix = null; + for (ActiveCosmetic activeCosmetic : cDatas) { + CosmeticData cosmeticData = cosmeticsManager.getCosmeticDataMap().get(activeCosmetic.getCosmeticData()); + if (cosmeticData != null && cosmeticData.getCosmeticType().equals("color")) { + color = cosmeticData; + } else if (cosmeticData != null && cosmeticData.getCosmeticType().equals("prefix")) { + prefix = cosmeticData; + } + } + + String building = ""; + for (int i = 0; i < lastprefix; i++) { + building += splitInto[i] +" "; + } + if (prefix != null) building += prefix.getData().replace("&", "§") + " "; + for (int i = lastprefix; i < lastValidNickname; i++) { + building += splitInto[i] +" "; + } + if (color != null) { + String nick = splitInto[lastValidNickname]; + building += color.getData().replace("&","§"); + boolean foundLegitChar = false; + boolean foundColor = false; + for (char c : nick.toCharArray()) { + if (foundColor) { + foundColor = false; continue; + } + if (c == '§' && !foundLegitChar) foundColor = true; + else { + foundLegitChar = true; + building += c; + } + } + building += " "; + } else { + building += splitInto[lastValidNickname] + " "; + } + for (int i = lastValidNickname+1; i<splitInto.length; i++) { + building += splitInto[i] + " "; + } + if (sibling.getUnformattedTextForChat().charAt(sibling.getUnformattedText().length()-1) != ' ') + building = building.substring(0, building.length() - 1); + + ChatComponentText chatComponents1 = new ChatComponentText(building); + chatComponents1.setChatStyle(sibling.getChatStyle()); + event.message.getSiblings().clear(); + event.message.getSiblings().add(chatComponents1); + event.message.getSiblings().addAll(iChatComponents); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerMessage.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerMessage.java new file mode 100644 index 00000000..b7c772f1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerMessage.java @@ -0,0 +1,106 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics.chatreplacers; + +import kr.syeyoung.dungeonsguide.cosmetics.ActiveCosmetic; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticData; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticsManager; +import kr.syeyoung.dungeonsguide.cosmetics.IChatReplacer; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatStyle; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.Tuple; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.ArrayList; +import java.util.List; + +public class ChatReplacerMessage implements IChatReplacer { + @Override + public boolean isAcceptable(ClientChatReceivedEvent event) { + for (IChatComponent sibling : event.message.getSiblings()) { + if (sibling.getChatStyle() != null && sibling.getChatStyle().getChatClickEvent() != null && sibling.getChatStyle().getChatClickEvent().getValue().startsWith("/msg")) return true; + } + return false; + } + + @Override + public void translate(ClientChatReceivedEvent event, CosmeticsManager cosmeticsManager) { + List<Tuple<IChatComponent, IChatComponent>> replaceMents = new ArrayList<>(); + List<IChatComponent> iChatComponents = new ArrayList<>( event.message.getSiblings() ); + List<IChatComponent> hasMsg = new ArrayList<>(); + for (IChatComponent sibling : iChatComponents) { + if (sibling.getChatStyle() != null && sibling.getChatStyle().getChatClickEvent() != null && sibling.getChatStyle().getChatClickEvent().getValue().startsWith("/msg")) { + hasMsg.add(sibling); + } + } + iChatComponents.removeAll(hasMsg); + + ChatComponentText chatComponents = new ChatComponentText(""); + chatComponents.getSiblings().addAll(hasMsg); + ChatStyle origStyle = hasMsg.get(0).getChatStyle(); + String name = chatComponents.getFormattedText(); + + + String[] splited = name.split(" "); + String actualName = splited[splited.length-1]; + + List<ActiveCosmetic> cDatas = cosmeticsManager.getActiveCosmeticByPlayerNameLowerCase().get(TextUtils.stripColor(actualName).toLowerCase()); + if (cDatas == null || splited.length > 2) return; + CosmeticData color=null, prefix=null; + for (ActiveCosmetic activeCosmetic : cDatas) { + CosmeticData cosmeticData = cosmeticsManager.getCosmeticDataMap().get(activeCosmetic.getCosmeticData()); + if (cosmeticData !=null && cosmeticData.getCosmeticType().equals("color")) { + color = cosmeticData; + } else if (cosmeticData != null && cosmeticData.getCosmeticType().equals("prefix")) { + prefix = cosmeticData; + } + } + + String building = ""; + if (prefix != null) building += prefix.getData().replace("&", "§") + " "; + if (splited.length == 2) building += splited[0] +" "; + + if (color != null) { + String nick = splited[1]; + building += color.getData().replace("&","§"); + boolean foundLegitChar = false; + boolean foundColor = false; + for (char c : nick.toCharArray()) { + if (foundColor) { + foundColor = false; continue; + } + if (c == '§' && !foundLegitChar) foundColor = true; + else { + foundLegitChar = true; + building += c; + } + } + } else { + building += splited[1] ; + } + + ChatComponentText chatComponents1 = new ChatComponentText(building); + chatComponents1.setChatStyle(origStyle); + event.message.getSiblings().clear(); + event.message.getSiblings().add(chatComponents1); + event.message.getSiblings().addAll(iChatComponents); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerPV.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerPV.java new file mode 100644 index 00000000..e5e4053f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerPV.java @@ -0,0 +1,119 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics.chatreplacers; + +import kr.syeyoung.dungeonsguide.cosmetics.ActiveCosmetic; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticData; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticsManager; +import kr.syeyoung.dungeonsguide.cosmetics.IChatReplacer; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.util.ChatComponentText; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.List; + + +// Bug 289 - mod conflict with NEU (Replaces /socialoptions with /pv) +public class ChatReplacerPV implements IChatReplacer { + @Override + public boolean isAcceptable(ClientChatReceivedEvent event) { + if (event.message.getChatStyle() != null && event.message.getChatStyle().getChatClickEvent() != null && event.message.getChatStyle().getChatClickEvent().getValue().startsWith("/pv")) return true; + return false; + } + + @Override + public void translate(ClientChatReceivedEvent event, CosmeticsManager cosmeticsManager) { + if (event.message.getChatStyle() != null && event.message.getChatStyle().getChatClickEvent() != null && event.message.getChatStyle().getChatClickEvent().getValue().startsWith("/pv")) { + String username = event.message.getChatStyle().getChatClickEvent().getValue().split(" ")[1]; + List<ActiveCosmetic> cDatas = cosmeticsManager.getActiveCosmeticByPlayerNameLowerCase().get(username.toLowerCase()); + + if (cDatas != null) { + CosmeticData color=null, prefix=null; + for (ActiveCosmetic activeCosmetic : cDatas) { + CosmeticData cosmeticData = cosmeticsManager.getCosmeticDataMap().get(activeCosmetic.getCosmeticData()); + if (cosmeticData !=null && cosmeticData.getCosmeticType().equals("color")) { + color = cosmeticData; + } else if (cosmeticData != null && cosmeticData.getCosmeticType().equals("prefix")) { + prefix = cosmeticData; + } + } + + String[] splitInto = event.message.getUnformattedTextForChat().split(" "); + int lastValidNickname = -1; + int lastprefix = -1; + for (int i = 0; i < splitInto.length; i++) { + String s = splitInto[i]; + if (s.startsWith("§7")) s = s.substring(2); + char c = s.charAt(0); + if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-') { + lastValidNickname = i; + if (i >= 1) { + String str = TextUtils.stripColor(splitInto[i-1]); + if (str.startsWith("[") && str.endsWith("]"))break; + } + } + } + if (lastValidNickname == -1) return; + + if (lastValidNickname -1 >= 0 && TextUtils.stripColor(splitInto[lastValidNickname - 1]).charAt(0) == '[') lastprefix = lastValidNickname -1; + else lastprefix = lastValidNickname; + + String building = ""; + for (int i = 0; i < lastprefix; i++) { + building += splitInto[i] +" "; + } + if (prefix != null) building += prefix.getData().replace("&", "§") + " "; + for (int i = lastprefix; i < lastValidNickname; i++) { + building += splitInto[i] +" "; + } + if (color != null) { + String nick = splitInto[lastValidNickname]; + building += color.getData().replace("&","§"); + boolean foundLegitChar = false; + boolean foundColor = false; + for (char c : nick.toCharArray()) { + if (foundColor) { + foundColor = false; continue; + } + if (c == '§' && !foundLegitChar) foundColor = true; + else { + foundLegitChar = true; + building += c; + } + } + building += " "; + } else { + building += splitInto[lastValidNickname] + " "; + } + for (int i = lastValidNickname+1; i<splitInto.length; i++) { + building += splitInto[i] + " "; + } + if (event.message.getUnformattedTextForChat().charAt(event.message.getUnformattedTextForChat().length()-1) != ' ') + building = building.substring(0, building.length() - 1); + + ChatComponentText newChatCompText = new ChatComponentText(building); + newChatCompText.setChatStyle(event.message.getChatStyle()); + newChatCompText.getSiblings().addAll(event.message.getSiblings()); + + event.message = newChatCompText; + } + } + + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerSocialOptions.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerSocialOptions.java new file mode 100644 index 00000000..adf70075 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerSocialOptions.java @@ -0,0 +1,117 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics.chatreplacers; + +import kr.syeyoung.dungeonsguide.cosmetics.ActiveCosmetic; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticData; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticsManager; +import kr.syeyoung.dungeonsguide.cosmetics.IChatReplacer; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.util.ChatComponentText; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.List; + +public class ChatReplacerSocialOptions implements IChatReplacer { + @Override + public boolean isAcceptable(ClientChatReceivedEvent event) { + if (event.message.getChatStyle() != null && event.message.getChatStyle().getChatClickEvent() != null && event.message.getChatStyle().getChatClickEvent().getValue().startsWith("/socialoptions")) return true; + return false; + } + + @Override + public void translate(ClientChatReceivedEvent event, CosmeticsManager cosmeticsManager) { + if (event.message.getChatStyle() != null && event.message.getChatStyle().getChatClickEvent() != null && event.message.getChatStyle().getChatClickEvent().getValue().startsWith("/socialoptions")) { + String username = event.message.getChatStyle().getChatClickEvent().getValue().split(" ")[1]; + List<ActiveCosmetic> cDatas = cosmeticsManager.getActiveCosmeticByPlayerNameLowerCase().get(username.toLowerCase()); + + if (cDatas != null) { + CosmeticData color=null, prefix=null; + for (ActiveCosmetic activeCosmetic : cDatas) { + CosmeticData cosmeticData = cosmeticsManager.getCosmeticDataMap().get(activeCosmetic.getCosmeticData()); + if (cosmeticData !=null && cosmeticData.getCosmeticType().equals("color")) { + color = cosmeticData; + } else if (cosmeticData != null && cosmeticData.getCosmeticType().equals("prefix")) { + prefix = cosmeticData; + } + } + + String[] splitInto = event.message.getUnformattedTextForChat().split(" "); + int lastValidNickname = -1; + int lastprefix = -1; + for (int i = 0; i < splitInto.length; i++) { + String s = splitInto[i]; + if (s.startsWith("§7")) s = s.substring(2); + char c = s.charAt(0); + if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-') { + lastValidNickname = i; + if (i >= 1) { + String str = TextUtils.stripColor(splitInto[i-1]); + if (str.startsWith("[") && str.endsWith("]"))break; + } + } + } + if (lastValidNickname == -1) return; + + if (lastValidNickname -1 >= 0 && TextUtils.stripColor(splitInto[lastValidNickname - 1]).charAt(0) == '[') lastprefix = lastValidNickname -1; + else lastprefix = lastValidNickname; + + String building = ""; + for (int i = 0; i < lastprefix; i++) { + building += splitInto[i] +" "; + } + if (prefix != null) building += prefix.getData().replace("&", "§") + " "; + for (int i = lastprefix; i < lastValidNickname; i++) { + building += splitInto[i] +" "; + } + if (color != null) { + String nick = splitInto[lastValidNickname]; + building += color.getData().replace("&","§"); + boolean foundLegitChar = false; + boolean foundColor = false; + for (char c : nick.toCharArray()) { + if (foundColor) { + foundColor = false; continue; + } + if (c == '§' && !foundLegitChar) foundColor = true; + else { + foundLegitChar = true; + building += c; + } + } + building += " "; + } else { + building += splitInto[lastValidNickname] + " "; + } + for (int i = lastValidNickname+1; i<splitInto.length; i++) { + building += splitInto[i] + " "; + } + if (event.message.getUnformattedTextForChat().charAt(event.message.getUnformattedTextForChat().length()-1) != ' ') + building = building.substring(0, building.length() - 1); + + ChatComponentText newChatCompText = new ChatComponentText(building); + newChatCompText.setChatStyle(event.message.getChatStyle()); + newChatCompText.getSiblings().addAll(event.message.getSiblings()); + + event.message = newChatCompText; + } + } + + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerViewProfile.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerViewProfile.java new file mode 100644 index 00000000..dd5bbd70 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/cosmetics/chatreplacers/ChatReplacerViewProfile.java @@ -0,0 +1,128 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.cosmetics.chatreplacers; + +import kr.syeyoung.dungeonsguide.cosmetics.ActiveCosmetic; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticData; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticsManager; +import kr.syeyoung.dungeonsguide.cosmetics.IChatReplacer; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.Tuple; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class ChatReplacerViewProfile implements IChatReplacer { + @Override + public boolean isAcceptable(ClientChatReceivedEvent event) { + for (IChatComponent sibling : event.message.getSiblings()) { + if (sibling.getChatStyle() != null && sibling.getChatStyle().getChatClickEvent() != null && sibling.getChatStyle().getChatClickEvent().getValue().startsWith("/viewprofile ")) return true; + } + return false; + } + + @Override + public void translate(ClientChatReceivedEvent event, CosmeticsManager cosmeticsManager) { + List<Tuple<IChatComponent, IChatComponent>> replaceMents = new ArrayList<>(); + for (IChatComponent sibling : event.message.getSiblings()) { + if (sibling.getChatStyle() != null && sibling.getChatStyle().getChatClickEvent() != null && sibling.getChatStyle().getChatClickEvent().getValue().startsWith("/viewprofile ")) { + String uid = sibling.getChatStyle().getChatClickEvent().getValue().split(" ")[1]; + List<ActiveCosmetic> cDatas = cosmeticsManager.getActiveCosmeticByPlayer().get(UUID.fromString(uid)); + + if (cDatas != null) { + CosmeticData color=null, prefix=null; + for (ActiveCosmetic activeCosmetic : cDatas) { + CosmeticData cosmeticData = cosmeticsManager.getCosmeticDataMap().get(activeCosmetic.getCosmeticData()); + if (cosmeticData !=null && cosmeticData.getCosmeticType().equals("color")) { + color = cosmeticData; + } else if (cosmeticData != null && cosmeticData.getCosmeticType().equals("prefix")) { + prefix = cosmeticData; + } + } + + String[] splitInto = sibling.getUnformattedTextForChat().split(" "); + int lastValidNickname = -1; + int lastprefix = -1; + for (int i = 0; i < splitInto.length; i++) { + String s = TextUtils.stripColor(splitInto[i]); + char c = s.charAt(0); + if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-') { + lastValidNickname = i; + if (i >= 1) { + String str = TextUtils.stripColor(splitInto[i-1]); + if (str.startsWith("[") && str.endsWith("]"))break; + } + } + } + if (lastValidNickname == -1) continue; + + if (lastValidNickname -1 >= 0 && TextUtils.stripColor(splitInto[lastValidNickname - 1]).charAt(0) == '[') lastprefix = lastValidNickname -1; + else lastprefix = lastValidNickname; + + String building = ""; + for (int i = 0; i < lastprefix; i++) { + building += splitInto[i] +" "; + } + if (prefix != null) building += prefix.getData().replace("&", "§") + " "; + for (int i = lastprefix; i < lastValidNickname; i++) { + building += splitInto[i] +" "; + } + if (color != null) { + String nick = splitInto[lastValidNickname]; + building += color.getData().replace("&","§"); + boolean foundLegitChar = false; + boolean foundColor = false; + for (char c : nick.toCharArray()) { + if (foundColor) { + foundColor = false; continue; + } + if (c == '§' && !foundLegitChar) foundColor = true; + else { + foundLegitChar = true; + building += c; + } + } + building += " "; + } else { + building += splitInto[lastValidNickname] + " "; + } + for (int i = lastValidNickname+1; i<splitInto.length; i++) { + building += splitInto[i] + " "; + } + if (sibling.getUnformattedTextForChat().charAt(sibling.getUnformattedText().length()-1) != ' ') + building = building.substring(0, building.length() - 1); + + ChatComponentText newChatCompText = new ChatComponentText(building); + newChatCompText.setChatStyle(sibling.getChatStyle()); + replaceMents.add(new Tuple<>(sibling, newChatCompText)); + break; + } + } + } + + for (Tuple<IChatComponent, IChatComponent> replaceMent : replaceMents) { + int index = event.message.getSiblings().indexOf(replaceMent.getFirst()); + event.message.getSiblings().set(index, replaceMent.getSecond()); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonActionManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonActionManager.java new file mode 100644 index 00000000..17aa0bbf --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonActionManager.java @@ -0,0 +1,35 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon; + +import lombok.Getter; +import net.minecraft.util.Vec3; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DungeonActionManager { + @Getter + private static final Map<Integer , Vec3> spawnLocation = new HashMap<Integer, Vec3>(); + + @Getter + private static final List<Integer> killeds = new ArrayList<Integer>(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonContext.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonContext.java new file mode 100755 index 00000000..fd2b8770 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonContext.java @@ -0,0 +1,207 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon; + +import kr.syeyoung.dungeonsguide.dungeon.events.*; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonSpecificDataProvider; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonSpecificDataProviderRegistry; +import kr.syeyoung.dungeonsguide.dungeon.events.*; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.events.BossroomEnterEvent; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.impl.dungeon.FeatureDungeonMap; +import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessor; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessor; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; +import net.minecraft.world.World; +import net.minecraftforge.client.event.ClientChatReceivedEvent; +import net.minecraftforge.common.MinecraftForge; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class DungeonContext { + @Getter + private final World world; + @Getter + private final MapProcessor mapProcessor; + + @Getter + @Setter + private BlockPos dungeonMin; + + @Getter + private final Map<Point, DungeonRoom> roomMapper = new HashMap<Point, DungeonRoom>(); + @Getter + private final List<DungeonRoom> dungeonRoomList = new ArrayList<DungeonRoom>(); + + @Getter + private final List<RoomProcessor> globalRoomProcessors = new ArrayList<RoomProcessor>(); + + @Getter + private final Map<String, Integer> deaths = new HashMap<String, Integer>(); + @Getter + private final List<String[]> milestoneReached = new ArrayList<String[]>(); + @Getter + @Setter + private long BossRoomEnterSeconds = -1; + @Getter + @Setter + private long init = -1; + @Getter + @Setter + private BlockPos bossroomSpawnPos = null; + + @Getter + @Setter + private boolean trapRoomGen = false; + + @Getter + private boolean gotMimic = false; + + private int latestSecretCnt = 0; + private int latestTotalSecret = 0; + private int latestCrypts = 0; + + @Getter + private int maxSpeed = 600; + @Getter + private double secretPercentage = 1.0; + + public void setGotMimic(boolean gotMimic) { + this.gotMimic = gotMimic; + createEvent(new DungeonNodataEvent("MIMIC_KILLED")); + } + + @Getter + @Setter + private BossfightProcessor bossfightProcessor; + + @Getter + private final Set<String> players = new HashSet<String>(); + + @Getter + private final List<DungeonEvent> events = new ArrayList<DungeonEvent>(); + + public DungeonContext(World world) { + this.world = world; + createEvent(new DungeonNodataEvent("DUNGEON_CONTEXT_CREATION")); + mapProcessor = new MapProcessor(this); + DungeonSpecificDataProvider doorFinder = DungeonSpecificDataProviderRegistry.getDoorFinder(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()); + if (doorFinder != null) { + trapRoomGen = doorFinder.isTrapSpawn(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()); + + secretPercentage = doorFinder.secretPercentage(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()); + maxSpeed = doorFinder.speedSecond(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()); + } else mapProcessor.setBugged(true); + init = System.currentTimeMillis(); + } + + public void createEvent(DungeonEventData eventData) { + events.add(new DungeonEvent(eventData)); + } + + + private final Rectangle roomBoundary = new Rectangle(-10,-10,138,138); + + public void tick() { + mapProcessor.tick(); + + if (mapProcessor.isInitialized() && BossRoomEnterSeconds == -1 && !roomBoundary.contains(mapProcessor.worldPointToMapPoint(Minecraft.getMinecraft().thePlayer.getPositionVector()))) { + BossRoomEnterSeconds = FeatureRegistry.DUNGEON_SBTIME.getTimeElapsed() / 1000; + bossroomSpawnPos = Minecraft.getMinecraft().thePlayer.getPosition(); + MinecraftForge.EVENT_BUS.post(new BossroomEnterEvent()); + createEvent(new DungeonNodataEvent("BOSSROOM_ENTER")); + DungeonSpecificDataProvider doorFinder = DungeonSpecificDataProviderRegistry.getDoorFinder(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()); + if (doorFinder != null) { + bossfightProcessor = doorFinder.createBossfightProcessor(world, DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()); + } else { + DungeonsGuide.sendDebugChat(new ChatComponentText("Error:: Null Data Providier")); + } + } + List<NetworkPlayerInfo> list = FeatureDungeonMap.field_175252_a.sortedCopy(Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()); + try { + for (int i = 1; i < 20; i++) { + NetworkPlayerInfo networkPlayerInfo = list.get(i); + String name = networkPlayerInfo.getDisplayName() != null ? networkPlayerInfo.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfo.getPlayerTeam(), networkPlayerInfo.getGameProfile().getName()); + if (name.trim().equals("§r") || name.startsWith("§r ")) continue; + players.add(TextUtils.stripColor(name).trim().split(" ")[0]); + } + } catch (Exception e) {} + + if (latestSecretCnt != FeatureRegistry.DUNGEON_SECRETS.getSecretsFound()) { + int newSecretCnt = FeatureRegistry.DUNGEON_SECRETS.getSecretsFound(); + createEvent(new DungeonSecretCountChangeEvent(latestSecretCnt, newSecretCnt, latestTotalSecret, FeatureRegistry.DUNGEON_SECRETS.sureOfTotalSecrets())); + latestSecretCnt = newSecretCnt; + } + if (latestTotalSecret != FeatureRegistry.DUNGEON_SECRETS.getTotalSecretsInt()) { + latestTotalSecret = FeatureRegistry.DUNGEON_SECRETS.getTotalSecretsInt(); + createEvent(new DungeonSecretCountChangeEvent(latestSecretCnt, latestSecretCnt, latestTotalSecret, FeatureRegistry.DUNGEON_SECRETS.sureOfTotalSecrets())); + } + if (latestCrypts != FeatureRegistry.DUNGEON_TOMBS.getTombsFound()) { + int newlatestCrypts = FeatureRegistry.DUNGEON_TOMBS.getTombsFound(); + createEvent(new DungeonCryptBrokenEvent(latestCrypts, newlatestCrypts)); + this.latestCrypts = newlatestCrypts; + } + } + + @Getter + private boolean ended = false; + @Getter + private boolean defeated = false; + public void onChat(ClientChatReceivedEvent event) { + IChatComponent component = event.message; + String formatted = component.getFormattedText(); + if (formatted.contains("$DG-Comm")) { + event.setCanceled(true); + String data = component.getFormattedText().substring(component.getFormattedText().indexOf("$DG-Comm")); + String actual = TextUtils.stripColor(data); + String coords = actual.split(" ")[1]; + String secrets = actual.split(" ")[2]; + int x = Integer.parseInt(coords.split("/")[0]); + int z = Integer.parseInt(coords.split("/")[1]); + int secrets2 = Integer.parseInt(secrets); + Point roomPt = mapProcessor.worldPointToRoomPoint(new BlockPos(x,70,z)); + DungeonsGuide.sendDebugChat(new ChatComponentText("Message from Other dungeons guide :: "+roomPt.x+" / " + roomPt.y + " total secrets "+secrets2)); + DungeonRoom dr = roomMapper.get(roomPt); + if (dr != null) { + dr.setTotalSecrets(secrets2); + } + } else if (formatted.contains("$DG-Mimic")) { + setGotMimic(true); + } else if (formatted.startsWith("§r§c§lPUZZLE FAIL! ") && formatted.endsWith(" §r§4Y§r§ci§r§6k§r§ee§r§as§r§2!§r")) { + createEvent(new DungeonPuzzleFailureEvent(TextUtils.stripColor(formatted.split(" ")[2]), formatted)); + } else if (formatted.contains("§6> §e§lEXTRA STATS §6<")) { + createEvent(new DungeonNodataEvent("DUNGEON_END")); + ended = true; + } else if (formatted.contains("§r§c☠ §r§eDefeated ")) { + defeated = true; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java new file mode 100755 index 00000000..da914ff3 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java @@ -0,0 +1,495 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.events.DungeonMapUpdateEvent; +import kr.syeyoung.dungeonsguide.dungeon.events.DungeonNodataEvent; +import kr.syeyoung.dungeonsguide.dungeon.events.DungeonRoomDiscoverEvent; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.EDungeonDoorType; +import kr.syeyoung.dungeonsguide.dungeon.events.SerializableBlockPos; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonSpecificDataProviderRegistry; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonSpecificDataProvider; +import kr.syeyoung.dungeonsguide.events.DungeonContextInitializationEvent; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.stomp.StompPayload; +import kr.syeyoung.dungeonsguide.utils.MapUtils; +import kr.syeyoung.dungeonsguide.wsresource.StaticResourceCache; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemMap; +import net.minecraft.item.ItemStack; +import net.minecraft.util.*; +import net.minecraft.world.storage.MapData; +import net.minecraftforge.common.MinecraftForge; +import org.json.JSONObject; + +import javax.vecmath.Vector2d; +import java.awt.*; +import java.util.*; +import java.util.List; + +public class MapProcessor { + + private final DungeonContext context; + + private byte[] lastMapData; + + @Getter + private MapData lastMapData2; + + @Getter + private final BiMap<String, String> mapIconToPlayerMap = HashBiMap.create(); + + @Getter @Setter + private Dimension unitRoomDimension; + @Getter @Setter + private Dimension doorDimension; // width: width of door, height: gap between rooms + @Getter @Setter + private Point topLeftMapPoint; + + @Setter + private boolean bugged = false; + + private final List<Point> roomsFound = new ArrayList<Point>(); + + private boolean axisMatch = false; + + @Getter + private boolean initialized = false; + + @Getter + private int undiscoveredRoom = 0; + + public MapProcessor(DungeonContext context) { + this.context = context; + } + + private static final Set<Vector2d> directions = Sets.newHashSet(new Vector2d(0,1), new Vector2d(0, -1), new Vector2d(1, 0), new Vector2d(-1 , 0)); + + private int waitCnt = 0; + private void buildMap(final byte[] mapData) { + final Point startroom = MapUtils.findFirstColorWithIn(mapData, (byte) 30, new Rectangle(0,0,128,128)); + if (startroom == null){ + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCouldn't retrieve map data, disabling mod for this dungeon run")); + bugged = true; + return; + } + // Determine room dimension + { + int width = MapUtils.getWidthOfColorAt(mapData, (byte) 30, startroom); + int height = MapUtils.getHeightOfColorAt(mapData, (byte) 30, startroom); + unitRoomDimension = new Dimension(width, height); + } + Vector2d doorDir = null; + // determine the gap + { + Point midStartRoom = new Point(startroom.x + unitRoomDimension.width / 2, startroom.y +unitRoomDimension.height / 2); + final int halfWidth = unitRoomDimension.width / 2 + 2; + for (Vector2d v:directions) { + byte color = MapUtils.getMapColorAt(mapData, (int)(v.x * halfWidth +midStartRoom.x), (int)(v.y *halfWidth +midStartRoom.y)); + if (color != 0) { + doorDir = v; + break; + } + } + + if (doorDir == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCouldn't determine door of the room, disabling mod for this dungeon run")); + bugged = true; + return; + } + Point basePoint = new Point(startroom.x, startroom.y); + if (doorDir.x > 0) basePoint.x += unitRoomDimension.width; + if (doorDir.x < 0) basePoint.x += -1; + if (doorDir.y > 0) basePoint.y += unitRoomDimension.height; + if (doorDir.y < 0) basePoint.y += -1; + int gap = MapUtils.getLengthOfColorExtending(mapData, (byte) 0, basePoint, doorDir); + Point pt = MapUtils.findFirstColorWithInNegate(mapData, (byte)0, new Rectangle(basePoint.x, basePoint.y, (int)Math.abs(doorDir.y) * unitRoomDimension.width + 1, (int)Math.abs(doorDir.x) * unitRoomDimension.height + 1)); + if (pt == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCouldn't determine door of the room, disabling mod for this dungeon run")); + bugged = true; + return; + } + int doorWidth = MapUtils.getLengthOfColorExtending(mapData, MapUtils.getMapColorAt(mapData, pt.x, pt.y), pt, new Vector2d((int)Math.abs(doorDir.y), (int)Math.abs(doorDir.x))); + doorDimension = new Dimension(doorWidth, gap); + } + // Determine Top Left + { + int x = startroom.x; + int y = startroom.y; + while (x >= unitRoomDimension.width + doorDimension.height) x -= unitRoomDimension.width + doorDimension.height; + while (y >= unitRoomDimension.height + doorDimension.height) y -= unitRoomDimension.height + doorDimension.height; + topLeftMapPoint = new Point(x, y); + } + // determine door location based on npc, and determine map min from there + { + DungeonSpecificDataProvider doorFinder = DungeonSpecificDataProviderRegistry.getDoorFinder(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()); + if (doorFinder == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCouldn't find door processor for "+ DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName())); + bugged = true; + return; + } + BlockPos door = doorFinder.findDoor(context.getWorld(), DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()); + if (door == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCouldn't determine door of the room, disabling mod for this dungeon run")); + bugged = true; + return; + } + + DungeonsGuide.sendDebugChat(new ChatComponentText("door Pos:"+door)); + + Point unitPoint = mapPointToRoomPoint(startroom); + unitPoint.translate(unitPoint.x + 1, unitPoint.y + 1); + unitPoint.translate((int)doorDir.x, (int)doorDir.y); + + Vector2d offset = doorFinder.findDoorOffset(context.getWorld(), DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()); + axisMatch = doorDir.equals(offset); + + int worldX = unitPoint.x * 16; + int worldY = unitPoint.y * 16; + BlockPos worldMin = door.add(-worldX, 0, -worldY); + context.setDungeonMin(worldMin); + + } + + DungeonsGuide.sendDebugChat(new ChatComponentText("Found Green room:"+startroom)); + DungeonsGuide.sendDebugChat(new ChatComponentText("Axis match:"+axisMatch)); + DungeonsGuide.sendDebugChat(new ChatComponentText("World Min:"+context.getDungeonMin())); + DungeonsGuide.sendDebugChat(new ChatComponentText("Dimension:"+unitRoomDimension)); + DungeonsGuide.sendDebugChat(new ChatComponentText("top Left:"+topLeftMapPoint)); + DungeonsGuide.sendDebugChat(new ChatComponentText("door dimension:"+doorDimension)); + context.createEvent(new DungeonNodataEvent("MAP_PROCESSOR_INIT")); + initialized = true; + MinecraftForge.EVENT_BUS.post(new DungeonContextInitializationEvent()); + } + + public Point mapPointToRoomPoint(Point mapPoint) { + int x = (int)((mapPoint.x - topLeftMapPoint.x) / ((double)unitRoomDimension.width + doorDimension.height)); + int y = (int)((mapPoint.y - topLeftMapPoint.y) / ((double)unitRoomDimension.height + doorDimension.height)); + return new Point(x,y); + } + public BlockPos mapPointToWorldPoint(Point mapPoint) { + int x = (int)((mapPoint.x - topLeftMapPoint.x) / ((double)unitRoomDimension.width + doorDimension.height) * 32 + context.getDungeonMin().getX()); + int y = (int)((mapPoint.y - topLeftMapPoint.y) / ((double)unitRoomDimension.height + doorDimension.height) * 32 + context.getDungeonMin().getZ()); + return new BlockPos(x,70,y); + } + public Point roomPointToMapPoint(Point roomPoint) { + return new Point(roomPoint.x * (unitRoomDimension.width +doorDimension.height) + topLeftMapPoint.x, + roomPoint.y *(unitRoomDimension.height + doorDimension.height) + topLeftMapPoint.y); + } + public BlockPos roomPointToWorldPoint(Point roomPoint) { + return new BlockPos(context.getDungeonMin().getX() +(roomPoint.x * 32), context.getDungeonMin().getY(), context.getDungeonMin().getZ() +(roomPoint.y *32)); + } + public Point worldPointToRoomPoint(BlockPos worldPoint) { + if (context.getDungeonMin() == null) return null; + return new Point((worldPoint.getX() - context.getDungeonMin().getX()) / 32, (worldPoint.getZ() - context.getDungeonMin().getZ()) / 32); + } + public Point worldPointToMapPoint(Vec3 worldPoint) { + if (context.getDungeonMin() == null) return null; + return new Point(topLeftMapPoint.x + (int)((worldPoint.xCoord - context.getDungeonMin().getX()) / 32.0f * (unitRoomDimension.width + doorDimension.height)), topLeftMapPoint.y + (int)((worldPoint.zCoord - context.getDungeonMin().getZ()) / 32.0f * (unitRoomDimension.height + doorDimension.height))); + } + + private void processMap(byte[] mapData) { + int height = (int)((128.0 - topLeftMapPoint.y) / (unitRoomDimension.height + doorDimension.height)); + int width = (int) ((128.0 - topLeftMapPoint.x) / (unitRoomDimension.width + doorDimension.height)); + if (MapUtils.getMapColorAt(mapData,0,0) != 0) return; + undiscoveredRoom = 0; + for (int y = 0; y <= height; y++){ + for (int x = 0; x <= width; x++) { + Point mapPoint = roomPointToMapPoint(new Point(x,y)); + byte color = MapUtils.getMapColorAt(mapData, mapPoint.x, mapPoint.y); + MapUtils.record(mapData, mapPoint.x, mapPoint.y, new Color(255,255,0,80)); + if (roomsFound.contains(new Point(x,y))) { + DungeonRoom dungeonRoom = context.getRoomMapper().get(new Point(x,y)); + if (color == 18 && dungeonRoom.getCurrentState() != DungeonRoom.RoomState.FINISHED) { + dungeonRoom.setCurrentState(DungeonRoom.RoomState.COMPLETE_WITHOUT_SECRETS); + dungeonRoom.setTotalSecrets(0); + } else if (color == 30) { + dungeonRoom.setCurrentState(DungeonRoom.RoomState.FINISHED); + dungeonRoom.setTotalSecrets(0); + } else if (dungeonRoom.getCurrentState() != DungeonRoom.RoomState.FINISHED){ + byte centerColor = MapUtils.getMapColorAt(mapData, mapPoint.x + unitRoomDimension.width / 2, mapPoint.y + unitRoomDimension.height / 2); + MapUtils.record(mapData, mapPoint.x + unitRoomDimension.width / 2, mapPoint.y + unitRoomDimension.height / 2, new Color(0,255,0,80)); + if (centerColor == 34) { + dungeonRoom.setCurrentState(DungeonRoom.RoomState.COMPLETE_WITHOUT_SECRETS); + } else if (centerColor == 30) { + dungeonRoom.setCurrentState(DungeonRoom.RoomState.FINISHED); + } else if (centerColor == 18) { // red + dungeonRoom.setCurrentState(DungeonRoom.RoomState.FAILED); + } + } + if (dungeonRoom.getTotalSecrets() == -1) { + if (dungeonRoom.getColor() == 82) dungeonRoom.setTotalSecrets(0); + else if (dungeonRoom.getColor() == 74) dungeonRoom.setTotalSecrets(0); + MapUtils.record(mapData, mapPoint.x, mapPoint.y +1, new Color(0,255,0,80)); + } + continue; + } + + if (color != 0 && color != 85) { + MapUtils.record(mapData, mapPoint.x, mapPoint.y, new Color(0,255,255,80)); + DungeonRoom rooms = buildRoom(mapData, new Point(x,y)); + if (rooms == null) continue; + context.createEvent(new DungeonRoomDiscoverEvent(rooms.getUnitPoints().get(0), rooms.getRoomMatcher().getRotation(), new SerializableBlockPos(rooms.getMin()), new SerializableBlockPos(rooms.getMax()), rooms.getShape(),rooms.getColor(), rooms.getDungeonRoomInfo().getUuid(), rooms.getDungeonRoomInfo().getName(), rooms.getDungeonRoomInfo().getProcessorId())); + DungeonsGuide.sendDebugChat(new ChatComponentText("New Map discovered! shape: "+rooms.getShape()+ " color: "+rooms.getColor()+" unitPos: "+x+","+y)); + DungeonsGuide.sendDebugChat(new ChatComponentText("New Map discovered! mapMin: "+rooms.getMin() + " mapMx: "+rooms.getMax())); + StringBuilder builder = new StringBuilder(); + for (int dy =0;dy<4;dy++) { + builder.append("\n"); + for (int dx = 0; dx < 4; dx ++) { + boolean isSet = ((rooms.getShape() >> (dy * 4 + dx)) & 0x1) != 0; + builder.append(isSet ? "O" : "X"); + } + } + DungeonsGuide.sendDebugChat(new ChatComponentText("Shape visual: "+ builder)); + + context.getDungeonRoomList().add(rooms); + for (Point p:rooms.getUnitPoints()) { + roomsFound.add(p); + context.getRoomMapper().put(p, rooms); + } + if (rooms.getRoomProcessor() != null && rooms.getRoomProcessor().readGlobalChat()) + context.getGlobalRoomProcessors().add(rooms.getRoomProcessor()); + } else if (color == 85){ + undiscoveredRoom++; + } + + } + } + } + + private static final Set<Vector2d> door_dirs = Sets.newHashSet(new Vector2d(0,0.5), new Vector2d(0, -0.5), new Vector2d(0.5, 0), new Vector2d(-0.5 , 0)); + private DungeonRoom buildRoom(byte[] mapData, Point unitPoint) { + Queue<Point[]> toCheck = new LinkedList<Point[]>(); + toCheck.add(new Point[] {unitPoint, unitPoint}); // requestor, target + Set<Point> checked = new HashSet<Point>(); + List<Point> ayConnected = new ArrayList<Point>(); + + int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE; + int maxX = 0, maxY = 0; + while(toCheck.peek() != null) { + Point[] check = toCheck.poll(); + if (checked.contains(check[1])) continue; + checked.add(check[1]); + + if (checkIfConnected(mapData, check[0], check[1])) { + ayConnected.add(check[1]); + if (check[1].x < minX) minX = check[1].x; + if (check[1].y < minY) minY = check[1].y; + if (check[1].x > maxX) maxX = check[1].x; + if (check[1].y > maxY) maxY = check[1].y; + for (Vector2d dir: directions) { + Point newPt = new Point(check[1].x + (int)dir.x, check[1].y +(int)dir.y); + toCheck.add(new Point[]{check[1], newPt}); + } + } + } + + short shape = 0; + for (Point p:ayConnected) { + int localX = p.x - minX, localY = p.y - minY; + shape |= 1 <<(localY *4 + localX); + } + Set<Vector2d> doors = new HashSet<>(); + for (Point p: ayConnected) { + for (Vector2d v: door_dirs) { + Vector2d v2 = new Vector2d(p.x + v.x , p.y + v.y ); + if (doors.contains(v2)) doors.remove(v2); + else doors.add(v2); + } + } + Point pt2 = roomPointToMapPoint(ayConnected.get(0)); + byte unit1 = MapUtils.getMapColorAt(mapData, pt2.x, pt2.y); + + // 0: none 1: open door door 2. unopen door 3: wither door 4. red door + Set<Tuple<Vector2d, EDungeonDoorType>> doorsAndStates = new HashSet<>(); + final int halfWidth = unitRoomDimension.width + 4; + for (Vector2d door : doors) { + int floorX = (int)Math.floor(door.x), floorY = (int)Math.floor(door.y); + Point mapPt = roomPointToMapPoint(new Point(floorX, floorY)); + Point target = new Point(mapPt.x+ unitRoomDimension.width/2 + (int)(halfWidth*(door.x - floorX)), mapPt.y + unitRoomDimension.height/2 + (int)(halfWidth*(door.y - floorY)) ); + MapUtils.record(mapData, target.x, target.y, Color.green); + byte color = MapUtils.getMapColorAt(mapData, target.x, target.y); + + Vector2d vector2d = new Vector2d(door.x - minX, door.y - minY); + if (color == 0) { + doorsAndStates.add(new Tuple<>(vector2d, EDungeonDoorType.NONE)); + } else if (color == 85) { + doorsAndStates.add(new Tuple<>(vector2d, EDungeonDoorType.UNOPEN)); + } else if (color == 119) { + doorsAndStates.add(new Tuple<>(vector2d, EDungeonDoorType.WITHER)); + } else if (color == 18 && unit1 != 18) { + doorsAndStates.add(new Tuple<>(vector2d, EDungeonDoorType.BLOOD)); + } else { + doorsAndStates.add(new Tuple<>(vector2d, EDungeonDoorType.ENTRANCE)); + } + } + + + try{ + return new DungeonRoom(ayConnected, shape, unit1, roomPointToWorldPoint(new Point(minX, minY)), roomPointToWorldPoint(new Point(maxX+1, maxY+1)).add(-1, 0, -1), context, doorsAndStates); + } catch (IllegalStateException ex) { + DungeonsGuide.sendDebugChat(new ChatComponentText("Failed to load room, retrying later :: "+ex.getLocalizedMessage())); + return null; + } + } + + private boolean checkIfConnected(byte[] mapData, Point unitPoint1, Point unitPoint2) { + if (unitPoint1 == unitPoint2) return true; + if (unitPoint1.equals(unitPoint2)) return true; + + + Point high = (unitPoint2.y > unitPoint1.y) ? unitPoint2 :(unitPoint2.x > unitPoint1.x) ? unitPoint2 : unitPoint1; + Point low = high == unitPoint2 ? unitPoint1 : unitPoint2; + + int xOff = low.x - high.x; + int yOff = low.y - high.y; + Point pt = roomPointToMapPoint(high); + Point pt2 = roomPointToMapPoint(low); + byte unit1 = MapUtils.getMapColorAt(mapData, pt.x, pt.y); + byte unit2 = MapUtils.getMapColorAt(mapData, pt2.x, pt2.y); + pt.translate(xOff, yOff); + byte unit3 = MapUtils.getMapColorAt(mapData, pt.x, pt.y); + + return unit1 == unit2 && unit2 == unit3 && unit1 != 0; + } + + public boolean isThereDifference(byte[] colors1, byte[] colors) { + if (colors1 == null || colors == null) return true; + for (int i =0; i < colors.length; i++) + if (colors[i] != colors1[i]) return true; + return false; + } + private int stabilizationTick = 0; + + private boolean processed = false; + private void processFinishedMap(byte[] mapData) { + if (MapUtils.getMapColorAt(mapData, 0, 0) == 0) return; + if (processed) return; + processed = true; + MapUtils.clearMap(); + MapUtils.record(mapData, 0, 0, Color.GREEN); + + int skill = MapUtils.readNumber(mapData, 51, 35, 9); + int exp = MapUtils.readNumber(mapData, 51, 54, 9); + int time = MapUtils.readNumber(mapData, 51, 73, 9); + int bonus = MapUtils.readNumber(mapData, 51, 92, 9); + DungeonsGuide.sendDebugChat(new ChatComponentText(("skill: " + skill + " / exp: " + exp + " / time: " + time + " / bonus : " + bonus))); + JSONObject payload = new JSONObject().put("timeSB", FeatureRegistry.DUNGEON_SBTIME.getTimeElapsed()) + .put("timeR", FeatureRegistry.DUNGEON_REALTIME.getTimeElapsed()) + .put("timeScore", time) + .put("completionStage", context.getBossRoomEnterSeconds() == -1 ? 0 : + context.isDefeated() ? 2 : 1) + .put("percentage", DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getPercentage() / 100.0) + .put("floor", DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()); + DungeonsGuide.sendDebugChat(new ChatComponentText(payload.toString())); + + try { + String target = StaticResourceCache.INSTANCE.getResource(StaticResourceCache.DATA_COLLECTION).get().getValue(); + if (FeatureRegistry.ETC_COLLECT_SCORE.isEnabled() && !target.contains("falsefalsefalsefalse")) { + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(payload.toString()).header("destination", target.replace("false", "").trim())); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void tick() { + if (waitCnt < 5) { + waitCnt++; + return; + } + if (bugged) return; + ItemStack stack = Minecraft.getMinecraft().thePlayer.inventory.getStackInSlot(8); + byte[] mapData; + if (stack == null || !(stack.getItem() instanceof ItemMap)) { + mapData = lastMapData; + } else { + MapData mapData1 = ((ItemMap)stack.getItem()).getMapData(stack, context.getWorld()); + if (mapData1 == null) mapData = lastMapData; + else { + mapData = mapData1.colors; + lastMapData2 = mapData1; + + if (isThereDifference(lastMapData, mapData)) { + stabilizationTick =0; + context.createEvent(new DungeonMapUpdateEvent(mapData)); + } else { + stabilizationTick++; + } + + if (stabilizationTick > 20) { + if (doorDimension == null) buildMap(mapData); + else processMap(mapData); + + if (context.isEnded()) { + processFinishedMap(mapData); + } + } + lastMapData = mapData; + } + + } + + + if (lastMapData2 != null && mapIconToPlayerMap.size() < context.getPlayers().size() && initialized) { + label: for (Map.Entry<String, Vec4b> stringVec4bEntry : lastMapData2.mapDecorations.entrySet()) { + if (mapIconToPlayerMap.containsValue(stringVec4bEntry.getKey())) continue; + int x = stringVec4bEntry.getValue().func_176112_b() /2 + 64; + int y = stringVec4bEntry.getValue().func_176113_c() /2 + 64; + BlockPos mapPos = mapPointToWorldPoint(new Point(x, y)); + String potentialPlayer = null; + for (String player : context.getPlayers()) { // check nearby players + if (mapIconToPlayerMap.containsKey(player)) continue; + EntityPlayer entityPlayer = Minecraft.getMinecraft().theWorld.getPlayerEntityByName(player); + if (entityPlayer == null || entityPlayer.isInvisible()) continue; + BlockPos pos = entityPlayer.getPosition(); + int dx = mapPos.getX() - pos.getX(); + int dz = mapPos.getZ() - pos.getZ(); + if (dx * dx + dz * dz < 100) { + if (potentialPlayer != null) continue label; + potentialPlayer = player; + } + } + if (potentialPlayer == null) continue; + + for (Map.Entry<String, Vec4b> stringVec4bEntry2 : lastMapData2.mapDecorations.entrySet()) { // check nearby markers + if (mapIconToPlayerMap.containsValue(stringVec4bEntry.getKey())) continue; + if (stringVec4bEntry.getKey().equals(stringVec4bEntry2.getKey())) continue; + int x2 = stringVec4bEntry2.getValue().func_176112_b() /2 + 64; + int y2 = stringVec4bEntry2.getValue().func_176113_c() /2 + 64; + int dx = x2 - x; + int dy = y2 - y; + if (dx * dx + dy * dy < 100) { + continue label; + } + } + mapIconToPlayerMap.put(potentialPlayer, stringVec4bEntry.getKey()); + } + } + + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/AbstractAction.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/AbstractAction.java new file mode 100644 index 00000000..c9a8ac9a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/AbstractAction.java @@ -0,0 +1,57 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +public abstract class AbstractAction implements Action { + @Override + public void onPlayerInteract(DungeonRoom dungeonRoom, PlayerInteractEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) { + + } + + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) { + + } + + @Override + public void onLivingDeath(DungeonRoom dungeonRoom, LivingDeathEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) { + + } + + @Override + public void onRenderScreen(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties) { + + } + + @Override + public void onLivingInteract(DungeonRoom dungeonRoom, PlayerInteractEntityEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) { + + } + + @Override + public void onTick(DungeonRoom dungeonRoom, ActionRoute.ActionRouteProperties actionRouteProperties) { + + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/Action.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/Action.java new file mode 100755 index 00000000..2be05ff8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/Action.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +import java.util.Set; + +public interface Action { + Set<Action> getPreRequisites(DungeonRoom dungeonRoom); + + void onPlayerInteract(DungeonRoom dungeonRoom, PlayerInteractEvent event, ActionRoute.ActionRouteProperties actionRouteProperties); + void onLivingInteract(DungeonRoom dungeonRoom, PlayerInteractEntityEvent event, ActionRoute.ActionRouteProperties actionRouteProperties); + void onLivingDeath(DungeonRoom dungeonRoom, LivingDeathEvent event, ActionRoute.ActionRouteProperties actionRouteProperties); + void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag); + void onRenderScreen(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties); + void onTick(DungeonRoom dungeonRoom, ActionRoute.ActionRouteProperties actionRouteProperties); + + boolean isComplete(DungeonRoom dungeonRoom); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionBreakWithSuperBoom.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionBreakWithSuperBoom.java new file mode 100755 index 00000000..b9307e0c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionBreakWithSuperBoom.java @@ -0,0 +1,101 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.HashSet; +import java.util.Set; + +@Data +public class ActionBreakWithSuperBoom extends AbstractAction { + private Set<Action> preRequisite = new HashSet<Action>(); + private OffsetPoint target; + + public ActionBreakWithSuperBoom(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return target.getBlock(dungeonRoom) == Blocks.air; + } + + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) { + Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture); + + BlockPos blockpos = target.getBlockPos(dungeonRoom); + + Entity viewing_from = Minecraft.getMinecraft().getRenderViewEntity(); + + double x_fix = viewing_from.lastTickPosX + ((viewing_from.posX - viewing_from.lastTickPosX) * partialTicks); + double y_fix = viewing_from.lastTickPosY + ((viewing_from.posY - viewing_from.lastTickPosY) * partialTicks); + double z_fix = viewing_from.lastTickPosZ + ((viewing_from.posZ - viewing_from.lastTickPosZ) * partialTicks); + + GlStateManager.pushMatrix(); + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + GlStateManager.disableLighting(); + GlStateManager.enableAlpha(); + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + GlStateManager.enableBlend(); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer vertexbuffer = tessellator.getWorldRenderer(); + vertexbuffer.begin(7, DefaultVertexFormats.BLOCK); + + BlockRendererDispatcher blockrendererdispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher(); + blockrendererdispatcher.getBlockModelRenderer().renderModel(Minecraft.getMinecraft().theWorld, + blockrendererdispatcher.getBlockModelShapes().getModelForState(Blocks.tnt.getDefaultState()), + Blocks.tnt.getDefaultState(), blockpos, vertexbuffer, false); + tessellator.draw(); + + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + + RenderUtils.highlightBlock(blockpos, new Color(0, 255,255,50), partialTicks, true); + RenderUtils.drawTextAtWorld("Superboom", blockpos.getX() + 0.5f, blockpos.getY() + 0.5f, blockpos.getZ() + 0.5f, 0xFFFFFF00, 0.03f, false, false, partialTicks); + } + + @Override + public String toString() { + return "BreakWithSuperboom\n- target: "+target.toString(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionChangeState.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionChangeState.java new file mode 100755 index 00000000..f88a3826 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionChangeState.java @@ -0,0 +1,71 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonDummy; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonMechanic; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonSecret; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.HashSet; +import java.util.Set; + +@Data +public class ActionChangeState extends AbstractAction{ + @EqualsAndHashCode.Exclude + private Set<Action> preRequisite2 = new HashSet<Action>(); + + private String mechanicName; + private String state; + + public ActionChangeState(String mechanicName, String state) { + this.mechanicName = mechanicName; + this.state = state; + } + + @Override + public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) { + Set<Action> set = new HashSet<Action>(); + set.addAll(preRequisite2); + DungeonMechanic mechanic = dungeonRoom.getMechanics().get(mechanicName); + if (mechanic!= null) + set.addAll(mechanic.getAction(state, dungeonRoom)); + return set; + } + @Override + public String toString() { + return "ChangeState\n- target: "+mechanicName+"\n- state: "+state; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + DungeonMechanic mechanic = dungeonRoom.getMechanics().get(mechanicName); + if (state.equalsIgnoreCase("navigate")) + return true; + if (mechanic== null) + return false; + if (mechanic instanceof DungeonSecret && ((DungeonSecret) mechanic).getSecretType() != DungeonSecret.SecretType.CHEST) + return true; + if (mechanic instanceof DungeonDummy) + return true; + return mechanic.getCurrentState(dungeonRoom).equalsIgnoreCase(state); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClick.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClick.java new file mode 100755 index 00000000..a903bcee --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClick.java @@ -0,0 +1,78 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockPos; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +import java.awt.*; +import java.util.HashSet; +import java.util.Set; + +@Data +public class ActionClick extends AbstractAction { + private Set<Action> preRequisite = new HashSet<Action>(); + private OffsetPoint target; + private Predicate<ItemStack> predicate = Predicates.alwaysTrue(); + + private boolean clicked = false; + + public ActionClick(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return clicked; + } + + @Override + public void onPlayerInteract(DungeonRoom dungeonRoom, PlayerInteractEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) { + if (clicked) return; + if (target.getBlockPos(dungeonRoom).equals(event.pos) && + (predicate == null || predicate.apply(event.entityLiving.getHeldItem()))) { + clicked = true; + } + } + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) { + BlockPos pos = target.getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, new Color(0, 255,255,50),partialTicks, true); + RenderUtils.drawTextAtWorld("Click", pos.getX() + 0.5f, pos.getY() + 0.3f, pos.getZ() + 0.5f, 0xFFFFFF00, 0.02f, false, false, partialTicks); + } + + + @Override + public String toString() { + return "Click\n- target: "+target.toString()+"\n- predicate: "+predicate.getClass().getSimpleName(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClickSet.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClickSet.java new file mode 100755 index 00000000..24bad024 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClickSet.java @@ -0,0 +1,91 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockPos; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +import java.awt.*; +import java.util.HashSet; +import java.util.Set; + +@Data +public class ActionClickSet extends AbstractAction { + private Set<Action> preRequisite = new HashSet<Action>(); + private OffsetPointSet target; + private Predicate<ItemStack> predicate = Predicates.alwaysTrue(); + + public ActionClickSet(OffsetPointSet target) { + this.target = target; + } + + @Override + public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public String toString() { + return "ClickSet\n- targets size: "+target.getOffsetPointList().size()+"\n- predicate: "+predicate.getClass().getSimpleName(); + } + + private boolean clicked = false; + @Override + public void onPlayerInteract(DungeonRoom dungeonRoom, PlayerInteractEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) { + if (clicked) return; + for (OffsetPoint pt2: target.getOffsetPointList()) { + if (pt2.getBlockPos(dungeonRoom).equals(event.pos) && + (predicate == null || predicate.apply(event.entityLiving.getHeldItem()))) { + clicked = true; + } + } + + } + + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) { + float xAcc = 0; + float yAcc = 0; + float zAcc = 0; + int size = target.getOffsetPointList().size(); + for (OffsetPoint offsetPoint : target.getOffsetPointList()) { + BlockPos pos = offsetPoint.getBlockPos(dungeonRoom); + xAcc += pos.getX() + 0.5f; + yAcc += pos.getY()+ 0.5f; + zAcc += pos.getZ()+ 0.5f; + RenderUtils.highlightBlock(offsetPoint.getBlockPos(dungeonRoom), new Color(0, 255,255,50),partialTicks, true); + } + + RenderUtils.drawTextAtWorld("Click", xAcc / size, yAcc / size, zAcc / size, 0xFFFFFF00, 0.02f, false, false, partialTicks); + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return clicked; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionComplete.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionComplete.java new file mode 100644 index 00000000..646c2171 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionComplete.java @@ -0,0 +1,41 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; + +import java.util.Collections; +import java.util.Set; + +public class ActionComplete extends AbstractAction { + @Override + public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) { + return Collections.emptySet(); + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return false; + } + + @Override + public String toString() { + return "Completed"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionDropItem.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionDropItem.java new file mode 100755 index 00000000..9d246fc8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionDropItem.java @@ -0,0 +1,71 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Data +public class ActionDropItem extends AbstractAction { + private Set<Action> preRequisite = new HashSet<Action>(); + private OffsetPoint target; + private Predicate<EntityItem> predicate = Predicates.alwaysTrue(); + + public ActionDropItem(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + BlockPos pos = target.getBlockPos(dungeonRoom); + List<EntityItem> item = dungeonRoom.getContext().getWorld().getEntitiesWithinAABB(EntityItem.class, + AxisAlignedBB.fromBounds(pos.getX(), pos.getY(), pos.getZ(), pos.getX()+1, pos.getY() + 1, pos.getZ() + 1)); + if (item.size() == 0) return false; + return (predicate == null || predicate.apply(item.get(0))); + } + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) { + BlockPos pos = target.getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, new Color(0, 255,255,50),partialTicks, true); + RenderUtils.drawTextAtWorld("Drop Item", pos.getX() + 0.5f, pos.getY() + 0.3f, pos.getZ() + 0.5f, 0xFFFFFF00, 0.02f, false, false, partialTicks); + } + + @Override + public String toString() { + return "DropItem\n- target: "+target.toString()+"\n- predicate: "+predicate.getClass().getSimpleName(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionInteract.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionInteract.java new file mode 100755 index 00000000..9b5a22be --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionInteract.java @@ -0,0 +1,81 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.DungeonActionManager; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.entity.Entity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.Vec3; + +import java.awt.*; +import java.util.HashSet; +import java.util.Set; + +@Data +public class ActionInteract extends AbstractAction { + private Set<Action> preRequisite = new HashSet<Action>(); + private OffsetPoint target; + private Predicate<Entity> predicate = Predicates.alwaysFalse(); + private int radius; + + public ActionInteract(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return interacted; + } + + private boolean interacted = false; + @Override + public void onLivingInteract(DungeonRoom dungeonRoom, PlayerInteractEntityEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) { + if (interacted) return; + + Vec3 spawnLoc = DungeonActionManager.getSpawnLocation().get(event.getEntity().getEntityId()); + if (spawnLoc == null) return; + if (target.getBlockPos(dungeonRoom).distanceSq(spawnLoc.xCoord, spawnLoc.yCoord, spawnLoc.zCoord) > radius * radius) return; + if (!predicate.apply(event.getEntity())) return; + interacted = true; + } + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) { + BlockPos pos = target.getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, new Color(0, 255,255,50),partialTicks, true); + RenderUtils.drawTextAtWorld("Interact", pos.getX() + 0.5f, pos.getY() + 0.3f, pos.getZ() + 0.5f, 0xFFFFFF00, 0.02f, false, false, partialTicks); + } + + @Override + public String toString() { + return "InteractEntity\n- target: "+target.toString()+"\n- radius: "+radius+"\n- predicate: "+(predicate == null ? "null" : predicate.getClass().getSimpleName()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionKill.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionKill.java new file mode 100755 index 00000000..a048bdf6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionKill.java @@ -0,0 +1,89 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.DungeonActionManager; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.entity.Entity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.Vec3; +import net.minecraftforge.event.entity.living.LivingDeathEvent; + +import java.awt.*; +import java.util.HashSet; +import java.util.Set; + +@Data +public class ActionKill extends AbstractAction { + private Set<Action> preRequisite = new HashSet<Action>(); + private OffsetPoint target; + private Predicate<Entity> predicate = Predicates.alwaysFalse(); + private int radius; + + public ActionKill(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + Vec3 spawn = new Vec3(target.getBlockPos(dungeonRoom)); + for (Integer killed : DungeonActionManager.getKilleds()) { + if (DungeonActionManager.getSpawnLocation().get(killed) == null) continue; + if (DungeonActionManager.getSpawnLocation().get(killed).squareDistanceTo(spawn) < 100) { + return true; + } + } + + return killed; + } + + private boolean killed = false; + @Override + public void onLivingDeath(DungeonRoom dungeonRoom, LivingDeathEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) { + if (killed) return; + + Vec3 spawnLoc = DungeonActionManager.getSpawnLocation().get(event.entity.getEntityId()); + if (spawnLoc == null) return; + if (target.getBlockPos(dungeonRoom).distanceSq(spawnLoc.xCoord, spawnLoc.yCoord, spawnLoc.zCoord) > radius * radius) return; + if (!predicate.apply(event.entity)) return; + killed = true; + } + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) { + BlockPos pos = target.getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, new Color(0, 255,255,50),partialTicks, true); + RenderUtils.drawTextAtWorld("Spawn", pos.getX() + 0.5f, pos.getY() + 0.3f, pos.getZ() + 0.5f, 0xFFFFFF00, 0.02f, false, false, partialTicks); + } + + @Override + public String toString() { + return "KillEntity\n- target: "+target.toString()+"\n- radius: "+radius+"\n- predicate: "+(predicate == null ? "null" : predicate.getClass().getSimpleName()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMove.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMove.java new file mode 100755 index 00000000..6f04b44d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMove.java @@ -0,0 +1,112 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.client.Minecraft; +import net.minecraft.util.BlockPos; +import net.minecraft.util.MathHelper; +import net.minecraft.util.Vec3; + +import java.util.HashSet; +import java.util.Set; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +@Data +public class ActionMove extends AbstractAction { + private Set<Action> preRequisite = new HashSet<Action>(); + private OffsetPoint target; + + public ActionMove(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return target.getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()) < 25; + } + + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) { + BlockPos pos = target.getBlockPos(dungeonRoom); + + float distance = MathHelper.sqrt_double(pos.distanceSq(Minecraft.getMinecraft().thePlayer.getPosition())); + float multiplier = distance / 120f; //mobs only render ~120 blocks away + if (flag) multiplier *= 2.0f; + float scale = 0.45f * multiplier; + scale *= 25.0 / 6.0; + if (actionRouteProperties.isBeacon()) { + RenderUtils.renderBeaconBeam(pos.getX(), pos.getY(), pos.getZ(), actionRouteProperties.getBeaconBeamColor(), partialTicks); + RenderUtils.highlightBlock(pos, actionRouteProperties.getBeaconColor(), partialTicks); + } + RenderUtils.drawTextAtWorld("Destination", pos.getX() + 0.5f, pos.getY() + 0.5f + scale, pos.getZ() + 0.5f, 0xFF00FF00, flag ? 2f : 1f, true, false, partialTicks); + RenderUtils.drawTextAtWorld(String.format("%.2f",MathHelper.sqrt_double(pos.distanceSq(Minecraft.getMinecraft().thePlayer.getPosition())))+"m", pos.getX() + 0.5f, pos.getY() + 0.5f - scale, pos.getZ() + 0.5f, 0xFFFFFF00, flag ? 2f : 1f, true, false, partialTicks); + + if (!FeatureRegistry.SECRET_TOGGLE_KEY.isEnabled() || !FeatureRegistry.SECRET_TOGGLE_KEY.togglePathfindStatus) { + if (poses != null){ + RenderUtils.drawLinesVec3(poses, actionRouteProperties.getLineColor(), actionRouteProperties.getLineWidth(), partialTicks, true); + } + } + } + + private int tick = -1; + private List<Vec3> poses; + private Future<List<Vec3>> latestFuture; + + @Override + public void onTick(DungeonRoom dungeonRoom, ActionRoute.ActionRouteProperties actionRouteProperties) { + tick = (tick+1) % Math.max(1, actionRouteProperties.getLineRefreshRate()); + if (latestFuture != null && latestFuture.isDone()) { + try { + poses = latestFuture.get(); + latestFuture = null; + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + + if (tick == 0 && actionRouteProperties.isPathfind() && latestFuture == null) { + if (!FeatureRegistry.SECRET_FREEZE_LINES.isEnabled() || poses == null) + latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000); + } + } + + public void forceRefresh(DungeonRoom dungeonRoom) { + try { + if (latestFuture != null) return; + } catch (Exception ignored) {} + latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000); + } + @Override + public String toString() { + return "Move\n- target: "+target.toString(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMoveNearestAir.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMoveNearestAir.java new file mode 100755 index 00000000..1535d574 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMoveNearestAir.java @@ -0,0 +1,112 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.client.Minecraft; +import net.minecraft.util.BlockPos; +import net.minecraft.util.MathHelper; +import net.minecraft.util.Vec3; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +@Data +public class ActionMoveNearestAir extends AbstractAction { + private Set<Action> preRequisite = new HashSet<Action>(); + private OffsetPoint target; + + public ActionMoveNearestAir(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return target.getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()) < 25; + } + + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) { + BlockPos pos = target.getBlockPos(dungeonRoom); + + float distance = MathHelper.sqrt_double(pos.distanceSq(Minecraft.getMinecraft().thePlayer.getPosition())); + float multiplier = distance / 120f; //mobs only render ~120 blocks away + if (flag) multiplier *= 2.0f; + float scale = 0.45f * multiplier; + scale *= 25.0 / 6.0; + if (actionRouteProperties.isBeacon()) { + RenderUtils.renderBeaconBeam(pos.getX(), pos.getY(), pos.getZ(), actionRouteProperties.getBeaconBeamColor(), partialTicks); + RenderUtils.highlightBlock(pos, actionRouteProperties.getBeaconColor(), partialTicks); + } + RenderUtils.drawTextAtWorld("Destination", pos.getX() + 0.5f, pos.getY() + 0.5f + scale, pos.getZ() + 0.5f, 0xFF00FF00, flag ? 2f : 1f, true, false, partialTicks); + RenderUtils.drawTextAtWorld(String.format("%.2f",MathHelper.sqrt_double(pos.distanceSq(Minecraft.getMinecraft().thePlayer.getPosition())))+"m", pos.getX() + 0.5f, pos.getY() + 0.5f - scale, pos.getZ() + 0.5f, 0xFFFFFF00, flag ? 2f : 1f, true, false, partialTicks); + + if (!FeatureRegistry.SECRET_TOGGLE_KEY.isEnabled() || !FeatureRegistry.SECRET_TOGGLE_KEY.togglePathfindStatus) { + if (poses != null){ + RenderUtils.drawLinesVec3(poses, actionRouteProperties.getLineColor(), actionRouteProperties.getLineWidth(), partialTicks, true); + } + } + } + + private int tick = -1; + private List<Vec3> poses; + private Future<List<Vec3>> latestFuture; + @Override + public void onTick(DungeonRoom dungeonRoom, ActionRoute.ActionRouteProperties actionRouteProperties) { + tick = (tick+1) % Math.max(1, actionRouteProperties.getLineRefreshRate()); + if (latestFuture != null && latestFuture.isDone()) { + try { + poses = latestFuture.get(); + latestFuture = null; + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + + if (tick == 0 && actionRouteProperties.isPathfind() && latestFuture == null) { + if (!FeatureRegistry.SECRET_FREEZE_LINES.isEnabled() || poses == null) + latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000); + } + } + + + public void forceRefresh(DungeonRoom dungeonRoom) { + try { + if (latestFuture != null) return; + } catch (Exception ignored) {} + latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000); + } + @Override + public String toString() { + return "MoveNearestAir\n- target: "+target.toString(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionRoot.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionRoot.java new file mode 100755 index 00000000..a2527b8b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionRoot.java @@ -0,0 +1,48 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import lombok.Data; + +import java.util.HashSet; +import java.util.Set; + +@Data +public class ActionRoot extends AbstractAction { + private Set<Action> preRequisite = new HashSet<Action>(); + + public ActionRoot() { + } + + @Override + public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return true; + } + + @Override + public String toString() { + return "Action Root"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionRoute.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionRoute.java new file mode 100644 index 00000000..bba5fb4d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionRoute.java @@ -0,0 +1,124 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions.tree; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.dungeon.actions.*; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent; +import lombok.Data; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +import java.util.List; + +public class ActionRoute { + @Getter + private final String mechanic; + @Getter + private final String state; + + @Getter + private int current; + @Getter + private final List<Action> actions; + + private final DungeonRoom dungeonRoom; + + @Getter + private final ActionRouteProperties actionRouteProperties; + + public ActionRoute(DungeonRoom dungeonRoom, String mechanic, String state, ActionRouteProperties actionRouteProperties) { + this.mechanic = mechanic; + this.state = state; + this.actionRouteProperties = actionRouteProperties; + + ActionChangeState actionChangeState = new ActionChangeState(mechanic, state); + ActionTree tree= ActionTree.buildActionTree(actionChangeState, dungeonRoom); + actions = ActionTreeUtil.linearifyActionTree(tree); + actions.add(new ActionComplete()); + current = 0; + this.dungeonRoom = dungeonRoom; + } + + public Action next() { + current ++; + if (current >= actions.size()) current = actions.size() - 1; + return actions.get(current); + } + + public Action prev() { + current --; + if (current < 0) current = 0; + return actions.get(current); + } + + public Action getCurrentAction() { + return actions.get(current); + } + + + + public void onPlayerInteract(PlayerInteractEvent event) { + getCurrentAction().onPlayerInteract(dungeonRoom, event, actionRouteProperties ); + } + public void onLivingDeath(LivingDeathEvent event) { + getCurrentAction().onLivingDeath(dungeonRoom, event, actionRouteProperties ); + } + public void onRenderWorld(float partialTicks, boolean flag) { + if (current -1 >= 0 && ( + (actions.get(current-1) instanceof ActionMove && ((ActionMove) actions.get(current-1)).getTarget().getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()) >= 25) + || (actions.get(current-1) instanceof ActionMoveNearestAir && ((ActionMoveNearestAir) actions.get(current-1)).getTarget().getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()) >= 25))) actions.get(current-1).onRenderWorld(dungeonRoom, partialTicks, actionRouteProperties, flag ); + getCurrentAction().onRenderWorld(dungeonRoom, partialTicks, actionRouteProperties, flag); + } + + public void onRenderScreen(float partialTicks) { + getCurrentAction().onRenderScreen(dungeonRoom, partialTicks, actionRouteProperties); + } + + public void onTick() { + Action current = getCurrentAction(); + + current.onTick(dungeonRoom, actionRouteProperties); + if (this.current -1 >= 0 && (actions.get(this.current-1) instanceof ActionMove || actions.get(this.current-1) instanceof ActionMoveNearestAir)) actions.get(this.current-1).onTick(dungeonRoom, actionRouteProperties ); + + if (dungeonRoom.getMechanics().get(mechanic).getCurrentState(dungeonRoom).equals(state)) { + this.current = actions.size() - 1; + } + + if (current.isComplete(dungeonRoom)) + next(); + } + + public void onLivingInteract(PlayerInteractEntityEvent event) { getCurrentAction().onLivingInteract(dungeonRoom, event, actionRouteProperties ); } + + @Data + public static class ActionRouteProperties { + private boolean pathfind; + private int lineRefreshRate; + private AColor lineColor; + private float lineWidth; + + private boolean beacon; + private AColor beaconColor; + private AColor beaconBeamColor; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTree.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTree.java new file mode 100755 index 00000000..0fdb97f6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTree.java @@ -0,0 +1,83 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions.tree; + +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionRoot; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +@Data +public class ActionTree implements Cloneable { + @EqualsAndHashCode.Exclude + private Set<ActionTree> parent; + private Action current; + private Set<ActionTree> children; + + @Override + public int hashCode() { return current == null ? 0 : current.hashCode(); } + + + public static ActionTree buildActionTree(Set<Action> actions, DungeonRoom dungeonRoom) { + ActionRoot root = new ActionRoot(); + root.setPreRequisite(actions); + ActionTree tree = new ActionTree(); + tree.setParent(new HashSet<ActionTree>()); + tree.setCurrent(root); + HashSet<ActionTree> set = new HashSet(); + for (Action action : actions) { + set.add(buildActionTree(tree, action, dungeonRoom, new HashMap<Action, ActionTree>())); + } + tree.setChildren(set); + return tree; + } + public static ActionTree buildActionTree(Action actions, DungeonRoom dungeonRoom) { + return buildActionTree(null, actions, dungeonRoom, new HashMap<Action, ActionTree>()); + } + + + + private static ActionTree buildActionTree(ActionTree parent, Action action, DungeonRoom dungeonRoom, Map<Action, ActionTree> alreadyBuilt) { + if (action == null) return null; + if (alreadyBuilt.containsKey(action)) { + ActionTree tree = alreadyBuilt.get(action); + tree.getParent().add(parent); + return tree; + } + + ActionTree tree = new ActionTree(); + alreadyBuilt.put(action, tree); + tree.setParent(new HashSet<ActionTree>()); + if (parent != null) + tree.getParent().add(parent); + tree.setCurrent(action); + HashSet<ActionTree> set = new HashSet(); + for (Action action2 : action.getPreRequisites(dungeonRoom)) { + set.add(buildActionTree(tree, action2, dungeonRoom, alreadyBuilt)); + } + tree.setChildren(set); + return tree; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTreeUtil.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTreeUtil.java new file mode 100644 index 00000000..4054f00d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTreeUtil.java @@ -0,0 +1,83 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.actions.tree; + +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; + +import java.util.*; + +public class ActionTreeUtil { + public static List<Action> linearifyActionTree(ActionTree input) { + ActionTree tree = copyActionTree(input); + + List<Action> actions = new ArrayList<Action>(); + + int plsHalt = 0; + while (tree.getChildren().size() != 0) { + plsHalt ++; + if (plsHalt > 1000000) throw new IllegalStateException("Linearifying process ran for 1 million cycle"); + Set<ActionTree> visited = new HashSet<ActionTree>(); + ActionTree curr = tree; + + int plsHalt2 = 0; + while (curr.getChildren().size() != 0) { + plsHalt2 ++; + if (plsHalt2 > 1000000) throw new IllegalStateException("Finding the leaf of tree ran for 1 million cycles"); + if (visited.contains(curr)) throw new IllegalStateException("Circular Reference Detected"); + visited.add(curr); + curr = curr.getChildren().iterator().next(); + } + + plsHalt2 =0; + while(curr.getChildren().size() == 0) { + plsHalt2 ++; + if (plsHalt2 > 1000000) throw new IllegalStateException("Building of array ran for 1 million cycles"); + + actions.add(curr.getCurrent()); + if (curr.getParent().size() == 0) break; + for (ActionTree parentTree:curr.getParent()) + parentTree.getChildren().remove(curr); + curr = curr.getParent().iterator().next(); + } + } + return actions; + } + + public static ActionTree copyActionTree(ActionTree tree) { + Map<ActionTree, ActionTree> built = new HashMap<ActionTree, ActionTree>(); + if (tree.getParent().size() != 0) throw new IllegalArgumentException("that is not head of tree"); + return copyActionTree(tree, built); + } + private static ActionTree copyActionTree(ActionTree tree, Map<ActionTree, ActionTree> preBuilts) { + if (preBuilts.containsKey(tree)) return preBuilts.get(tree); + + ActionTree clone = new ActionTree(); + preBuilts.put(tree, clone); + + clone.setCurrent(tree.getCurrent()); + clone.setParent(new HashSet<ActionTree>()); + clone.setChildren(new HashSet<ActionTree>()); + for (ActionTree tree3 : tree.getChildren()) { + ActionTree clone3 = copyActionTree(tree3, preBuilts); + clone3.getParent().add(clone); + clone.getChildren().add(clone3); + } + return clone; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java new file mode 100755 index 00000000..ef25fbe1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java @@ -0,0 +1,60 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.data; + +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonMechanic; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +@Getter +@Setter +public class DungeonRoomInfo implements Serializable { + private static final long serialVersionUID = -8291811286448196640L; + + public DungeonRoomInfo(short shape, byte color) { + this.uuid = UUID.randomUUID(); + this.name = this.uuid.toString(); + this.shape = shape; + this.color = color; + } + + private transient boolean registered; + + private boolean isUserMade = false; + + private short shape; + private byte color; + + private int[][] blocks; + + private UUID uuid; + private String name; + + private String processorId = "default"; + + private Map<String, Object> properties = new HashMap<String, Object>(); + + private Map<String, DungeonMechanic> mechanics = new HashMap<String, DungeonMechanic>(); + private int totalSecrets = -1; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java new file mode 100755 index 00000000..180dd76d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java @@ -0,0 +1,110 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.data; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.VectorUtils; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.util.BlockPos; +import net.minecraft.util.Vec3; + +import javax.vecmath.Vector2d; +import java.io.Serializable; + +@Data +@AllArgsConstructor +public class OffsetPoint implements Cloneable, Serializable { + private static final long serialVersionUID = 3102336358774967540L; + + private int x; + private int y; + private int z; + + public OffsetPoint(DungeonRoom dungeonRoom, BlockPos pos) { + setPosInWorld(dungeonRoom, pos); + } + public OffsetPoint(DungeonRoom dungeonRoom, Vec3 pos) { + setPosInWorld(dungeonRoom, new BlockPos((int)pos.xCoord, (int)pos.yCoord, (int)pos.zCoord)); + } + + + public void setPosInWorld(DungeonRoom dungeonRoom, BlockPos pos) { + Vector2d vector2d = new Vector2d(pos.getX() - dungeonRoom.getMin().getX(), pos.getZ() - dungeonRoom.getMin().getZ()); + for (int i = 0; i < dungeonRoom.getRoomMatcher().getRotation(); i++) { + vector2d = VectorUtils.rotateClockwise(vector2d); + if (i % 2 == 0) { + vector2d.x += dungeonRoom.getDungeonRoomInfo().getBlocks()[0].length - 1; // + Z + } else { + vector2d.x += dungeonRoom.getDungeonRoomInfo().getBlocks().length - 1; // + X + } + } + + this.x = (int) vector2d.x; + this.z = (int) vector2d.y; + this.y = pos.getY()-dungeonRoom.getMin().getY(); + } + + public BlockPos toRotatedRelBlockPos(DungeonRoom dungeonRoom) { + int rot = dungeonRoom.getRoomMatcher().getRotation(); + Vector2d rot2 = new Vector2d(x,z); + for (int i = 0; i < dungeonRoom.getRoomMatcher().getRotation(); i++) { + rot2 = VectorUtils.rotateCounterClockwise(rot2); + if (i % 2 == 0) { + rot2.y += dungeonRoom.getMax().getZ() - dungeonRoom.getMin().getZ() + 1; // + Z + } else { + rot2.y += dungeonRoom.getMax().getX() - dungeonRoom.getMin().getX() + 1; // + X + } + } + + return new BlockPos(rot2.x, y, rot2.y); + } + + public Block getBlock(DungeonRoom dungeonRoom) { + BlockPos relBp = toRotatedRelBlockPos(dungeonRoom); + + Block b = dungeonRoom.getRelativeBlockAt(relBp.getX(), relBp.getY(), relBp.getZ()); + return b; + } + public BlockPos getBlockPos(DungeonRoom dungeonRoom) { + BlockPos relBp = toRotatedRelBlockPos(dungeonRoom); + return dungeonRoom.getRelativeBlockPosAt(relBp.getX(), relBp.getY(), relBp.getZ()); + } + + public int getData(DungeonRoom dungeonRoom) { + BlockPos relBp = toRotatedRelBlockPos(dungeonRoom); + + int b = dungeonRoom.getRelativeBlockDataAt(relBp.getX(), relBp.getY(), relBp.getZ()); + return b; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return new OffsetPoint(x,y,z); + } + + @Override + public String toString() { + return "OffsetPoint{x=" + x + + ", y=" + y + + ", z=" + z + + '}'; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java new file mode 100755 index 00000000..c674fdbc --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.data; + +import lombok.Data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@Data +public class OffsetPointSet implements Cloneable, Serializable { + private List<OffsetPoint> offsetPointList = new ArrayList<OffsetPoint>(); + + @Override + public Object clone() throws CloneNotSupportedException { + OffsetPointSet ops = new OffsetPointSet(); + for (OffsetPoint offsetPoint : offsetPointList) { + ops.offsetPointList.add((OffsetPoint) offsetPoint.clone()); + } + return ops; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombDataProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombDataProvider.java new file mode 100755 index 00000000..39eacbc1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombDataProvider.java @@ -0,0 +1,172 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.doorfinder; + +import com.google.common.base.Predicate; +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.*; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.*; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.world.World; + +import javax.vecmath.Vector2d; +import java.util.Collection; +import java.util.Set; + +public class CatacombDataProvider implements DungeonSpecificDataProvider { + + private static final Set<Vector2d> directions = Sets.newHashSet(new Vector2d(0,1), new Vector2d(0, -1), new Vector2d(1, 0), new Vector2d(-1 , 0)); + + @Override + public BlockPos findDoor(World w, String dungeonName) { + Collection<EntityArmorStand> armorStand = w.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() { + @Override + public boolean apply(EntityArmorStand input) { + return input.getName().equals("§bMort"); + } + }); + + if (armorStand.size() != 0) { + EntityArmorStand mort = armorStand.iterator().next(); + BlockPos pos = mort.getPosition(); + pos = pos.add(0, 3, 0); + for (int i = 0; i < 5; i++) { + for (Vector2d vector2d:directions) { + BlockPos test = pos.add(vector2d.x * i, 0, vector2d.y * i); + if (w.getChunkFromBlockCoords(test).getBlock(test) == Blocks.iron_bars) { + return pos.add(vector2d.x * (i + 2), -2, vector2d.y * (i+2)); + } + } + } + } + return null; + } + + @Override + public Vector2d findDoorOffset(World w, String dungeonName) { + Collection<EntityArmorStand> armorStand = w.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() { + @Override + public boolean apply(EntityArmorStand input) { + return input.getName().equals("§bMort"); + } + }); + + if (armorStand.size() != 0) { + EntityArmorStand mort = armorStand.iterator().next(); + BlockPos pos = mort.getPosition(); + pos = pos.add(0, 3, 0); + for (int i = 0; i < 5; i++) { + for (Vector2d vector2d:directions) { + BlockPos test = pos.add(vector2d.x * i, 0, vector2d.y * i); + if (w.getChunkFromBlockCoords(test).getBlock(test) == Blocks.iron_bars) { + return vector2d; + } + } + } + } + return null; + } + /* + * + * */ + + @Override + public BossfightProcessor createBossfightProcessor(World w, String dungeonName) { + String floor = dungeonName.substring(14).trim(); + DungeonsGuide.sendDebugChat(new ChatComponentText("Floor: "+floor+ " Building bossfight processor")); + if (floor.equals("F1")) { + return new BossfightProcessorBonzo(); + } else if (floor.equals("F2")) { + return new BossfightProcessorScarf(); + } else if (floor.equals("F3")) { + return new BossfightProcessorProf(); + } else if (floor.equals("F4")) { + return new BossfightProcessorThorn(); + } else if (floor.equals("F5")) { + return new BossfightProcessorLivid(false); + } else if (floor.equals("F6")) { + return new BossfightProcessorSadan(); + } else if (floor.equals("F7")) { + return new BossfightProcessorNecron(); + } + return null; + } + + @Override + public boolean isTrapSpawn(String dungeonName) { + String floor = dungeonName.substring(14).trim(); + if (floor.equals("F3")) { + return true; + } else if (floor.equals("F4")) { + return true; + } else if (floor.equals("F5")) { + return true; + } else if (floor.equals("F6")) { + return true; + } else return floor.equals("F7"); + } + + @Override + public double secretPercentage(String dungeonName) { + String floor = dungeonName.substring(14).trim(); + if (floor.equals("F1")) { + return 0.3; + } else if (floor.equals("F2")) { + return 0.4; + } else if (floor.equals("F3")) { + return 0.5; + } else if (floor.equals("F4")) { + return 0.6; + } else if (floor.equals("F5")) { + return 0.7; + } else if (floor.equals("F6")) { + return 0.85; + } else if (floor.equals("F7")) { + return 1.0; + } else if (floor.equals("E")) { + return 0.3; + } + return 1.0; + } + + @Override + public int speedSecond(String dungeonName) { + String floor = dungeonName.substring(14).trim(); + if (floor.equals("F1")) { + return 600; + } else if (floor.equals("F2")) { + return 600; + } else if (floor.equals("F3")) { + return 600; + } else if (floor.equals("F4")) { + return 600; + } else if (floor.equals("F5")) { + return 720; + } else if (floor.equals("F6")) { + return 600; + } else if (floor.equals("F7")) { + return 720; + } + return 600; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombMasterDataProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombMasterDataProvider.java new file mode 100755 index 00000000..9d1f63b9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombMasterDataProvider.java @@ -0,0 +1,127 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.doorfinder; + +import com.google.common.base.Predicate; +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.*; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessor; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessorLivid; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.world.World; + +import javax.vecmath.Vector2d; +import java.util.Collection; +import java.util.Set; + +public class CatacombMasterDataProvider implements DungeonSpecificDataProvider { + + private static final Set<Vector2d> directions = Sets.newHashSet(new Vector2d(0,1), new Vector2d(0, -1), new Vector2d(1, 0), new Vector2d(-1 , 0)); + + @Override + public BlockPos findDoor(World w, String dungeonName) { + Collection<EntityArmorStand> armorStand = w.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() { + @Override + public boolean apply(EntityArmorStand input) { + return input.getName().equals("§bMort"); + } + }); + + if (armorStand.size() != 0) { + EntityArmorStand mort = armorStand.iterator().next(); + BlockPos pos = mort.getPosition(); + pos = pos.add(0, 3, 0); + for (int i = 0; i < 5; i++) { + for (Vector2d vector2d:directions) { + BlockPos test = pos.add(vector2d.x * i, 0, vector2d.y * i); + if (w.getChunkFromBlockCoords(test).getBlock(test) == Blocks.iron_bars) { + return pos.add(vector2d.x * (i + 2), -2, vector2d.y * (i+2)); + } + } + } + } + return null; + } + + @Override + public Vector2d findDoorOffset(World w, String dungeonName) { + Collection<EntityArmorStand> armorStand = w.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() { + @Override + public boolean apply(EntityArmorStand input) { + return input.getName().equals("§bMort"); + } + }); + + if (armorStand.size() != 0) { + EntityArmorStand mort = armorStand.iterator().next(); + BlockPos pos = mort.getPosition(); + pos = pos.add(0, 3, 0); + for (int i = 0; i < 5; i++) { + for (Vector2d vector2d:directions) { + BlockPos test = pos.add(vector2d.x * i, 0, vector2d.y * i); + if (w.getChunkFromBlockCoords(test).getBlock(test) == Blocks.iron_bars) { + return vector2d; + } + } + } + } + return null; + } + /* + * + * */ + + @Override + public BossfightProcessor createBossfightProcessor(World w, String dungeonName) { + String floor = dungeonName.substring(14).trim(); + DungeonsGuide.sendDebugChat(new ChatComponentText("Floor: Master mode "+floor+ " Building bossfight processor")); + if (floor.equals("M5")) { + return new BossfightProcessorLivid(true); + } + return null; + } + + @Override + public boolean isTrapSpawn(String dungeonName) { + String floor = dungeonName.substring(14).trim(); + if (floor.equals("M3")) { + return true; + } else if (floor.equals("M4")) { + return true; + } else if (floor.equals("M5")) { + return true; + } else if (floor.equals("M6")) { + return true; + } else return floor.equals("M7"); + } + + @Override + public double secretPercentage(String dungeonName) { + return 1.0; + } + + @Override + public int speedSecond(String dungeonName) { + return 480; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonDoor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonDoor.java new file mode 100755 index 00000000..d0b61120 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonDoor.java @@ -0,0 +1,81 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.doorfinder; + +import com.google.common.collect.Sets; +import lombok.Getter; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +import java.util.Set; + +@Getter +public class DungeonDoor { + private final World w; + private final BlockPos position; + private EDungeonDoorType type; + private boolean isZDir; + + private static final Set<Block> legalBlocks = Sets.newHashSet(Blocks.coal_block, Blocks.barrier, Blocks.monster_egg, Blocks.air, Blocks.stained_hardened_clay); + + public DungeonDoor(World world, BlockPos pos, EDungeonDoorType type) { + this.w = world; + this.position = pos; + Block itshouldbeall = world.getChunkFromBlockCoords(pos).getBlock(pos); + + if (type == EDungeonDoorType.WITHER && itshouldbeall == Blocks.air) type = EDungeonDoorType.WITHER_FAIRY; + this.type = type; + boolean exist = type.isExist(); + + for (int x = -1; x<=1; x++) + for (int y = -1; y<=1; y++) + for (int z = -1; z<=1; z++) { + BlockPos pos2 = pos.add(x,y,z); + Block block = world.getChunkFromBlockCoords(pos2).getBlock(pos2); + if (itshouldbeall != block) exist = false; + } + if (exist) { + BlockPos ZCheck = pos.add(0,0,2); + isZDir = world.getChunkFromBlockCoords(ZCheck).getBlock(ZCheck) == Blocks.air; + + if (isZDir) { + for (int x = -1; x<=1; x++) + for (int y = -1; y<=1; y++) + for (int z = -2; z<=2; z+=4) { + BlockPos pos2 = pos.add(x,y,z); + Block block = world.getChunkFromBlockCoords(pos2).getBlock(pos2); + if (block != Blocks.air) exist = false; + } + } else { + for (int x = -2; x<=2; x+=4) + for (int y = -1; y<=1; y++) + for (int z = -1; z<=1; z++) { + BlockPos pos2 = pos.add(x,y,z); + Block block = world.getChunkFromBlockCoords(pos2).getBlock(pos2); + if (block != Blocks.air) exist = false; + } + } + } + if (!exist) { + isZDir = false; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProvider.java new file mode 100755 index 00000000..4145188c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProvider.java @@ -0,0 +1,38 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.doorfinder; + +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessor; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +import javax.vecmath.Vector2d; + +public interface DungeonSpecificDataProvider { + BlockPos findDoor(World w, String dungeonName); + Vector2d findDoorOffset(World w, String dungeonName); + + BossfightProcessor createBossfightProcessor(World w, String dungeonName); + + boolean isTrapSpawn(String dungeonName); + + double secretPercentage(String dungeonName); + + int speedSecond(String dungeonName); +}
\ No newline at end of file diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProviderRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProviderRegistry.java new file mode 100755 index 00000000..7421728e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProviderRegistry.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.doorfinder; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +public class DungeonSpecificDataProviderRegistry { + public static final Map<Pattern, DungeonSpecificDataProvider> doorFinders = new HashMap<Pattern, DungeonSpecificDataProvider>(); + + static { + doorFinders.put(Pattern.compile("The Catacombs (?:F[0-9]|E)"), new CatacombDataProvider()); + doorFinders.put(Pattern.compile("The Catacombs (?:M[0-9])"), new CatacombMasterDataProvider()); + } + + public static DungeonSpecificDataProvider getDoorFinder(String dungeonName) { + for (Map.Entry<Pattern, DungeonSpecificDataProvider> doorFinderEntry :doorFinders.entrySet()){ + if (doorFinderEntry.getKey().matcher(dungeonName).matches()) return doorFinderEntry.getValue(); + } + return null; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/EDungeonDoorType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/EDungeonDoorType.java new file mode 100644 index 00000000..3a07629e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/EDungeonDoorType.java @@ -0,0 +1,33 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.doorfinder; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum EDungeonDoorType { + NONE(false, false, false,"?"), ENTRANCE(true, false, false, "entrance"), WITHER(true, true,true,"withergate"),WITHER_FAIRY(true, false,true,"wither-fairy-gate"), BLOOD(true, true,true, "bloodgate"), UNOPEN(true, false, false,"gate"); + + private boolean exist; + private boolean keyRequired; + private boolean headToBlood; + private String name; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonCryptBrokenEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonCryptBrokenEvent.java new file mode 100644 index 00000000..9e16498b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonCryptBrokenEvent.java @@ -0,0 +1,34 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class DungeonCryptBrokenEvent implements DungeonEventData { + private int prevCrypts; + private int newCrypts; + + @Override + public String getEventName() { + return "CRYPTS_CHANGE"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonDeathEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonDeathEvent.java new file mode 100644 index 00000000..bbb2481d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonDeathEvent.java @@ -0,0 +1,35 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class DungeonDeathEvent implements DungeonEventData { + private String playerName; + private String message; + private int cnt; + + @Override + public String getEventName() { + return "PLAYER_DEATH"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEvent.java new file mode 100644 index 00000000..a62997bf --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEvent.java @@ -0,0 +1,41 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class DungeonEvent implements Serializable { + private long UTCTime = System.currentTimeMillis(); + private long realTimeElapsed; + private long skyblockTimeElapsed; + + private String eventName; + private DungeonEventData data; + + public DungeonEvent(DungeonEventData eventData){ + this.data = eventData; + this.realTimeElapsed = FeatureRegistry.DUNGEON_REALTIME.getTimeElapsed(); + this.skyblockTimeElapsed = FeatureRegistry.DUNGEON_SBTIME.getTimeElapsed(); + this.eventName = eventData.getEventName(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventData.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventData.java new file mode 100644 index 00000000..a75d0f02 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventData.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import java.io.Serializable; + +public interface DungeonEventData extends Serializable { + String getEventName(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventHolder.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventHolder.java new file mode 100644 index 00000000..3e431107 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventHolder.java @@ -0,0 +1,32 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +@Data +public class DungeonEventHolder implements Serializable { + private long date; + private Set<String> players; + private List<DungeonEvent> eventDataList; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonMapUpdateEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonMapUpdateEvent.java new file mode 100644 index 00000000..a29d2f01 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonMapUpdateEvent.java @@ -0,0 +1,33 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class DungeonMapUpdateEvent implements DungeonEventData { + private byte[] map; + + @Override + public String getEventName() { + return "MAP_UPDATE"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonNodataEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonNodataEvent.java new file mode 100644 index 00000000..4db127d6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonNodataEvent.java @@ -0,0 +1,28 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class DungeonNodataEvent implements DungeonEventData { + private String eventName; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonPuzzleFailureEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonPuzzleFailureEvent.java new file mode 100644 index 00000000..88d6377f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonPuzzleFailureEvent.java @@ -0,0 +1,33 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class DungeonPuzzleFailureEvent implements DungeonEventData { + private String playerName; + private String message; + @Override + public String getEventName() { + return "PUZZLE_FAILURE"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonRoomDiscoverEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonRoomDiscoverEvent.java new file mode 100644 index 00000000..8cec640c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonRoomDiscoverEvent.java @@ -0,0 +1,44 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.awt.*; +import java.util.UUID; + +@Data +@AllArgsConstructor +public class DungeonRoomDiscoverEvent implements DungeonEventData { + private Point unitPt; + private int rotation; + private SerializableBlockPos min; + private SerializableBlockPos max; + private int shape; + private int color; + private UUID roomUID; + private String roomName; + private String roomProc; + + @Override + public String getEventName() { + return "ROOM_DISCOVER"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonSecretCountChangeEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonSecretCountChangeEvent.java new file mode 100644 index 00000000..702d61ba --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonSecretCountChangeEvent.java @@ -0,0 +1,36 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class DungeonSecretCountChangeEvent implements DungeonEventData { + private int prevCount; + private int newCount; + private int totalSecret; + private boolean sureTotalSecret; + + @Override + public String getEventName() { + return "SECRET_CNT_CHANGE"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonStateChangeEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonStateChangeEvent.java new file mode 100644 index 00000000..16cb9661 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonStateChangeEvent.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.awt.*; + +@Data +@AllArgsConstructor +public class DungeonStateChangeEvent implements DungeonEventData { + private Point unitPt; + private String roomName; + private DungeonRoom.RoomState from; + private DungeonRoom.RoomState to; + + @Override + public String getEventName() { + return "ROOM_STATE_CHANGE"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/SerializableBlockPos.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/SerializableBlockPos.java new file mode 100644 index 00000000..ab1031e7 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/SerializableBlockPos.java @@ -0,0 +1,36 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.events; + +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.util.BlockPos; + +import java.io.Serializable; + +@Data @AllArgsConstructor +public class SerializableBlockPos implements Serializable { + private int x, y, z; + + public SerializableBlockPos(BlockPos pos) { + this.x = pos.getX(); + this.y = pos.getY(); + this.z = pos.getZ(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonBreakableWall.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonBreakableWall.java new file mode 100755 index 00000000..9f11cde9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonBreakableWall.java @@ -0,0 +1,157 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionBreakWithSuperBoom; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMoveNearestAir; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.*; +import java.util.List; + +@Data +public class DungeonBreakableWall implements DungeonMechanic, RouteBlocker { + private static final long serialVersionUID = 1161593374765852217L; + private OffsetPointSet secretPoint = new OffsetPointSet(); + private List<String> preRequisite = new ArrayList<String>(); + + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (state.equalsIgnoreCase("navigate")) { + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + + int leastY = Integer.MAX_VALUE; + OffsetPoint thatPt = null; + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + if (offsetPoint.getY() < leastY) { + thatPt = offsetPoint; + leastY = offsetPoint.getY(); + } + } + ActionMoveNearestAir actionMove = new ActionMoveNearestAir(thatPt); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + return base; + } + + if (!"open".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for breakable wall"); + if (!isBlocking(dungeonRoom)) { + return Collections.emptySet(); + } + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + { + ActionBreakWithSuperBoom actionClick; + preRequisites.add(actionClick = new ActionBreakWithSuperBoom(getRepresentingPoint(dungeonRoom))); + preRequisites = actionClick.getPreRequisite(); + } + { + + int leastY = Integer.MAX_VALUE; + OffsetPoint thatPt = null; + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + if (offsetPoint.getY() < leastY) { + thatPt = offsetPoint; + leastY = offsetPoint.getY(); + } + } + ActionMoveNearestAir actionMove = new ActionMoveNearestAir(thatPt); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + } + { + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + if (secretPoint.getOffsetPointList().isEmpty()) return; + OffsetPoint firstpt = secretPoint.getOffsetPointList().get(0); + BlockPos pos = firstpt.getBlockPos(dungeonRoom); + RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + RenderUtils.highlightBlock(offsetPoint.getBlockPos(dungeonRoom), color,partialTicks); + } + } + + @Override + public boolean isBlocking(DungeonRoom dungeonRoom) { + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + if (offsetPoint.getBlock(dungeonRoom) != Blocks.air) return true; + } + return false; + } + + public DungeonBreakableWall clone() throws CloneNotSupportedException { + DungeonBreakableWall dungeonSecret = new DungeonBreakableWall(); + dungeonSecret.secretPoint = (OffsetPointSet) secretPoint.clone(); + dungeonSecret.preRequisite = new ArrayList<String>(preRequisite); + return dungeonSecret; + } + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + Block b = Blocks.air; + if (!secretPoint.getOffsetPointList().isEmpty()) + b = secretPoint.getOffsetPointList().get(0).getBlock(dungeonRoom); + + return b == Blocks.air ?"open" :"closed"; + } + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + return isBlocking(dungeonRoom) ? Sets.newHashSet("navigate", "open") : Sets.newHashSet("navigate"); + } + + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("open", "closed"); + } + + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + return secretPoint.getOffsetPointList().size() == 0 ? null : secretPoint.getOffsetPointList().get(secretPoint.getOffsetPointList().size() / 2); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDoor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDoor.java new file mode 100755 index 00000000..79ab6fcf --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDoor.java @@ -0,0 +1,129 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.List; +import java.util.*; + +@Data +public class DungeonDoor implements DungeonMechanic, RouteBlocker { + private static final long serialVersionUID = -1011605722415475761L; + private OffsetPointSet secretPoint = new OffsetPointSet(); + private List<String> openPreRequisite = new ArrayList<String>(); + private List<String> closePreRequisite = new ArrayList<String>(); + + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (!("open".equalsIgnoreCase(state) || "closed".equalsIgnoreCase(state))) throw new IllegalArgumentException(state+" is not valid state for door"); + if (state.equalsIgnoreCase(getCurrentState(dungeonRoom))) return Collections.emptySet(); + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + { + if (state.equalsIgnoreCase("open")) { + for (String str : openPreRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } else { + for (String str : closePreRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + if (secretPoint.getOffsetPointList().isEmpty()) return; + OffsetPoint firstpt = secretPoint.getOffsetPointList().get(0); + BlockPos pos = firstpt.getBlockPos(dungeonRoom); + RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + RenderUtils.highlightBlock(offsetPoint.getBlockPos(dungeonRoom), color,partialTicks); + } + } + + @Override + public boolean isBlocking(DungeonRoom dungeonRoom) { + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + if (offsetPoint.getBlock(dungeonRoom) != Blocks.air) return true; + } + return false; + } + + public DungeonDoor clone() throws CloneNotSupportedException { + DungeonDoor dungeonSecret = new DungeonDoor(); + dungeonSecret.secretPoint = (OffsetPointSet) secretPoint.clone(); + dungeonSecret.openPreRequisite = new ArrayList<String>(openPreRequisite); + dungeonSecret.closePreRequisite = new ArrayList<String>(closePreRequisite); + return dungeonSecret; + } + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + return isBlocking(dungeonRoom) ?"closed":"open"; + } + + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + String currentStatus = getCurrentState(dungeonRoom); + if (currentStatus.equalsIgnoreCase("closed")) + return Collections.singleton("open"); + else if (currentStatus.equalsIgnoreCase("open")) + return Collections.singleton("closed"); + return Collections.emptySet(); + } + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("open", "closed"); + } + + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + int leastY = Integer.MAX_VALUE; + OffsetPoint thatPt = null; + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + if (offsetPoint.getY() < leastY) { + thatPt = offsetPoint; + leastY = offsetPoint.getY(); + } + } + return thatPt; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDummy.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDummy.java new file mode 100755 index 00000000..79f079c1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDummy.java @@ -0,0 +1,108 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionClick; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMove; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Data +public class DungeonDummy implements DungeonMechanic { + private static final long serialVersionUID = -8449664812034435765L; + private OffsetPoint secretPoint = new OffsetPoint(0,0,0); + private List<String> preRequisite = new ArrayList<String>(); + + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { +// if (!"navigate".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret"); + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + if (state.equalsIgnoreCase("navigate")){ + ActionMove actionMove = new ActionMove(secretPoint); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + } else if (state.equalsIgnoreCase("click")) { + ActionClick actionClick = new ActionClick(secretPoint); + preRequisites.add(actionClick); + preRequisites = actionClick.getPreRequisite(); + + ActionMove actionMove = new ActionMove(secretPoint); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + + } + { + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + BlockPos pos = getSecretPoint().getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, color,partialTicks); + RenderUtils.drawTextAtWorld("D-"+name, pos.getX() +0.5f, pos.getY()+0.375f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + } + + + public DungeonDummy clone() throws CloneNotSupportedException { + DungeonDummy dungeonSecret = new DungeonDummy(); + dungeonSecret.secretPoint = (OffsetPoint) secretPoint.clone(); + dungeonSecret.preRequisite = new ArrayList<String>(preRequisite); + return dungeonSecret; + } + + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + return "no-state"; + } + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("navigate", "click"); + } + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("no-state","navigate,click"); + } + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + return secretPoint; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonFairySoul.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonFairySoul.java new file mode 100755 index 00000000..1c110bb5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonFairySoul.java @@ -0,0 +1,105 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionInteract; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMove; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates.PredicateArmorStand; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.List; +import java.util.*; + +@Data +public class DungeonFairySoul implements DungeonMechanic { + private static final long serialVersionUID = 156412742320519783L; + private OffsetPoint secretPoint = new OffsetPoint(0,0,0); + private List<String> preRequisite = new ArrayList<String>(); + + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (!"navigate".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret"); + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + { + ActionInteract actionClick= new ActionInteract(secretPoint); + actionClick.setPredicate(PredicateArmorStand.INSTANCE); + actionClick.setRadius(3); + preRequisites.add(actionClick); + preRequisites = actionClick.getPreRequisite(); + } + { + ActionMove actionMove = new ActionMove(secretPoint); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + } + { + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + BlockPos pos = getSecretPoint().getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, color,partialTicks); + RenderUtils.drawTextAtWorld("F-"+name, pos.getX() +0.5f, pos.getY()+0.375f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + } + + + public DungeonFairySoul clone() throws CloneNotSupportedException { + DungeonFairySoul dungeonSecret = new DungeonFairySoul(); + dungeonSecret.secretPoint = (OffsetPoint) secretPoint.clone(); + dungeonSecret.preRequisite = new ArrayList<String>(preRequisite); + return dungeonSecret; + } + + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + return "no-state"; + } + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("navigate"); + } + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("no-state","navigate"); + } + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + return secretPoint; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonJournal.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonJournal.java new file mode 100755 index 00000000..f0edc4a6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonJournal.java @@ -0,0 +1,98 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMove; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Data +public class DungeonJournal implements DungeonMechanic { + private static final long serialVersionUID = 4117372070037496743L; + private OffsetPoint secretPoint = new OffsetPoint(0,0,0); + private List<String> preRequisite = new ArrayList<String>(); + + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (!"navigate".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret"); + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + { + ActionMove actionMove = new ActionMove(secretPoint); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + } + { + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + BlockPos pos = getSecretPoint().getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, color,partialTicks); + RenderUtils.drawTextAtWorld("J-"+name, pos.getX() +0.5f, pos.getY()+0.375f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + } + + + public DungeonJournal clone() throws CloneNotSupportedException { + DungeonJournal dungeonSecret = new DungeonJournal(); + dungeonSecret.secretPoint = (OffsetPoint) secretPoint.clone(); + dungeonSecret.preRequisite = new ArrayList<String>(preRequisite); + return dungeonSecret; + } + + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + return "no-state"; + } + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("navigate"); + } + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("no-state","navigate"); + } + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + return secretPoint; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonLever.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonLever.java new file mode 100755 index 00000000..5bc1f650 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonLever.java @@ -0,0 +1,130 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.actions.*; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.List; +import java.util.*; + +@Data +public class DungeonLever implements DungeonMechanic { + private OffsetPoint leverPoint = new OffsetPoint(0,0,0); + private List<String> preRequisite = new ArrayList<String>(); + private String triggering = ""; + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (state.equals(getCurrentState(dungeonRoom))) return Collections.emptySet(); + if (state.equalsIgnoreCase("navigate")) { + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom)); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + return base; + } + + if (!("triggered".equalsIgnoreCase(state) || "untriggered".equalsIgnoreCase(state))) throw new IllegalArgumentException(state+" is not valid state for secret"); + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + if (!state.equalsIgnoreCase(getCurrentState(dungeonRoom))){ + ActionClick actionClick; + preRequisites.add(actionClick = new ActionClick(leverPoint)); + preRequisites = actionClick.getPreRequisite(); + } + { + ActionMove actionMove = new ActionMove(leverPoint); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + } + { + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + BlockPos pos = getLeverPoint().getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, color,partialTicks); + RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + } + + public DungeonLever clone() throws CloneNotSupportedException { + DungeonLever dungeonSecret = new DungeonLever(); + dungeonSecret.leverPoint = (OffsetPoint) leverPoint.clone(); + dungeonSecret.triggering = triggering; + dungeonSecret.preRequisite = new ArrayList<String>(preRequisite); + return dungeonSecret; + } + + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + if (triggering == null) triggering = "null"; + DungeonMechanic mechanic = dungeonRoom.getMechanics().get(triggering); + if (mechanic == null) + { + return "undeterminable"; + } else { + String state = mechanic.getCurrentState(dungeonRoom); + if ("open".equalsIgnoreCase(state)) { + return "triggered"; + } else { + return "untriggered"; + } + } + } + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + String currentStatus = getCurrentState(dungeonRoom); + if (currentStatus.equalsIgnoreCase("untriggered")) + return Sets.newHashSet("navigate", "triggered"); + else if (currentStatus.equalsIgnoreCase("triggered")) + return Sets.newHashSet("navigate","untriggered"); + return Sets.newHashSet("navigate"); + } + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("triggered", "untriggered"); + } + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + return leverPoint; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonMechanic.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonMechanic.java new file mode 100755 index 00000000..677a5489 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonMechanic.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; + +import java.awt.*; +import java.io.Serializable; +import java.util.Set; + +public interface DungeonMechanic extends Serializable { + Set<Action> getAction(String state, DungeonRoom dungeonRoom); + + void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks); + + String getCurrentState(DungeonRoom dungeonRoom); + + Set<String> getPossibleStates(DungeonRoom dungeonRoom); + Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom); + + OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonNPC.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonNPC.java new file mode 100755 index 00000000..e1fc4bfc --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonNPC.java @@ -0,0 +1,107 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionInteract; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMove; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates.PredicateArmorStand; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Data +public class DungeonNPC implements DungeonMechanic { + private static final long serialVersionUID = -89487601113028763L; + private OffsetPoint secretPoint = new OffsetPoint(0,0,0); + private List<String> preRequisite = new ArrayList<String>(); + + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (!"navigate".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret"); + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + { + ActionInteract actionClick= new ActionInteract(secretPoint); + actionClick.setPredicate(PredicateArmorStand.INSTANCE); + actionClick.setRadius(3); + preRequisites.add(actionClick); + preRequisites = actionClick.getPreRequisite(); + } + { + ActionMove actionMove = new ActionMove(secretPoint); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + } + { + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + BlockPos pos = getSecretPoint().getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, color,partialTicks); + RenderUtils.drawTextAtWorld("F-"+name, pos.getX() +0.5f, pos.getY()+0.375f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + } + + + public DungeonNPC clone() throws CloneNotSupportedException { + DungeonNPC dungeonSecret = new DungeonNPC(); + dungeonSecret.secretPoint = (OffsetPoint) secretPoint.clone(); + dungeonSecret.preRequisite = new ArrayList<String>(preRequisite); + return dungeonSecret; + } + + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + return "no-state"; + } + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("navigate"); + } + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("no-state","navigate"); + } + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + return secretPoint; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayDoor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayDoor.java new file mode 100755 index 00000000..b97f84d0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayDoor.java @@ -0,0 +1,134 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMoveNearestAir; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.List; +import java.util.*; + +@Data +public class DungeonOnewayDoor implements DungeonMechanic, RouteBlocker { + private static final long serialVersionUID = -1810891721127873330L; + private OffsetPointSet secretPoint = new OffsetPointSet(); + private List<String> preRequisite = new ArrayList<String>(); + + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (state.equalsIgnoreCase("navigate")) { + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom)); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + return base; + } + if (!("open".equalsIgnoreCase(state))) throw new IllegalArgumentException(state+" is not valid state for door"); + if (!isBlocking(dungeonRoom)) { + return Collections.emptySet(); + } + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + { + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + if (secretPoint.getOffsetPointList().isEmpty()) return; + OffsetPoint firstpt = secretPoint.getOffsetPointList().get(0); + BlockPos pos = firstpt.getBlockPos(dungeonRoom); + RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + RenderUtils.highlightBlock(offsetPoint.getBlockPos(dungeonRoom), color,partialTicks); + } + } + + @Override + public boolean isBlocking(DungeonRoom dungeonRoom) { + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + if (offsetPoint.getBlock(dungeonRoom) != Blocks.air) return true; + } + return false; + } + + public DungeonOnewayDoor clone() throws CloneNotSupportedException { + DungeonOnewayDoor dungeonSecret = new DungeonOnewayDoor(); + dungeonSecret.secretPoint = (OffsetPointSet) secretPoint.clone(); + dungeonSecret.preRequisite = new ArrayList<String>(preRequisite); + return dungeonSecret; + } + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + return isBlocking(dungeonRoom) ?"closed":"open"; + } + + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + String currentStatus = getCurrentState(dungeonRoom); + if (currentStatus.equalsIgnoreCase("closed")) + return Sets.newHashSet("navigate", "open"); + return Sets.newHashSet("navigate"); + } + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("open", "closed"); + } + + + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + int leastY = Integer.MAX_VALUE; + OffsetPoint thatPt = null; + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + if (offsetPoint.getY() < leastY) { + thatPt = offsetPoint; + leastY = offsetPoint.getY(); + } + } + return thatPt; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayLever.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayLever.java new file mode 100755 index 00000000..8403efca --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayLever.java @@ -0,0 +1,129 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.actions.*; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.*; +import java.util.List; + +@Data +public class DungeonOnewayLever implements DungeonMechanic { + private static final long serialVersionUID = -3203171200265540652L; + private OffsetPoint leverPoint = new OffsetPoint(0,0,0); + private List<String> preRequisite = new ArrayList<String>(); + private String triggering = ""; + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (state.equals(getCurrentState(dungeonRoom))) return Collections.emptySet(); + if (state.equalsIgnoreCase("navigate")) { + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom)); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + return base; + } + if (!("triggered".equalsIgnoreCase(state))) throw new IllegalArgumentException(state+" is not valid state for secret"); + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + { + ActionClick actionClick; + preRequisites.add(actionClick = new ActionClick(leverPoint)); + preRequisites = actionClick.getPreRequisite(); + } + { + ActionMove actionMove = new ActionMove(leverPoint); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + } + { + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + BlockPos pos = getLeverPoint().getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, color,partialTicks); + RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + } + + public DungeonOnewayLever clone() throws CloneNotSupportedException { + DungeonOnewayLever dungeonSecret = new DungeonOnewayLever(); + dungeonSecret.leverPoint = (OffsetPoint) leverPoint.clone(); + dungeonSecret.triggering = triggering; + dungeonSecret.preRequisite = new ArrayList<String>(preRequisite); + return dungeonSecret; + } + + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + if (triggering == null) triggering = "null"; + DungeonMechanic mechanic = dungeonRoom.getMechanics().get(triggering); + if (mechanic == null) + { + return "undeterminable"; + } else { + String state = mechanic.getCurrentState(dungeonRoom); + if ("open".equalsIgnoreCase(state)) { + return "triggered"; + } else { + return "untriggered"; + } + } + } + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + String currentStatus = getCurrentState(dungeonRoom); + if (currentStatus.equalsIgnoreCase("untriggered")) + return Sets.newHashSet("navigate", "triggered"); + return Sets.newHashSet("navigate"); + } + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("triggered", "untriggered"); + } + + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + return leverPoint; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonPressurePlate.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonPressurePlate.java new file mode 100755 index 00000000..8d79d924 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonPressurePlate.java @@ -0,0 +1,132 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.actions.*; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.*; +import java.util.List; + +@Data +public class DungeonPressurePlate implements DungeonMechanic { + private static final long serialVersionUID = 7450034718355390645L; + private OffsetPoint platePoint = new OffsetPoint(0,0,0); + private List<String> preRequisite = new ArrayList<String>(); + private String triggering = ""; + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (state.equals(getCurrentState(dungeonRoom))) return Collections.emptySet(); + if (state.equalsIgnoreCase("navigate")) { + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom)); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + return base; + } + if (!("triggered".equalsIgnoreCase(state) || "untriggered".equalsIgnoreCase(state))) throw new IllegalArgumentException(state+" is not valid state for secret"); + if (state.equalsIgnoreCase(getCurrentState(dungeonRoom))) return Collections.emptySet(); + + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + if ("triggered".equalsIgnoreCase(state)) { + ActionDropItem actionClick; + preRequisites.add(actionClick = new ActionDropItem(platePoint)); + preRequisites = actionClick.getPreRequisite(); + } + { + ActionMove actionMove = new ActionMove(platePoint); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + } + { + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + BlockPos pos = getPlatePoint().getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, color,partialTicks); + RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + } + + public DungeonPressurePlate clone() throws CloneNotSupportedException { + DungeonPressurePlate dungeonSecret = new DungeonPressurePlate(); + dungeonSecret.platePoint = (OffsetPoint) platePoint.clone(); + dungeonSecret.triggering = triggering; + dungeonSecret.preRequisite = new ArrayList<String>(preRequisite); + return dungeonSecret; + } + + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + if (triggering == null) triggering = "null"; + DungeonMechanic mechanic = dungeonRoom.getMechanics().get(triggering); + if (mechanic == null) + { + return "undeterminable"; + } else { + String state = mechanic.getCurrentState(dungeonRoom); + if ("open".equalsIgnoreCase(state)) { + return "triggered"; + } else { + return "untriggered"; + } + } + } + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + String currentStatus = getCurrentState(dungeonRoom); + if (currentStatus.equalsIgnoreCase("triggered")) + return Sets.newHashSet("navigate", "untriggered"); + else if (currentStatus.equalsIgnoreCase("untriggered")) + return Sets.newHashSet("navigate", "triggered"); + return Sets.newHashSet("navigate"); + } + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("triggered", "untriggered"); + } + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + return platePoint; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonRoomDoor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonRoomDoor.java new file mode 100644 index 00000000..6b0d58f8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonRoomDoor.java @@ -0,0 +1,98 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMove; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonDoor; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.HashSet; +import java.util.Set; + +public class DungeonRoomDoor implements DungeonMechanic { + @Getter + private final DungeonDoor doorfinder; + private OffsetPoint offsetPoint; + + public DungeonRoomDoor(DungeonRoom dungeonRoom, DungeonDoor doorfinder) { + this.doorfinder = doorfinder; + if (doorfinder.isZDir()) { + if (dungeonRoom.canAccessAbsolute(doorfinder.getPosition().add(0,0,2))) + offsetPoint = new OffsetPoint(dungeonRoom, doorfinder.getPosition().add(0,0,2)); + else if (dungeonRoom.canAccessAbsolute(doorfinder.getPosition().add(0,0,-2))) + offsetPoint = new OffsetPoint(dungeonRoom, doorfinder.getPosition().add(0,0,-2)); + } else { + if (dungeonRoom.canAccessAbsolute(doorfinder.getPosition().add(2,0,0))) + offsetPoint = new OffsetPoint(dungeonRoom, doorfinder.getPosition().add(2,0,0)); + else if (dungeonRoom.canAccessAbsolute(doorfinder.getPosition().add(-2,0,0))) + offsetPoint = new OffsetPoint(dungeonRoom, doorfinder.getPosition().add(-2,0,0)); + } + if (offsetPoint == null) { + offsetPoint = new OffsetPoint(dungeonRoom, doorfinder.getPosition()); + } + } + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (!"navigate".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret"); + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + { + ActionMove actionMove = new ActionMove(offsetPoint); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + BlockPos pos = offsetPoint.getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, color,partialTicks); + RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + } + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + return doorfinder.getType().isKeyRequired() ? "key" : "normal"; + } + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("navigate"); + } + + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("key-open", "key-closed", "normal"); + } + + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + return offsetPoint; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonSecret.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonSecret.java new file mode 100755 index 00000000..b03d5b3a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonSecret.java @@ -0,0 +1,239 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.actions.*; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.DungeonActionManager; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates.PredicateBat; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.pathfinding.NodeProcessorDungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.tileentity.TileEntityChest; +import net.minecraft.util.BlockPos; +import net.minecraft.util.Vec3; + +import java.awt.*; +import java.util.*; +import java.util.List; + +@Data +public class DungeonSecret implements DungeonMechanic { + private static final long serialVersionUID = 8784808599222706537L; + + private OffsetPoint secretPoint = new OffsetPoint(0,0,0); + private SecretType secretType = SecretType.CHEST; + private List<String> preRequisite = new ArrayList<String>(); + + public void tick(DungeonRoom dungeonRoom) { + if (secretType == SecretType.CHEST) { + BlockPos pos = secretPoint.getBlockPos(dungeonRoom); + IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(pos); + if (blockState.getBlock() == Blocks.chest || blockState.getBlock() == Blocks.trapped_chest) { + TileEntityChest chest = (TileEntityChest) dungeonRoom.getContext().getWorld().getTileEntity(pos); + if (chest.numPlayersUsing > 0) { + dungeonRoom.getRoomContext().put("c-"+pos.toString(), 2); + } else { + dungeonRoom.getRoomContext().put("c-"+pos.toString(), 1); + } + } + } else if (secretType == SecretType.ESSENCE) { + BlockPos pos = secretPoint.getBlockPos(dungeonRoom); + IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(pos); + if (blockState.getBlock() == Blocks.skull) { + dungeonRoom.getRoomContext().put("e-"+pos.toString(), true); + } + } else if (secretType == SecretType.ITEM_DROP) { + Vec3 pos = new Vec3(secretPoint.getBlockPos(dungeonRoom)); + Vec3 player = Minecraft.getMinecraft().thePlayer.getPositionVector(); + if (player.squareDistanceTo(pos) < 16) { + Vec3 vec3 = pos.subtract(player).normalize(); + for (int i = 0; i < player.distanceTo(pos); i++) { + Vec3 vec = player.addVector(vec3.xCoord * i, vec3.yCoord * i, vec3.zCoord * i); + BlockPos bpos = new BlockPos(vec); + IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(bpos); + if (!NodeProcessorDungeonRoom.isValidBlock(blockState)) + return; + } + dungeonRoom.getRoomContext().put("i-" + pos, true); + } + } + } + + public SecretStatus getSecretStatus(DungeonRoom dungeonRoom) { + if (secretType == SecretType.CHEST) { + BlockPos pos = secretPoint.getBlockPos(dungeonRoom); + IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(pos); + if (dungeonRoom.getRoomContext().containsKey("c-"+pos.toString())) + return ((int)dungeonRoom.getRoomContext().get("c-"+pos.toString()) == 2 || blockState.getBlock() == Blocks.air) ? SecretStatus.FOUND : SecretStatus.CREATED; + + if (blockState.getBlock() == Blocks.air) { + return SecretStatus.DEFINITELY_NOT; + } else if (blockState.getBlock() != Blocks.chest && blockState.getBlock() != Blocks.trapped_chest) { + return SecretStatus.ERROR; + } else { + TileEntityChest chest = (TileEntityChest) dungeonRoom.getContext().getWorld().getTileEntity(pos); + if (chest.numPlayersUsing > 0) { + return SecretStatus.FOUND; + } else{ + return SecretStatus.CREATED; + } + } + } else if (secretType == SecretType.ESSENCE) { + BlockPos pos = secretPoint.getBlockPos(dungeonRoom); + IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(pos); + if (blockState.getBlock() == Blocks.skull) { + dungeonRoom.getRoomContext().put("e-"+pos.toString(), true); + return SecretStatus.DEFINITELY_NOT; + } else { + if (dungeonRoom.getRoomContext().containsKey("e-"+pos.toString())) + return SecretStatus.FOUND; + return SecretStatus.NOT_SURE; + } + } else if (secretType == SecretType.BAT) { + Vec3 spawn = new Vec3(secretPoint.getBlockPos(dungeonRoom)); + for (Integer killed : DungeonActionManager.getKilleds()) { + if (DungeonActionManager.getSpawnLocation().get(killed) == null) continue; + if (DungeonActionManager.getSpawnLocation().get(killed).squareDistanceTo(spawn) < 100) { + return SecretStatus.FOUND; + } + } + return SecretStatus.NOT_SURE; + } else { + Vec3 pos = new Vec3(secretPoint.getBlockPos(dungeonRoom)); + if (dungeonRoom.getRoomContext().containsKey("i-"+ pos)) + return SecretStatus.FOUND; + Vec3 player = Minecraft.getMinecraft().thePlayer.getPositionVector(); + if (player.squareDistanceTo(pos) < 16) { + Vec3 vec3 = pos.subtract(player).normalize(); + for (int i = 0; i < player.distanceTo(pos); i++) { + Vec3 vec = player.addVector(vec3.xCoord * i, vec3.yCoord * i, vec3.zCoord * i); + BlockPos bpos = new BlockPos(vec); + IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(bpos); + if (!NodeProcessorDungeonRoom.isValidBlock(blockState)) + return SecretStatus.NOT_SURE; + } + dungeonRoom.getRoomContext().put("i-" + pos, true); + } + return SecretStatus.NOT_SURE; + } + } + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (state.equalsIgnoreCase("navigate")) { + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom)); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + return base; + } + if (!"found".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret"); + if (state.equals("found") && getSecretStatus(dungeonRoom) == SecretStatus.FOUND) return new HashSet<>(); + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + if (secretType == SecretType.CHEST || secretType == SecretType.ESSENCE) { + ActionClick actionClick; + preRequisites.add(actionClick = new ActionClick(secretPoint)); + preRequisites = actionClick.getPreRequisite(); + } else if (secretType == SecretType.BAT) { + ActionKill actionKill; + preRequisites.add(actionKill = new ActionKill(secretPoint)); + actionKill.setPredicate(PredicateBat.INSTANCE); + actionKill.setRadius(10); + preRequisites = actionKill.getPreRequisite(); + } + { + ActionMove actionMove = new ActionMove(secretPoint); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + } + { + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + BlockPos pos = getSecretPoint().getBlockPos(dungeonRoom); + RenderUtils.highlightBlock(pos, color,partialTicks); + RenderUtils.drawTextAtWorld(getSecretType().name(), pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.375f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + } + + public enum SecretType { + BAT, CHEST, ITEM_DROP, ESSENCE + } + + @AllArgsConstructor + @Getter + public enum SecretStatus { + DEFINITELY_NOT("definitely_not"), NOT_SURE("not_sure"), CREATED("created"), FOUND("found"), ERROR("error"); + + private final String stateName; + } + + public DungeonSecret clone() throws CloneNotSupportedException { + DungeonSecret dungeonSecret = new DungeonSecret(); + dungeonSecret.secretPoint = (OffsetPoint) secretPoint.clone(); + dungeonSecret.secretType = secretType; + dungeonSecret.preRequisite = new ArrayList<String>(preRequisite); + return dungeonSecret; + } + + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + return getSecretStatus(dungeonRoom).getStateName(); + } + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + SecretStatus status = getSecretStatus(dungeonRoom); + if (status == SecretStatus.FOUND) return Sets.newHashSet("navigate"); + else return Sets.newHashSet("found", "navigate"); + } + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("found"/*, "definitely_not", "not_sure", "created", "error"*/); + } + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + return secretPoint; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonTomb.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonTomb.java new file mode 100755 index 00000000..e4dc79cb --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonTomb.java @@ -0,0 +1,137 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionBreakWithSuperBoom; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMoveNearestAir; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.*; +import java.util.List; + +@Data +public class DungeonTomb implements DungeonMechanic, RouteBlocker { + private static final long serialVersionUID = -7347076019472222115L; + private OffsetPointSet secretPoint = new OffsetPointSet(); + private List<String> preRequisite = new ArrayList<String>(); + + + @Override + public Set<Action> getAction(String state, DungeonRoom dungeonRoom) { + if (state.equalsIgnoreCase("navigate")) { + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom)); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + return base; + } + if (!"open".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for tomb"); + if (!isBlocking(dungeonRoom)) { + return Collections.emptySet(); + } + Set<Action> base; + Set<Action> preRequisites = base = new HashSet<Action>(); + { + ActionBreakWithSuperBoom actionClick; + preRequisites.add(actionClick = new ActionBreakWithSuperBoom(secretPoint.getOffsetPointList().get(0))); + preRequisites = actionClick.getPreRequisite(); + } + { + ActionMoveNearestAir actionMove = new ActionMoveNearestAir(secretPoint.getOffsetPointList().get(0)); + preRequisites.add(actionMove); + preRequisites = actionMove.getPreRequisite(); + } + { + for (String str : preRequisite) { + if (str.isEmpty()) continue; + ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]); + preRequisites.add(actionChangeState); + } + } + return base; + } + + @Override + public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) { + if (secretPoint.getOffsetPointList().isEmpty()) return; + OffsetPoint firstpt = secretPoint.getOffsetPointList().get(0); + BlockPos pos = firstpt.getBlockPos(dungeonRoom); + RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks); + + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + RenderUtils.highlightBlock(offsetPoint.getBlockPos(dungeonRoom), color,partialTicks); + } + } + + @Override + public boolean isBlocking(DungeonRoom dungeonRoom) { + for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) { + if (offsetPoint.getBlock(dungeonRoom) != Blocks.air) return true; + } + return false; + } + + public DungeonTomb clone() throws CloneNotSupportedException { + DungeonTomb dungeonSecret = new DungeonTomb(); + dungeonSecret.secretPoint = (OffsetPointSet) secretPoint.clone(); + dungeonSecret.preRequisite = new ArrayList<String>(preRequisite); + return dungeonSecret; + } + + @Override + public String getCurrentState(DungeonRoom dungeonRoom) { + Block b = Blocks.air; + if (!secretPoint.getOffsetPointList().isEmpty()) + b = secretPoint.getOffsetPointList().get(0).getBlock(dungeonRoom); + return b == Blocks.air ?"open" :"closed"; + } + + @Override + public Set<String> getPossibleStates(DungeonRoom dungeonRoom) { + return isBlocking(dungeonRoom) ? Sets.newHashSet("open", "navigate") : Sets.newHashSet("navigate"); + } + @Override + public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) { + return Sets.newHashSet("open", "closed"); + } + + + @Override + public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) { + return secretPoint.getOffsetPointList().size() == 0 ? null : secretPoint.getOffsetPointList().get(0); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/RouteBlocker.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/RouteBlocker.java new file mode 100755 index 00000000..e12d1269 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/RouteBlocker.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; + +public interface RouteBlocker { + boolean isBlocking(DungeonRoom dungeonRoom); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateArmorStand.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateArmorStand.java new file mode 100755 index 00000000..a4eddefe --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateArmorStand.java @@ -0,0 +1,44 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates; + +import com.google.common.base.Predicate; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityArmorStand; +import org.jetbrains.annotations.Nullable; + + +public class PredicateArmorStand implements Predicate<Entity> { + + public static final PredicateArmorStand INSTANCE = new PredicateArmorStand(); + + @Override + public boolean apply(@Nullable Entity input) { + return input instanceof EntityArmorStand; + } + + @Override + public int hashCode() { + return 0; + } + @Override + public boolean equals(Object o) { + return o == this || o != null && (o.getClass() == this.getClass()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateBat.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateBat.java new file mode 100755 index 00000000..b7fae7a8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateBat.java @@ -0,0 +1,44 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates; + +import com.google.common.base.Predicate; +import net.minecraft.entity.Entity; +import net.minecraft.entity.passive.EntityBat; +import org.jetbrains.annotations.Nullable; + + +public class PredicateBat implements Predicate<Entity> { + + public static final PredicateBat INSTANCE = new PredicateBat(); + + @Override + public boolean apply(@Nullable Entity input) { + return input instanceof EntityBat; + } + + @Override + public int hashCode() { + return 0; + } + @Override + public boolean equals(Object o) { + return o == this || o != null && (o.getClass() == this.getClass()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateSuperBoom.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateSuperBoom.java new file mode 100755 index 00000000..d4cce7f1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateSuperBoom.java @@ -0,0 +1,43 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates; + +import com.google.common.base.Predicate; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +public class PredicateSuperBoom implements Predicate<ItemStack> { + + public static final PredicateSuperBoom INSTANCE = new PredicateSuperBoom(); + + @Override + public boolean apply(@Nullable ItemStack input) { + return false; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public boolean equals(Object o) { + return o == this || o != null && (o.getClass() == this.getClass()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java new file mode 100755 index 00000000..83dbb889 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java @@ -0,0 +1,380 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.roomfinder; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.EDungeonDoorType; +import kr.syeyoung.dungeonsguide.dungeon.events.DungeonStateChangeEvent; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonMechanic; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonRoomDoor; +import kr.syeyoung.dungeonsguide.features.impl.secret.FeaturePathfindStrategy; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.MapProcessor; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonDoor; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.roomprocessor.ProcessorFactory; +import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessor; +import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessorGenerator; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.pathfinding.PathEntity; +import net.minecraft.pathfinding.PathFinder; +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.*; +import net.minecraft.world.ChunkCache; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +import javax.vecmath.Vector2d; +import java.awt.*; +import java.util.*; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +@Getter +public class DungeonRoom { + private final List<Point> unitPoints; + private final short shape; + private final byte color; + + private final BlockPos min; + private final BlockPos max; + private final Point minRoomPt; + + private final DungeonContext context; + + private final List<DungeonDoor> doors = new ArrayList<DungeonDoor>(); + + private DungeonRoomInfo dungeonRoomInfo; + + private final int unitWidth; // X + private final int unitHeight; // Z + + @Setter + private int totalSecrets = -1; + private RoomState currentState = RoomState.DISCOVERED; + + private Map<String, DungeonMechanic> cached = null; + + @Getter + private World cachedWorld; + public Map<String, DungeonMechanic> getMechanics() { + if (cached == null || EditingContext.getEditingContext() != null) { + cached = new HashMap<String, DungeonMechanic>(dungeonRoomInfo.getMechanics()); + int index = 0; + for (DungeonDoor door : doors) { + if (door.getType().isExist()) cached.put((door.getType().getName())+"-"+(++index), new DungeonRoomDoor(this, door)); + } + } + return cached; + } + + public void setCurrentState(RoomState currentState) { + context.createEvent(new DungeonStateChangeEvent(unitPoints.get(0), dungeonRoomInfo.getName(), this.currentState, currentState)); + this.currentState = currentState; + } + + private Map<BlockPos, AStarFineGrid> activeBetterAStar = new HashMap<>(); + private Map<BlockPos, AStarCornerCut> activeBetterAStarCornerCut = new HashMap<>(); + private Map<BlockPos, ThetaStar> activeThetaStar = new HashMap<>(); + + public ScheduledFuture<List<Vec3>> createEntityPathTo(IBlockAccess blockaccess, Entity entityIn, BlockPos targetPos, float dist, int timeout) { + FeaturePathfindStrategy.PathfindStrategy pathfindStrategy = FeatureRegistry.SECRET_PATHFIND_STRATEGY.getPathfindStrat(); + if (pathfindStrategy == FeaturePathfindStrategy.PathfindStrategy.JPS_LEGACY) { + ScheduledFuture<List<Vec3>> sf = asyncPathFinder.schedule(() -> { + BlockPos min = new BlockPos(getMin().getX(), 0, getMin().getZ()); + BlockPos max= new BlockPos(getMax().getX(), 255, getMax().getZ()); + JPSPathfinder pathFinder = new JPSPathfinder(this); + pathFinder.pathfind(entityIn.getPositionVector(), new Vec3(targetPos).addVector(0.5, 0.5, 0.5), 1.5f,timeout); + return pathFinder.getRoute(); + }, 0, TimeUnit.MILLISECONDS); + return sf; + } else if (pathfindStrategy == FeaturePathfindStrategy.PathfindStrategy.A_STAR_FINE_GRID) { + ScheduledFuture<List<Vec3>> sf = asyncPathFinder.schedule(() -> { + AStarFineGrid pathFinder = + activeBetterAStar.computeIfAbsent(targetPos, (pos) -> new AStarFineGrid(this, new Vec3(pos.getX(), pos.getY(), pos.getZ()).addVector(0.5, 0.5, 0.5))); + pathFinder.pathfind(entityIn.getPositionVector(),timeout); + return pathFinder.getRoute(); + }, 0, TimeUnit.MILLISECONDS); + return sf; + }else if (pathfindStrategy == FeaturePathfindStrategy.PathfindStrategy.A_STAR_DIAGONAL) { + ScheduledFuture<List<Vec3>> sf = asyncPathFinder.schedule(() -> { + AStarCornerCut pathFinder = + activeBetterAStarCornerCut.computeIfAbsent(targetPos, (pos) -> new AStarCornerCut(this, new Vec3(pos.getX(), pos.getY(), pos.getZ()).addVector(0.5, 0.5, 0.5))); + pathFinder.pathfind(entityIn.getPositionVector(),timeout); + return pathFinder.getRoute(); + }, 0, TimeUnit.MILLISECONDS); + return sf; + } else if (pathfindStrategy == FeaturePathfindStrategy.PathfindStrategy.THETA_STAR) { + ScheduledFuture<List<Vec3>> sf = asyncPathFinder.schedule(() -> { + ThetaStar pathFinder = + activeThetaStar.computeIfAbsent(targetPos, (pos) -> new ThetaStar(this, new Vec3(pos.getX(), pos.getY(), pos.getZ()).addVector(0.5, 0.5, 0.5))); + pathFinder.pathfind(entityIn.getPositionVector(),timeout); + return pathFinder.getRoute(); + }, 0, TimeUnit.MILLISECONDS); + return sf; + } else { + ScheduledFuture<List<Vec3>> sf = asyncPathFinder.schedule(() -> { + PathFinder pathFinder = new PathFinder(nodeProcessorDungeonRoom); + PathEntity latest = pathFinder.createEntityPathTo(blockaccess, entityIn, targetPos, dist); + if (latest != null) { + List<Vec3> poses = new ArrayList<>(); + for (int i = 0; i < latest.getCurrentPathLength(); i++) { + PathPoint pathPoint = latest.getPathPointFromIndex(i); + poses.add(new Vec3(getMin().add(pathPoint.xCoord, pathPoint.yCoord, pathPoint.zCoord)).addVector(0.5,0.5,0.5)); + } + return poses; + } + return new ArrayList<>(); + }, 0, TimeUnit.MILLISECONDS); + return sf; + } + } + + private static final ScheduledExecutorService asyncPathFinder = Executors.newScheduledThreadPool(4); + @Getter + private final NodeProcessorDungeonRoom nodeProcessorDungeonRoom; + + @Getter + private final Map<String, Object> roomContext = new HashMap<String, Object>(); + + @AllArgsConstructor + @Getter + public enum RoomState { + DISCOVERED(0), COMPLETE_WITHOUT_SECRETS(0), FINISHED(0), FAILED(-14); + private final int scoreModifier; + } + + private RoomProcessor roomProcessor; + + public DungeonRoom(List<Point> points, short shape, byte color, BlockPos min, BlockPos max, DungeonContext context, Set<Tuple<Vector2d, EDungeonDoorType>> doorsAndStates) { + this.unitPoints = points; + this.shape = shape; + this.color = color; + this.min = min; + this.max = max; + this.context = context; + + minRoomPt = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); + for (Point pt : unitPoints) { + if (pt.x < minRoomPt.x) minRoomPt.x = pt.x; + if (pt.y < minRoomPt.y) minRoomPt.y = pt.y; + } + unitWidth = (int) Math.ceil(max.getX() - min.getX() / 32.0); + unitHeight = (int) Math.ceil(max.getZ() - min.getZ() / 32.0); + + + ChunkCache chunkCache = new ChunkCache(getContext().getWorld(), min.add(-3, 0, -3), max.add(3,0,3), 0); + this.cachedWorld = new CachedWorld(chunkCache); + + + + minx = min.getX() * 2; miny = 0; minz = min.getZ() * 2; + maxx = max.getX() * 2 + 2; maxy = 255 * 2 + 2; maxz = max.getZ() * 2 + 2; + + lenx = maxx - minx; + leny = maxy - miny; + lenz = maxz - minz; + arr = new long[lenx *leny * lenz * 2 / 8];; + + buildDoors(doorsAndStates); + buildRoom(); + nodeProcessorDungeonRoom = new NodeProcessorDungeonRoom(this); + updateRoomProcessor(); + + + } + + private static final Set<Vector2d> directions = Sets.newHashSet(new Vector2d(0,16), new Vector2d(0, -16), new Vector2d(16, 0), new Vector2d(-16 , 0)); + + private void buildDoors(Set<Tuple<Vector2d, EDungeonDoorType>> doorsAndStates) { + Set<Tuple<BlockPos, EDungeonDoorType>> positions = new HashSet<>(); + BlockPos pos = context.getMapProcessor().roomPointToWorldPoint(minRoomPt).add(16,0,16); + for (Tuple<Vector2d, EDungeonDoorType> doorsAndState : doorsAndStates) { + Vector2d vector2d = doorsAndState.getFirst(); + BlockPos neu = pos.add(vector2d.x * 32, 0, vector2d.y * 32); + positions.add(new Tuple<>(neu, doorsAndState.getSecond())); + } + + for (Tuple<BlockPos, EDungeonDoorType> door : positions) { + doors.add(new DungeonDoor(context.getWorld(), door.getFirst(), door.getSecond())); + } + } + + private RoomMatcher roomMatcher = null; + private void buildRoom() { + if (roomMatcher == null) + roomMatcher = new RoomMatcher(this); + DungeonRoomInfo dungeonRoomInfo = roomMatcher.match(); + if (dungeonRoomInfo == null) { + dungeonRoomInfo = roomMatcher.createNew(); + if (color == 18) dungeonRoomInfo.setProcessorId("bossroom"); + } + this.dungeonRoomInfo = dungeonRoomInfo; + totalSecrets = dungeonRoomInfo.getTotalSecrets(); + } + + public void updateRoomProcessor() { + RoomProcessorGenerator roomProcessorGenerator = ProcessorFactory.getRoomProcessorGenerator(dungeonRoomInfo.getProcessorId()); + if (roomProcessorGenerator == null) this.roomProcessor = null; + else this.roomProcessor = roomProcessorGenerator.createNew(this); + } + + public Block getAbsoluteBlockAt(int x, int y, int z) { + // validate x y z's + BlockPos pos = new BlockPos(x,y,z); + if (canAccessAbsolute(pos)) { + return cachedWorld.getBlockState(pos).getBlock(); + } + return null; + } + + public Block getRelativeBlockAt(int x, int y, int z) { + // validate x y z's + if (canAccessRelative(x,z)) { + BlockPos pos = new BlockPos(x,y,z).add(min.getX(),min.getY(),min.getZ()); + return cachedWorld.getBlockState(pos).getBlock(); + } + return null; + } + + public BlockPos getRelativeBlockPosAt(int x, int y, int z) { + BlockPos pos = new BlockPos(x,y,z).add(min.getX(),min.getY(),min.getZ()); + return pos; + } + + public int getRelativeBlockDataAt(int x, int y, int z) { + // validate x y z's + if (canAccessRelative(x,z)) { + BlockPos pos = new BlockPos(x,y,z).add(min.getX(),min.getY(),min.getZ()); + IBlockState iBlockState = cachedWorld.getBlockState(pos); + return iBlockState.getBlock().getMetaFromState(iBlockState); + } + return -1; + } + + public int getAbsoluteBlockDataAt(int x, int y, int z) { + // validate x y z's + BlockPos pos = new BlockPos(x,y,z); + if (canAccessAbsolute(pos)) { + IBlockState iBlockState = cachedWorld.getBlockState(pos); + return iBlockState.getBlock().getMetaFromState(iBlockState); + } + return -1; + } + + public boolean canAccessAbsolute(BlockPos pos) { + MapProcessor mapProcessor = this.context.getMapProcessor(); + Point roomPt = mapProcessor.worldPointToRoomPoint(pos); + roomPt.translate(-minRoomPt.x, -minRoomPt.y); + + return (shape >>(roomPt.y *4 +roomPt.x) & 0x1) > 0; + } + public boolean canAccessRelative(int x, int z) { + return x>= 0 && z >= 0 && (shape >>((z/32) *4 +(x/32)) & 0x1) > 0; + } + + + + long arr[]; + // These values are doubled + private final int minx, miny, minz, maxx, maxy, maxz; + private final int lenx, leny, lenz; + private static final float playerWidth = 0.3f; + public boolean isBlocked(int x,int y, int z) { + if (x < minx || z < minz || x >= maxx || z >= maxz || y < miny || y >= maxy) return true; + int dx = x - minx, dy = y - miny, dz = z - minz; + int bitIdx = dx * leny * lenz + dy * lenz + dz; + int location = bitIdx / 4; + int bitStart = (2 * (bitIdx % 4)); + long theBit = arr[location]; + if (((theBit >> bitStart) & 0x2) > 0) return ((theBit >> bitStart) & 1) > 0; + float wX = x / 2.0f, wY = y / 2.0f, wZ = z / 2.0f; + + + AxisAlignedBB bb = AxisAlignedBB.fromBounds(wX - playerWidth, wY, wZ - playerWidth, wX + playerWidth, wY + 1.9f, wZ + playerWidth); + + int i = MathHelper.floor_double(bb.minX); + int j = MathHelper.floor_double(bb.maxX + 1.0D); + int k = MathHelper.floor_double(bb.minY); + int l = MathHelper.floor_double(bb.maxY + 1.0D); + int i1 = MathHelper.floor_double(bb.minZ); + int j1 = MathHelper.floor_double(bb.maxZ + 1.0D); + BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos(); + + List<AxisAlignedBB> list = new ArrayList<>(); + for (int k1 = i; k1 < j; ++k1) { + for (int l1 = i1; l1 < j1; ++l1) { + for (int i2 = k - 1; i2 < l; ++i2) { + blockPos.set(k1, i2, l1); + IBlockState iblockstate1 = cachedWorld.getBlockState(blockPos); + Block b = iblockstate1.getBlock(); + if (!b.getMaterial().blocksMovement())continue; + if (b.isFullCube() && i2 == k-1) continue; + if (iblockstate1.equals( NodeProcessorDungeonRoom.preBuilt)) continue; + if (b.isFullCube()) { + theBit |= (3L << bitStart); + arr[location] = theBit; + return true; + } + try { + b.addCollisionBoxesToList(cachedWorld, blockPos, iblockstate1, bb, list, null); + } catch (Exception e) { + return true; + } + if (list.size() > 0) { + theBit |= (3L << bitStart); + arr[location] = theBit; + return true; + } + } + } + } + theBit |= 2L << bitStart; + arr[location] = theBit; + return false; + } + + + public void resetBlock(BlockPos pos) { + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + for (int z = -1; z <= 1; z++) { + resetBlock(pos.getX()*2 + x, pos.getY()*2 + y, pos.getZ()*2 + z); + } + } + } + } + private void resetBlock(int x, int y, int z) { + if (x < minx || z < minz || x >= maxx || z >= maxz || y < miny || y >= maxy) return; + int dx = x - minx, dy = y - miny, dz = z - minz; + int bitIdx = dx * leny * lenz + dy * lenz + dz; + int location = bitIdx / 4; + arr[location] = 0; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoomInfoRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoomInfoRegistry.java new file mode 100755 index 00000000..a97efa43 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoomInfoRegistry.java @@ -0,0 +1,142 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.roomfinder; + +import com.google.common.io.Files; +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import kr.syeyoung.dungeonsguide.launcher.Main; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import org.apache.commons.io.IOUtils; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.io.*; +import java.nio.charset.Charset; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.*; + +public class DungeonRoomInfoRegistry { + @Getter + private static final List<DungeonRoomInfo> registered = new ArrayList<DungeonRoomInfo>(); + private static final Map<Short, List<DungeonRoomInfo>> shapeMap = new HashMap<Short, List<DungeonRoomInfo>>(); + private static final Map<UUID, DungeonRoomInfo> uuidMap = new HashMap<UUID, DungeonRoomInfo>(); + + public static void register(DungeonRoomInfo dungeonRoomInfo) { + if (dungeonRoomInfo == null) throw new NullPointerException("what the fak parameter is noll?"); + if (uuidMap.containsKey(dungeonRoomInfo.getUuid())) { + DungeonRoomInfo dri1 = uuidMap.get(dungeonRoomInfo.getUuid()); + registered.remove(dri1); + shapeMap.get(dri1.getShape()).remove(dri1); + uuidMap.remove(dri1.getUuid()); + } + dungeonRoomInfo.setRegistered(true); + registered.add(dungeonRoomInfo); + uuidMap.put(dungeonRoomInfo.getUuid(), dungeonRoomInfo); + List<DungeonRoomInfo> roomInfos = shapeMap.get(dungeonRoomInfo.getShape()); + if (roomInfos == null) roomInfos = new ArrayList<DungeonRoomInfo>(); + roomInfos.add(dungeonRoomInfo); + shapeMap.put(dungeonRoomInfo.getShape(), roomInfos); + } + + + public static List<DungeonRoomInfo> getByShape(Short shape) { + List<DungeonRoomInfo> dungeonRoomInfos = shapeMap.get(shape); + return dungeonRoomInfos == null ? Collections.emptyList() : dungeonRoomInfos; + } + + public static DungeonRoomInfo getByUUID(UUID uid) { + return uuidMap.get(uid); + } + + public static void unregister(DungeonRoomInfo dungeonRoomInfo) { + if (!dungeonRoomInfo.isRegistered()) throw new IllegalStateException("what tha fak? that is not registered one"); + if (!uuidMap.containsKey(dungeonRoomInfo.getUuid())) throw new IllegalStateException("what tha fak? that is not registered one, but you desperately wanted to trick this program"); + dungeonRoomInfo.setRegistered(false); + registered.remove(dungeonRoomInfo); + shapeMap.get(dungeonRoomInfo.getShape()).remove(dungeonRoomInfo); + uuidMap.remove(dungeonRoomInfo.getUuid()); + } + + public static void saveAll(File dir) { + dir.mkdirs(); + boolean isDev = Minecraft.getMinecraft().getSession().getPlayerID().replace("-","").equals("e686fe0aab804a71ac7011dc8c2b534c"); + String nameidstring = "name,uuid,processsor,secrets"; + String ids = ""; + for (DungeonRoomInfo dungeonRoomInfo : registered) { + try { + if (!dungeonRoomInfo.isUserMade() && !isDev) continue; + FileOutputStream fos = new FileOutputStream(new File(dir, dungeonRoomInfo.getUuid().toString() + ".roomdata")); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(dungeonRoomInfo); + oos.flush(); + oos.close(); + + nameidstring += "\n"+dungeonRoomInfo.getName()+","+dungeonRoomInfo.getUuid() +","+dungeonRoomInfo.getProcessorId()+","+dungeonRoomInfo.getTotalSecrets(); + ids += "roomdata/"+dungeonRoomInfo.getUuid() +".roomdata\n"; + } catch (Exception e) {e.printStackTrace();} + } + + try { + Files.write(nameidstring, new File(dir, "roomidmapping.csv"), Charset.defaultCharset()); + Files.write(ids, new File(dir, "datas.txt"), Charset.defaultCharset()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void loadAll(File dir) throws BadPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, IllegalBlockSizeException, NoSuchPaddingException, InvalidKeyException { + registered.clear(); + shapeMap.clear(); + uuidMap.clear(); + try { + List<String> lines = IOUtils.readLines(Main.class.getResourceAsStream("/roomdata/datas.txt")); + for (String name : lines) { + if (!name.endsWith(".roomdata")) continue; + try { + InputStream fis = Main.class.getResourceAsStream("/"+name); + ObjectInputStream ois = new ObjectInputStream(fis); + DungeonRoomInfo dri = (DungeonRoomInfo) ois.readObject(); + ois.close(); + fis.close(); + register(dri); + } catch (Exception e) { + System.out.println(name); + e.printStackTrace(); + } + } + } catch (Exception e) {e.printStackTrace();} + for (File f : dir.listFiles()) { + if (!f.getName().endsWith(".roomdata")) continue; + try { + InputStream fis = new FileInputStream(f); + ObjectInputStream ois = new ObjectInputStream(fis); + DungeonRoomInfo dri = (DungeonRoomInfo) ois.readObject(); + ois.close(); + fis.close(); + register(dri); + } catch (Exception e) { + System.out.println(f.getName());e.printStackTrace();} + } + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java new file mode 100755 index 00000000..f0da1f35 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java @@ -0,0 +1,154 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.dungeon.roomfinder; + +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import kr.syeyoung.dungeonsguide.utils.ArrayUtils; +import kr.syeyoung.dungeonsguide.utils.ShortUtils; +import lombok.Getter; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.world.World; + +import java.util.List; + +public class RoomMatcher { + private final DungeonRoom dungeonRoom; + + @Getter + private DungeonRoomInfo match; + @Getter + private int rotation; // how much the "found room" has to rotate clockwise to match the given dungeon room info. ! + private boolean triedMatch = false; + + private final World w; + + public RoomMatcher(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + w = dungeonRoom.getContext().getWorld(); + } + + public DungeonRoomInfo match() { + if (triedMatch) return match; + + int zz = dungeonRoom.getMax().getZ() - dungeonRoom.getMin().getZ() + 1; + int xx = dungeonRoom.getMax().getX() - dungeonRoom.getMin().getX() + 1; + for (int z = 0; z < zz; z ++) { + for (int x = 0; x < xx; x++) { + if (x % 8 == 0 && z % 8 == 0 && dungeonRoom.getContext().getWorld().getChunkFromBlockCoords(dungeonRoom.getRelativeBlockPosAt(x, 0, z)).isEmpty()) { + throw new IllegalStateException("chunk is not loaded"); + + } + } + } + + triedMatch = true; + int lowestcost = 10; + int lowestRot = 0; + DungeonRoomInfo bestMatch = null; + for (int rotation = 0; rotation < 4; rotation++) { + short shape = dungeonRoom.getShape(); + for (int j = 0; j<rotation; j++) + shape = ShortUtils.rotateClockwise(shape); + shape = ShortUtils.topLeftifyInt(shape); + + List<DungeonRoomInfo> roomInfoList = DungeonRoomInfoRegistry.getByShape(shape); + for (DungeonRoomInfo roomInfo : roomInfoList) { + int cost = tryMatching(roomInfo, rotation); + if (cost == 0) { + match = roomInfo; + this.rotation = rotation; + return match; + } + if (cost < lowestcost) { + lowestcost = cost; + bestMatch = roomInfo; + lowestRot = rotation; + } + } + } + match = bestMatch; + this.rotation = lowestRot; + return bestMatch; + } + + private int tryMatching(DungeonRoomInfo dungeonRoomInfo, int rotation) { + if (dungeonRoomInfo.getColor() != dungeonRoom.getColor()) return Integer.MAX_VALUE; + + int[][] res = dungeonRoomInfo.getBlocks(); + for (int i = 0; i < rotation; i++) + res = ArrayUtils.rotateCounterClockwise(res); + + int wrongs = 0; + for (int z = 0; z < res.length; z ++) { + for (int x = 0; x < res[0].length; x++) { + int data = res[z][x]; + if (data == -1) continue; + Block b = dungeonRoom.getRelativeBlockAt(x,0,z); + + if (b == null || Block.getIdFromBlock(b) != data) { + wrongs++; + + if (wrongs > 10) return wrongs; + } + } + } + return wrongs; + } + + private static final int offset = 3; + public DungeonRoomInfo createNew() { + DungeonRoomInfo roomInfo = new DungeonRoomInfo(dungeonRoom.getShape(), dungeonRoom.getColor()); + + int maxX = dungeonRoom.getMax().getX(); + int maxZ = dungeonRoom.getMax().getZ(); + int minX = dungeonRoom.getMin().getX(); + int minZ = dungeonRoom.getMin().getZ(); + int widthX = maxX - minX + 2; + int heightZ = maxZ - minZ + 2; + int[][] data = new int[dungeonRoom.getMax().getZ() - dungeonRoom.getMin().getZ() +2][dungeonRoom.getMax().getX() - dungeonRoom.getMin().getX() + 2]; + + for (int z = 0; z < data.length; z++) { + for (int x = 0; x < data[0].length; x++) { +// if (!(offset < x && widthX - offset > x && offset < z && heightZ - offset > z)) { +// data[z][x] = -1; +// continue; +// } + if (!(dungeonRoom.canAccessRelative(x + offset, z + offset) + && dungeonRoom.canAccessRelative(x - offset -1 , z - offset-1) + && dungeonRoom.canAccessRelative(x + offset , z - offset-1) + && dungeonRoom.canAccessRelative(x - offset -1 , z + offset))) { + data[z][x] = -1; + continue; + } + + Block b = dungeonRoom.getRelativeBlockAt(x,0,z); + if (b == null || b == Blocks.chest || b == Blocks.trapped_chest) { + data[z][x] = -1; + } else { + data[z][x] = Block.getIdFromBlock(b); + } + } + } + + roomInfo.setBlocks(data); + roomInfo.setUserMade(true); + return roomInfo; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/DungeonListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/DungeonListener.java new file mode 100755 index 00000000..21ea0bb4 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/DungeonListener.java @@ -0,0 +1,578 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.eventlistener; + +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.config.Config; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.DungeonActionManager; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonDoor; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonAddSet; +import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonParameterEdit; +import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonRoomEdit; +import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessor; +import kr.syeyoung.dungeonsguide.utils.MapUtils; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.passive.EntityBat; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.Vec3; +import net.minecraftforge.client.event.ClientChatReceivedEvent; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.client.CustomModLoadingErrorDisplayException; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.relauncher.Side; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class DungeonListener { + @SubscribeEvent + public void onWorldLoad(WorldEvent.Unload event) { + try { + Config.saveConfig(); + } catch (IOException e) { + e.printStackTrace(); + } + DungeonActionManager.getSpawnLocation().clear(); + DungeonActionManager.getKilleds().clear(); + } + + @SubscribeEvent + public void onPostDraw(GuiScreenEvent.DrawScreenEvent.Post e) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + if (!skyblockStatus.isOnDungeon()) return; + + if (skyblockStatus.getContext() != null) { + DungeonContext context = skyblockStatus.getContext(); + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + if (thePlayer == null) return; + if (context.getBossfightProcessor() != null) context.getBossfightProcessor().onPostGuiRender(e); + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom != null && dungeonRoom.getRoomProcessor() != null) { + dungeonRoom.getRoomProcessor().onPostGuiRender(e); + } + } + GlStateManager.enableBlend(); + GlStateManager.color(1,1,1,1); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableAlpha(); + } catch (Throwable e2) {e2.printStackTrace(); Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cDG HAS RAN INTO ERROR WHILE RENDERING SCREEN! Please report to support channel"));} + } + @SubscribeEvent + public void onEntityUpdate(LivingEvent.LivingUpdateEvent e) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + if (!skyblockStatus.isOnDungeon()) return; + + if (skyblockStatus.getContext() != null) { + DungeonContext context = skyblockStatus.getContext(); + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + if (thePlayer == null) return; + if (context.getBossfightProcessor() != null) context.getBossfightProcessor().onEntityUpdate(e); + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom != null && dungeonRoom.getRoomProcessor() != null) { + dungeonRoom.getRoomProcessor().onEntityUpdate(e); + } + } + } catch (Throwable e2) {e2.printStackTrace();} + } + + boolean wasOnHypixel = false; + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent ev) throws Throwable { + try { + if (ev.side == Side.SERVER) return; + if (ev.phase == TickEvent.Phase.START) { + + + + + + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + { + boolean isOnDungeon = skyblockStatus.isOnDungeon(); + boolean isOnSkyblock = skyblockStatus.isOnSkyblock(); + skyblockStatus.updateStatus(); + + if (!wasOnHypixel && skyblockStatus.isOnHypixel()) { + MinecraftForge.EVENT_BUS.post(new HypixelJoinedEvent()); + } + wasOnHypixel = skyblockStatus.isOnHypixel(); + + if (isOnSkyblock && !skyblockStatus.isOnSkyblock()) { + MinecraftForge.EVENT_BUS.post(new SkyblockLeftEvent()); + } else if (!isOnSkyblock && skyblockStatus.isOnSkyblock()) { + MinecraftForge.EVENT_BUS.post(new SkyblockJoinedEvent()); + } + + if ((isOnDungeon && !skyblockStatus.isOnDungeon())) { + MinecraftForge.EVENT_BUS.post(new DungeonLeftEvent()); + skyblockStatus.setContext(null); + if (!FeatureRegistry.ADVANCED_DEBUGGABLE_MAP.isEnabled()) + MapUtils.clearMap(); + return; + } + if (isOnSkyblock) { + if (skyblockStatus.getContext() != null) { + skyblockStatus.getContext().tick(); + } else if (skyblockStatus.isOnDungeon()){ + skyblockStatus.setContext(new DungeonContext(Minecraft.getMinecraft().thePlayer.worldObj)); + MinecraftForge.EVENT_BUS.post(new DungeonStartedEvent()); + } + } + } + + if (!skyblockStatus.isOnDungeon()) return; + + if (skyblockStatus.getContext() != null) { + DungeonContext context = skyblockStatus.getContext(); + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + if (thePlayer == null) return; + if (context.getBossfightProcessor() != null) context.getBossfightProcessor().tick(); + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom != null && dungeonRoom.getRoomProcessor() != null) { + dungeonRoom.getRoomProcessor().tick(); + } + } + } + } catch (Throwable e2) { + if (e2 instanceof CustomModLoadingErrorDisplayException) throw e2; + e2.printStackTrace(); + } + } + + + @SubscribeEvent + public void onHypixelJoin(HypixelJoinedEvent skyblockJoinedEvent) { + if (DungeonsGuide.getDungeonsGuide().isFirstTimeUsingDG()) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fThank you for installing DungeonsGuide, the most intelligent skyblock dungeon mod!")); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fThe gui for relocating GUI Elements and enabling or disabling features can be opened by typing §e/dg")); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fType §e/dg help §fto view full list of commands offered by dungeons guide!")); + } + } + + @SubscribeEvent + public void onRender(RenderGameOverlayEvent.Post postRender) { + try { + if (!(postRender.type == RenderGameOverlayEvent.ElementType.EXPERIENCE || postRender.type == RenderGameOverlayEvent.ElementType.JUMPBAR)) return; + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnDungeon()) return; + + if (skyblockStatus.getContext() != null) { + DungeonContext context = skyblockStatus.getContext(); + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + if (context.getBossfightProcessor() != null) context.getBossfightProcessor().drawScreen(postRender.partialTicks); + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom != null) { + if (dungeonRoom.getRoomProcessor() != null) { + dungeonRoom.getRoomProcessor().drawScreen(postRender.partialTicks); + } + } + + } + GlStateManager.enableBlend(); + GlStateManager.color(1,1,1,1); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + Minecraft.getMinecraft().entityRenderer.setupOverlayRendering(); + GlStateManager.enableAlpha(); + } catch (Throwable e) { + e.printStackTrace();Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cDG HAS RAN INTO ERROR WHILE RENDERING SCREEN! Please report to support channel")); + } + } + + @SubscribeEvent(receiveCanceled = true, priority = EventPriority.HIGHEST) + public void onChatReceived(ClientChatReceivedEvent clientChatReceivedEvent) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnDungeon()) return; + + if (clientChatReceivedEvent.type != 2 && clientChatReceivedEvent.message.getFormattedText().contains("§6> §e§lEXTRA STATS §6<")) { + MinecraftForge.EVENT_BUS.post(new DungeonEndedEvent()); + } + + DungeonContext context = skyblockStatus.getContext(); + + if (skyblockStatus.getContext() != null) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + try { + context.onChat(clientChatReceivedEvent); + } catch (Throwable t) { + t.printStackTrace(); + } + + if (context.getBossfightProcessor() != null) { + if (clientChatReceivedEvent.type == 2) + context.getBossfightProcessor().actionbarReceived(clientChatReceivedEvent.message); + else + context.getBossfightProcessor().chatReceived(clientChatReceivedEvent.message); + } + RoomProcessor roomProcessor = null; + try { + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom != null) { + if (dungeonRoom.getRoomProcessor() != null) { + if (clientChatReceivedEvent.type == 2) { + dungeonRoom.getRoomProcessor().actionbarReceived(clientChatReceivedEvent.message); + roomProcessor = dungeonRoom.getRoomProcessor(); + } else { + dungeonRoom.getRoomProcessor().chatReceived(clientChatReceivedEvent.message); + roomProcessor = dungeonRoom.getRoomProcessor(); + } + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + if (clientChatReceivedEvent.type == 2) return; + for (RoomProcessor globalRoomProcessor : context.getGlobalRoomProcessors()) { + if (globalRoomProcessor == roomProcessor) continue; + try { + globalRoomProcessor.chatReceived(clientChatReceivedEvent.message); + } catch (Throwable t) { + t.printStackTrace(); + } + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + + @SubscribeEvent + public void onWorldRender(RenderWorldLastEvent renderWorldLastEvent) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnDungeon()) return; + + DungeonContext context = skyblockStatus.getContext(); + if (context == null) return; + if (FeatureRegistry.DEBUG.isEnabled()) { + for (DungeonRoom dungeonRoom : context.getDungeonRoomList()) { + for(DungeonDoor door : dungeonRoom.getDoors()) { + RenderUtils.renderDoor(door, renderWorldLastEvent.partialTicks); + } + } + } + + + if (skyblockStatus.getContext() != null) { + + if (context.getBossfightProcessor() != null) { + context.getBossfightProcessor().drawWorld(renderWorldLastEvent.partialTicks); + } + + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj; + if (dungeonRoom != null) { + if (dungeonRoom.getRoomProcessor() != null) { + dungeonRoom.getRoomProcessor().drawWorld(renderWorldLastEvent.partialTicks); + } + } + + if (FeatureRegistry.DEBUG.isEnabled() && dungeonRoom !=null) { + + Vec3 player = Minecraft.getMinecraft().thePlayer.getPositionVector(); + BlockPos real = new BlockPos(player.xCoord * 2, player.yCoord * 2, player.zCoord * 2); + for (BlockPos allInBox : BlockPos.getAllInBox(real.add(-1, -1, -1), real.add(1, 1, 1))) { + boolean blocked = dungeonRoom.isBlocked(allInBox.getX(), allInBox.getY(), allInBox.getZ()); + + RenderUtils.highlightBox( + AxisAlignedBB.fromBounds( + allInBox.getX() / 2.0 - 0.1, allInBox.getY() / 2.0 - 0.1, allInBox.getZ() / 2.0 - 0.1, + allInBox.getX() / 2.0 + 0.1, allInBox.getY() / 2.0 + 0.1, allInBox.getZ() / 2.0 + 0.1 + ), blocked ? new Color(0x55FF0000, true) : new Color(0x3300FF00, true), renderWorldLastEvent.partialTicks, false); + + } + } + + } + + if (EditingContext.getEditingContext() != null) { + GuiScreen guiScreen = EditingContext.getEditingContext().getCurrent(); + if (guiScreen instanceof GuiDungeonParameterEdit) { + ValueEdit valueEdit = ((GuiDungeonParameterEdit) guiScreen).getValueEdit(); + if (valueEdit != null) { + valueEdit.renderWorld(renderWorldLastEvent.partialTicks); + } + } else if (guiScreen instanceof GuiDungeonValueEdit) { + ValueEdit valueEdit = ((GuiDungeonValueEdit) guiScreen).getValueEdit(); + if (valueEdit != null) { + valueEdit.renderWorld(renderWorldLastEvent.partialTicks); + } + } else if (guiScreen instanceof GuiDungeonAddSet) { + ((GuiDungeonAddSet) guiScreen).onWorldRender(renderWorldLastEvent.partialTicks); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + @SubscribeEvent() + public void onKey2(KeyBindPressedEvent keyInputEvent) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnDungeon()) return; + + DungeonContext context = skyblockStatus.getContext(); + + if (skyblockStatus.getContext() != null) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + if (context.getBossfightProcessor() != null) { + context.getBossfightProcessor().onKeybindPress(keyInputEvent); + } + RoomProcessor roomProcessor = null; + try { + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom != null) { + if (dungeonRoom.getRoomProcessor() != null) { + dungeonRoom.getRoomProcessor().onKeybindPress(keyInputEvent); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + @SubscribeEvent() + public void onInteract(PlayerInteractEntityEvent interact) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnDungeon()) return; + + DungeonContext context = skyblockStatus.getContext(); + + if (skyblockStatus.getContext() != null) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + if (context.getBossfightProcessor() != null) { + context.getBossfightProcessor().onInteract(interact); + } + RoomProcessor roomProcessor = null; + try { + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom != null) { + if (dungeonRoom.getRoomProcessor() != null) { + dungeonRoom.getRoomProcessor().onInteract(interact); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @SubscribeEvent() + public void onBlockChange(BlockUpdateEvent.Post postInteract) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnDungeon()) return; + + DungeonContext context = skyblockStatus.getContext(); + + if (skyblockStatus.getContext() != null) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + if (context.getBossfightProcessor() != null) { + context.getBossfightProcessor().onBlockUpdate(postInteract); + } + RoomProcessor roomProcessor = null; + try { + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom != null) { + if (dungeonRoom.getRoomProcessor() != null) { + dungeonRoom.getRoomProcessor().onBlockUpdate(postInteract); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @SubscribeEvent + public void onKeyInput(KeyBindPressedEvent keyInputEvent) { + if (FeatureRegistry.DEBUG.isEnabled() && FeatureRegistry.ADVANCED_ROOMEDIT.isEnabled() && keyInputEvent.getKey() == FeatureRegistry.ADVANCED_ROOMEDIT.<Integer>getParameter("key").getValue() ){ + EditingContext ec = EditingContext.getEditingContext(); + if (ec == null) { + DungeonContext context = DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext(); + if (context == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Not in dungeons")); + return; + } + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + + if (dungeonRoom == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Can't determine the dungeon room you're in")); + return; + } + + if (EditingContext.getEditingContext() != null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("There is an editing session currently open.")); + return; + } + + EditingContext.createEditingContext(dungeonRoom); + EditingContext.getEditingContext().openGui(new GuiDungeonRoomEdit(dungeonRoom)); + } else ec.reopen(); + } + } + @SubscribeEvent + public void onInteract(PlayerInteractEvent keyInputEvent) { + try { + if (!keyInputEvent.world.isRemote) return; + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnDungeon()) return; + + DungeonContext context = skyblockStatus.getContext(); + + if (skyblockStatus.getContext() != null) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + if (context.getBossfightProcessor() != null) { + context.getBossfightProcessor().onInteractBlock(keyInputEvent); + } + RoomProcessor roomProcessor = null; + try { + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom != null) { + if (dungeonRoom.getRoomProcessor() != null) { + dungeonRoom.getRoomProcessor().onInteractBlock(keyInputEvent); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Getter + private final Map<Integer, Vec3> entityIdToPosMap = new HashMap<Integer, Vec3>(); + @SubscribeEvent + public void onEntitySpawn(EntityJoinWorldEvent spawn) { + DungeonActionManager.getSpawnLocation().put(spawn.entity.getEntityId(), new Vec3(spawn.entity.posX, spawn.entity.posY, spawn.entity.posZ)); + } + + + @SubscribeEvent + public void onEntityDeSpawn(LivingDeathEvent deathEvent) { + if (deathEvent.entityLiving instanceof EntityBat) + DungeonActionManager.getKilleds().add(deathEvent.entity.getEntityId()); + + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnDungeon()) return; + + DungeonContext context = skyblockStatus.getContext(); + + if (skyblockStatus.getContext() != null) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + + if (context.getBossfightProcessor() != null) { + context.getBossfightProcessor().onEntityDeath(deathEvent); + } + RoomProcessor roomProcessor = null; + try { + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom != null) { + if (dungeonRoom.getRoomProcessor() != null) { + dungeonRoom.getRoomProcessor().onEntityDeath(deathEvent); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + + if (!(deathEvent.entityLiving instanceof EntityBat)) + DungeonActionManager.getSpawnLocation().remove(deathEvent.entity.getEntityId()); + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/FeatureListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/FeatureListener.java new file mode 100644 index 00000000..cc9fe5b6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/FeatureListener.java @@ -0,0 +1,511 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.eventlistener; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.guiconfig.location.GuiGuiLocationConfig; +import kr.syeyoung.dungeonsguide.features.listener.*; +import kr.syeyoung.dungeonsguide.features.AbstractFeature; +import kr.syeyoung.dungeonsguide.features.listener.*; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraftforge.client.event.*; +import net.minecraftforge.client.event.sound.PlaySoundEvent; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +public class FeatureListener { + @SubscribeEvent + public void onRender(RenderGameOverlayEvent.Post postRender) { + try { + boolean isLocConfig = Minecraft.getMinecraft().currentScreen instanceof GuiGuiLocationConfig; + + if (!(postRender.type == RenderGameOverlayEvent.ElementType.EXPERIENCE || postRender.type == RenderGameOverlayEvent.ElementType.JUMPBAR)) return; + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof ScreenRenderListener && (!isLocConfig || !(abstractFeature instanceof GuiFeature))) { + ((ScreenRenderListener) abstractFeature).drawScreen(postRender.partialTicks); + } + } + GlStateManager.enableBlend(); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @SubscribeEvent + public void onKeybindPress(KeyBindPressedEvent keyBindPressedEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof KeybindPressedListener) { + ((KeybindPressedListener) abstractFeature).onKeybindPress(keyBindPressedEvent); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @SubscribeEvent + public void onStomp(StompConnectedEvent stompConnectedEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof StompConnectedListener) { + ((StompConnectedListener) abstractFeature).onStompConnected(stompConnectedEvent); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onStomp(TextureStitchEvent.Pre textureStitchEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof TextureStichListener) { + ((TextureStichListener) abstractFeature).onTextureStitch(textureStitchEvent); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onStomp(TextureStitchEvent.Post textureStitchEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof TextureStichListener) { + ((TextureStichListener) abstractFeature).onTextureStitch(textureStitchEvent); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onDiscordUserUpdate(DiscordUserUpdateEvent discordUserUpdateEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof DiscordUserUpdateListener) { + ((DiscordUserUpdateListener) abstractFeature).onDiscordUserUpdate(discordUserUpdateEvent); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onDiscordUserUpdate(DiscordUserJoinRequestEvent discordUserUpdateEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof DiscordUserJoinRequestListener) { + ((DiscordUserJoinRequestListener) abstractFeature).onDiscordUserJoinRequest(discordUserUpdateEvent); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onWindowUpdate(WindowUpdateEvent windowUpdateEvent) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof GuiUpdateListener) { + ((GuiUpdateListener) abstractFeature).onGuiUpdate(windowUpdateEvent); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onRender(RenderLivingEvent.Pre preRender) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof EntityLivingRenderListener) { + ((EntityLivingRenderListener) abstractFeature).onEntityRenderPre(preRender); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @SubscribeEvent + public void onSound(PlaySoundEvent soundEvent) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof SoundListener) { + ((SoundListener) abstractFeature).onSound(soundEvent); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @SubscribeEvent + public void onRender(RenderLivingEvent.Post preRender) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof EntityLivingRenderListener) { + ((EntityLivingRenderListener) abstractFeature).onEntityRenderPost(preRender); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onRender(TitleEvent titleEvent) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof TitleListener) { + ((TitleListener) abstractFeature).onTitle(titleEvent.getPacketTitle()); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onRender(RenderPlayerEvent.Pre preRender) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof PlayerRenderListener) { + ((PlayerRenderListener) abstractFeature).onEntityRenderPre(preRender); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onRender(RenderPlayerEvent.Post preRender) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof PlayerRenderListener) { + ((PlayerRenderListener) abstractFeature).onEntityRenderPost(preRender); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + + @SubscribeEvent + public void onRenderWorld(RenderWorldLastEvent postRender) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof WorldRenderListener) { + ((WorldRenderListener) abstractFeature).drawWorld(postRender.partialTicks); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onInteract(PlayerInteractEvent postRender) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof InteractListener) { + ((InteractListener) abstractFeature).onInteract(postRender); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + + @SubscribeEvent + public void onRenderWorld(ClientChatReceivedEvent postRender) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof ChatListener) { + ((ChatListener) abstractFeature).onChat(postRender); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @SubscribeEvent + public void onChatGlobal(ClientChatReceivedEvent postRender) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof ChatListenerGlobal) { + ((ChatListenerGlobal) abstractFeature).onChat(postRender); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @SubscribeEvent + public void dungeonTooltip(ItemTooltipEvent event) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof TooltipListener) { + ((TooltipListener) abstractFeature).onTooltip(event); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent tick) { + if (tick.phase == TickEvent.Phase.END && tick.type == TickEvent.Type.CLIENT ) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof TickListener) { + ((TickListener) abstractFeature).onTick(); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + } + @SubscribeEvent + public void onGuiOpen(GuiOpenEvent tick) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof GuiOpenListener) { + ((GuiOpenListener) abstractFeature).onGuiOpen(tick); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onGuiRender(GuiScreenEvent.DrawScreenEvent.Post render) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof GuiPostRenderListener) { + ((GuiPostRenderListener) abstractFeature).onGuiPostRender(render); + } + } + GlStateManager.enableBlend(); + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onGuiRender(GuiScreenEvent.DrawScreenEvent.Pre render) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof GuiPreRenderListener) { + ((GuiPreRenderListener) abstractFeature).onGuiPreRender(render); + } + } + GlStateManager.enableBlend(); + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onGuiRender(GuiScreenEvent.BackgroundDrawnEvent render) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof GuiBackgroundRenderListener) { + ((GuiBackgroundRenderListener) abstractFeature).onGuiBGRender(render); + } + } + GlStateManager.enableBlend(); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @SubscribeEvent(receiveCanceled = true, priority = EventPriority.HIGH) + public void onGuiEvent(GuiScreenEvent.MouseInputEvent.Pre input) { + try { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnSkyblock()) return; + + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof GuiClickListener) { + ((GuiClickListener) abstractFeature).onMouseInput(input); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onSkyblockJoin(SkyblockJoinedEvent joinedEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof SkyblockJoinListener) { + ((SkyblockJoinListener) abstractFeature).onSkyblockJoin(); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onSkyblockQuit(SkyblockLeftEvent leftEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof SkyblockLeaveListener) { + ((SkyblockLeaveListener) abstractFeature).onSkyblockQuit(); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onKey(GuiScreenEvent.KeyboardInputEvent event) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof KeyInputListener) { + ((KeyInputListener) abstractFeature).onKeyInput(event); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onDungeonStart(DungeonStartedEvent leftEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof DungeonStartListener) { + ((DungeonStartListener) abstractFeature).onDungeonStart(); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onDungeonLeft(DungeonLeftEvent leftEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof DungeonQuitListener) { + ((DungeonQuitListener) abstractFeature).onDungeonQuit(); + } + if (abstractFeature instanceof DungeonEndListener) { + ((DungeonEndListener) abstractFeature).onDungeonEnd(); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onDungeonInitialize(DungeonContextInitializationEvent leftEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof DungeonContextInitializationListener) { + ((DungeonContextInitializationListener) abstractFeature).onDungeonInitialize(); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onDungeonInitialize(BossroomEnterEvent enterEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof BossroomEnterListener) { + ((BossroomEnterListener) abstractFeature).onBossroomEnter(); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + @SubscribeEvent + public void onDungeonInitialize(DungeonEndedEvent endedEvent) { + try { + for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) { + if (abstractFeature instanceof DungeonEndListener) { + ((DungeonEndListener) abstractFeature).onDungeonEnd(); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/PacketListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/PacketListener.java new file mode 100644 index 00000000..3ae0b7f5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/PacketListener.java @@ -0,0 +1,176 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.eventlistener; + +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.cosmetics.CustomPacketPlayerListItem; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.network.Packet; +import net.minecraft.network.play.INetHandlerPlayClient; +import net.minecraft.network.play.client.C02PacketUseEntity; +import net.minecraft.network.play.server.*; +import net.minecraft.util.BlockPos; +import net.minecraft.util.Tuple; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent; + +import java.util.Arrays; + +@ChannelHandler.Sharable +public class PacketListener extends ChannelDuplexHandler { + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + Packet packet = (Packet) msg; + if (skyblockStatus.isOnSkyblock() + && msg instanceof S04PacketEntityEquipment + && FeatureRegistry.FIX_SPIRIT_BOOTS.isEnabled()) { // Inventory packet name + S04PacketEntityEquipment packet2 = (S04PacketEntityEquipment) msg; + if (packet2.getEntityID() == Minecraft.getMinecraft().thePlayer.getEntityId()) { + packet2 = new S04PacketEntityEquipment(packet2.getEntityID(), packet2.getEquipmentSlot() + 1, packet2.getItemStack()); + packet = packet2; + } + } + if (packet instanceof S45PacketTitle) { + MinecraftForge.EVENT_BUS.post(new TitleEvent((S45PacketTitle) packet)); + } + if (packet instanceof S38PacketPlayerListItem) { + packet = new CustomPacketPlayerListItem((S38PacketPlayerListItem) packet); + } + if (packet instanceof S30PacketWindowItems) { + packet = new CustomWindowItems((S30PacketWindowItems) packet); + } + if (packet instanceof S2FPacketSetSlot) { + packet = new CustomSetSlot((S2FPacketSetSlot) packet); + } + if (packet instanceof S23PacketBlockChange) { + packet = new SingleBlockChange((S23PacketBlockChange) packet); + } else if (packet instanceof S22PacketMultiBlockChange) { + packet = new MultiBlockChange((S22PacketMultiBlockChange) packet); + } + super.channelRead(ctx, packet); + } + + private static class CustomWindowItems extends S30PacketWindowItems { + public CustomWindowItems(S30PacketWindowItems parent) { + super(parent.func_148911_c(), Arrays.asList(parent.getItemStacks())); + } + + @Override + public void processPacket(INetHandlerPlayClient handler) { + super.processPacket(handler); + MinecraftForge.EVENT_BUS.post(new WindowUpdateEvent(this, null)); + } + } + private static class CustomSetSlot extends S2FPacketSetSlot { + public CustomSetSlot(S2FPacketSetSlot parent) { + super(parent.func_149175_c(), parent.func_149173_d(), parent.func_149174_e()); + } + @Override + public void processPacket(INetHandlerPlayClient handler) { + super.processPacket(handler); + MinecraftForge.EVENT_BUS.post(new WindowUpdateEvent(null, this)); + } + } + + private static class SingleBlockChange extends S23PacketBlockChange { + private S23PacketBlockChange old; + public SingleBlockChange(S23PacketBlockChange blockChange) { + this.old = blockChange; + } + + @Override + public void processPacket(INetHandlerPlayClient handler) { + BlockUpdateEvent blockUpdateEvent = new BlockUpdateEvent.Pre(); + blockUpdateEvent.getUpdatedBlocks().add(new Tuple<>(getBlockPosition(),getBlockState())); + MinecraftForge.EVENT_BUS.post(blockUpdateEvent); + super.processPacket(handler); + blockUpdateEvent = new BlockUpdateEvent.Post(); + blockUpdateEvent.getUpdatedBlocks().add(new Tuple<>(getBlockPosition(), getBlockState())); + MinecraftForge.EVENT_BUS.post(blockUpdateEvent); + } + + @Override + public BlockPos getBlockPosition() { + return old.getBlockPosition(); + } + + @Override + public IBlockState getBlockState() { + return old.getBlockState(); + } + } + + + private static class MultiBlockChange extends S22PacketMultiBlockChange { + private S22PacketMultiBlockChange old; + public MultiBlockChange(S22PacketMultiBlockChange blockChange) { + this.old = blockChange; + } + @Override + public void processPacket(INetHandlerPlayClient handler) { + BlockUpdateEvent blockUpdateEvent = new BlockUpdateEvent.Pre(); + for (S22PacketMultiBlockChange.BlockUpdateData changedBlock : getChangedBlocks()) { + blockUpdateEvent.getUpdatedBlocks().add(new Tuple<>(changedBlock.getPos(), changedBlock.getBlockState())); + } + MinecraftForge.EVENT_BUS.post(blockUpdateEvent); + super.processPacket(handler); + blockUpdateEvent = new BlockUpdateEvent.Post(); + for (S22PacketMultiBlockChange.BlockUpdateData changedBlock : getChangedBlocks()) { + blockUpdateEvent.getUpdatedBlocks().add(new Tuple<>(changedBlock.getPos(), changedBlock.getBlockState())); + } + MinecraftForge.EVENT_BUS.post(blockUpdateEvent); + } + + @Override + public BlockUpdateData[] getChangedBlocks() { + return old.getChangedBlocks(); + } + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + Packet packet = (Packet) msg; + if (packet instanceof C02PacketUseEntity) { + C02PacketUseEntity packet2 = (C02PacketUseEntity) packet; + PlayerInteractEntityEvent piee; + if (packet2.getAction() == C02PacketUseEntity.Action.ATTACK) + piee = new PlayerInteractEntityEvent(true, packet2.getEntityFromWorld(Minecraft.getMinecraft().theWorld)); + else + piee = new PlayerInteractEntityEvent(false, ((C02PacketUseEntity) packet).getEntityFromWorld(Minecraft.getMinecraft().theWorld)); + + if (MinecraftForge.EVENT_BUS.post(piee)) return; + } + super.write(ctx, msg, promise); + } + + @SubscribeEvent + public void onServerConnect(FMLNetworkEvent.ClientConnectedToServerEvent event) { + event.manager.channel().pipeline().addBefore("packet_handler", "dg_packet_handler", this); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/BlockUpdateEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/BlockUpdateEvent.java new file mode 100644 index 00000000..81480223 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/BlockUpdateEvent.java @@ -0,0 +1,37 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import lombok.Getter; +import lombok.Setter; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.BlockPos; +import net.minecraft.util.Tuple; +import net.minecraftforge.fml.common.eventhandler.Event; + +import java.util.HashSet; +import java.util.Set; + +public abstract class BlockUpdateEvent extends Event { + @Getter @Setter + private Set<Tuple<BlockPos, IBlockState>> updatedBlocks = new HashSet<>(); + + public static class Pre extends BlockUpdateEvent {}; + public static class Post extends BlockUpdateEvent {}; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/BossroomEnterEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/BossroomEnterEvent.java new file mode 100644 index 00000000..d02e8f84 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/BossroomEnterEvent.java @@ -0,0 +1,24 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import net.minecraftforge.fml.common.eventhandler.Event; + +public class BossroomEnterEvent extends Event { +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserJoinRequestEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserJoinRequestEvent.java new file mode 100644 index 00000000..80a9315a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserJoinRequestEvent.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordUser; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraftforge.fml.common.eventhandler.Event; + +@Data @AllArgsConstructor +public class DiscordUserJoinRequestEvent extends Event { + private DiscordUser discordUser; + private boolean isInvite; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserUpdateEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserUpdateEvent.java new file mode 100644 index 00000000..858da5bf --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserUpdateEvent.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import kr.syeyoung.dungeonsguide.rpc.JDiscordRelation; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraftforge.fml.common.eventhandler.Event; + +@Data @AllArgsConstructor +public class DiscordUserUpdateEvent extends Event { + private JDiscordRelation prev, current; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonContextInitializationEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonContextInitializationEvent.java new file mode 100644 index 00000000..81ceffed --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonContextInitializationEvent.java @@ -0,0 +1,24 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import net.minecraftforge.fml.common.eventhandler.Event; + +public class DungeonContextInitializationEvent extends Event { +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonEndedEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonEndedEvent.java new file mode 100644 index 00000000..7430389f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonEndedEvent.java @@ -0,0 +1,24 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import net.minecraftforge.fml.common.eventhandler.Event; + +public class DungeonEndedEvent extends Event { +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonLeftEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonLeftEvent.java new file mode 100644 index 00000000..a0abaea8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonLeftEvent.java @@ -0,0 +1,24 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import net.minecraftforge.fml.common.eventhandler.Event; + +public class DungeonLeftEvent extends Event { +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonStartedEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonStartedEvent.java new file mode 100644 index 00000000..6fc7dd02 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/DungeonStartedEvent.java @@ -0,0 +1,24 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import net.minecraftforge.fml.common.eventhandler.Event; + +public class DungeonStartedEvent extends Event { +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/HypixelJoinedEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/HypixelJoinedEvent.java new file mode 100644 index 00000000..c442ca62 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/HypixelJoinedEvent.java @@ -0,0 +1,24 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import net.minecraftforge.fml.common.eventhandler.Event; + +public class HypixelJoinedEvent extends Event { +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/KeyBindPressedEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/KeyBindPressedEvent.java new file mode 100644 index 00000000..c277b227 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/KeyBindPressedEvent.java @@ -0,0 +1,28 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraftforge.fml.common.eventhandler.Event; + +@Data @AllArgsConstructor +public class KeyBindPressedEvent extends Event { + private int key; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/PlayerInteractEntityEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/PlayerInteractEntityEvent.java new file mode 100644 index 00000000..e11bf0cb --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/PlayerInteractEntityEvent.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.entity.Entity; +import net.minecraftforge.fml.common.eventhandler.Event; + +@AllArgsConstructor +public class PlayerInteractEntityEvent extends Event { + + @Getter @Setter + private boolean attack; + @Getter @Setter + private Entity entity; + + @Override + public boolean isCancelable() { + return true; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/PlayerListItemPacketEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/PlayerListItemPacketEvent.java new file mode 100644 index 00000000..65e936f0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/PlayerListItemPacketEvent.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.network.play.server.S38PacketPlayerListItem; +import net.minecraftforge.fml.common.eventhandler.Event; + +@Data +@AllArgsConstructor +public class PlayerListItemPacketEvent extends Event { + private S38PacketPlayerListItem packetPlayerListItem; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/SkyblockJoinedEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/SkyblockJoinedEvent.java new file mode 100644 index 00000000..4a04d55c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/SkyblockJoinedEvent.java @@ -0,0 +1,24 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import net.minecraftforge.fml.common.eventhandler.Event; + +public class SkyblockJoinedEvent extends Event { +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/SkyblockLeftEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/SkyblockLeftEvent.java new file mode 100644 index 00000000..5055b1bc --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/SkyblockLeftEvent.java @@ -0,0 +1,24 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import net.minecraftforge.fml.common.eventhandler.Event; + +public class SkyblockLeftEvent extends Event { +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/StompConnectedEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/StompConnectedEvent.java new file mode 100644 index 00000000..50eba951 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/StompConnectedEvent.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import kr.syeyoung.dungeonsguide.stomp.StompInterface; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraftforge.fml.common.eventhandler.Event; + +@Data +@AllArgsConstructor +public class StompConnectedEvent extends Event { + private StompInterface stompInterface; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/TitleEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/TitleEvent.java new file mode 100644 index 00000000..0559524c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/TitleEvent.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.network.play.server.S45PacketTitle; +import net.minecraftforge.fml.common.eventhandler.Event; + +@Data +@AllArgsConstructor +public class TitleEvent extends Event { + S45PacketTitle packetTitle; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/events/WindowUpdateEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/WindowUpdateEvent.java new file mode 100644 index 00000000..5715687b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/events/WindowUpdateEvent.java @@ -0,0 +1,32 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.events; + +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.network.play.server.S2FPacketSetSlot; +import net.minecraft.network.play.server.S30PacketWindowItems; +import net.minecraftforge.fml.common.eventhandler.Event; + +@Data +@AllArgsConstructor +public class WindowUpdateEvent extends Event { + S30PacketWindowItems windowItems; + S2FPacketSetSlot packetSetSlot; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/AbstractFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/AbstractFeature.java new file mode 100644 index 00000000..9eea3694 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/AbstractFeature.java @@ -0,0 +1,109 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features; + +import com.google.common.base.Supplier; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator; +import kr.syeyoung.dungeonsguide.config.guiconfig.MFeatureEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.MParameterEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.RootConfigPanel; +import kr.syeyoung.dungeonsguide.config.types.TypeConverter; +import kr.syeyoung.dungeonsguide.config.types.TypeConverterRegistry; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.Setter; + +import java.util.*; + +public abstract class AbstractFeature { + @Getter + private final String category; + @Getter + private final String name; + + @Getter + private final String description; + + @Getter + private final String key; + + protected Map<String, FeatureParameter> parameters = new HashMap<String, FeatureParameter>(); + + protected AbstractFeature(String category, String name, String description, String key) { + this.category = category; + this.name = name; + this.description = description; + this.key = key; + } + + @Getter + @Setter + private boolean enabled = true; + + public List<FeatureParameter> getParameters() { return new ArrayList<FeatureParameter>(parameters.values()); } + + public <T> FeatureParameter<T> getParameter(String key) { + return parameters.get(key); + } + + public void loadConfig(JsonObject jsonObject) { // gets key, calls it + enabled = jsonObject.get("$enabled").getAsBoolean(); + + for (Map.Entry<String, FeatureParameter> parameterEntry : parameters.entrySet()) { + parameterEntry.getValue().setToDefault(); + JsonElement element = jsonObject.get(parameterEntry.getKey()); + if (element == null) continue; + TypeConverter typeConverter = TypeConverterRegistry.getTypeConverter(parameterEntry.getValue().getValue_type()); + parameterEntry.getValue().setValue(typeConverter.deserialize(element)); + } + } + + public JsonObject saveConfig() { + JsonObject object = new JsonObject(); + for (Map.Entry<String, FeatureParameter> parameterEntry : parameters.entrySet()) { + TypeConverter typeConverter = TypeConverterRegistry.getTypeConverter(parameterEntry.getValue().getValue_type()); + JsonElement obj = typeConverter.serialize(parameterEntry.getValue().getValue()); + object.add(parameterEntry.getKey(), obj); + } + object.addProperty("$enabled", isEnabled()); + return object; + } + + public String getEditRoute(RootConfigPanel rootConfigPanel) { + ConfigPanelCreator.map.put("base." + key , new Supplier<MPanel>() { + @Override + public MPanel get() { + MFeatureEdit featureEdit = new MFeatureEdit(AbstractFeature.this, rootConfigPanel); + for (FeatureParameter parameter: getParameters()) { + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(AbstractFeature.this, parameter, rootConfigPanel)); + } + return featureEdit; + } + }); + return "base." + key ; + } + + public void onParameterReset() {} + + public boolean isDisyllable() { + return true; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureParameter.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureParameter.java new file mode 100644 index 00000000..eabfe218 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureParameter.java @@ -0,0 +1,51 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features; + +import kr.syeyoung.dungeonsguide.config.types.TypeConverter; +import kr.syeyoung.dungeonsguide.config.types.TypeConverterRegistry; +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class FeatureParameter<T> { + private String key; + + private String name; + private String description; + + private T value; + private T default_value; + private String value_type; + + public FeatureParameter(String key, String name, String description, T default_value, String value_type) { + this.key = key; this.name = name; this.default_value = default_value; + this.description = description; this.value_type = value_type; + } + + public void setToDefault() { + TypeConverter<T> typeConverter = TypeConverterRegistry.getTypeConverter(getValue_type()); + value = (T) typeConverter.deserialize(typeConverter.serialize(default_value)); + } + + public T getValue() { + return value == null ? default_value : value; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java new file mode 100644 index 00000000..b7beb540 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java @@ -0,0 +1,219 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features; + +import kr.syeyoung.dungeonsguide.features.impl.advanced.FeatureDebug; +import kr.syeyoung.dungeonsguide.features.impl.advanced.FeatureDebuggableMap; +import kr.syeyoung.dungeonsguide.features.impl.advanced.FeatureRoomCoordDisplay; +import kr.syeyoung.dungeonsguide.features.impl.advanced.FeatureRoomDebugInfo; +import kr.syeyoung.dungeonsguide.features.impl.boss.*; +import kr.syeyoung.dungeonsguide.features.impl.boss.terminal.FeatureSimonSaysSolver; +import kr.syeyoung.dungeonsguide.features.impl.boss.terminal.FeatureTerminalSolvers; +import kr.syeyoung.dungeonsguide.features.impl.cosmetics.FeatureNicknameColor; +import kr.syeyoung.dungeonsguide.features.impl.cosmetics.FeatureNicknamePrefix; +import kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer.PartyInviteViewer; +import kr.syeyoung.dungeonsguide.features.impl.discord.onlinealarm.PlayingDGAlarm; +import kr.syeyoung.dungeonsguide.features.impl.dungeon.*; +import kr.syeyoung.dungeonsguide.features.impl.etc.*; +import kr.syeyoung.dungeonsguide.features.impl.etc.ability.FeatureAbilityCooldown; +import kr.syeyoung.dungeonsguide.features.impl.party.APIKey; +import kr.syeyoung.dungeonsguide.features.impl.party.FeaturePartyList; +import kr.syeyoung.dungeonsguide.features.impl.party.FeaturePartyReady; +import kr.syeyoung.dungeonsguide.features.impl.party.customgui.FeatureCustomPartyFinder; +import kr.syeyoung.dungeonsguide.features.impl.party.playerpreview.FeatureViewPlayerOnJoin; +import kr.syeyoung.dungeonsguide.features.impl.secret.*; +import kr.syeyoung.dungeonsguide.features.impl.secret.mechanicbrowser.FeatureMechanicBrowse; +import kr.syeyoung.dungeonsguide.features.impl.solvers.*; +import kr.syeyoung.dungeonsguide.features.impl.dungeon.*; +import kr.syeyoung.dungeonsguide.features.impl.solvers.*; +import lombok.Getter; +import org.lwjgl.input.Keyboard; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FeatureRegistry { + @Getter + private static final List<AbstractFeature> featureList = new ArrayList<AbstractFeature>(); + private static final Map<String, AbstractFeature> featureByKey = new HashMap<String, AbstractFeature>(); + @Getter + private static final Map<String, List<AbstractFeature>> featuresByCategory = new HashMap<String, List<AbstractFeature>>(); + @Getter + private static final Map<String, String> categoryDescription = new HashMap<>(); + + public static AbstractFeature getFeatureByKey(String key) { + return featureByKey.get(key); + } + + public static <T extends AbstractFeature> T register(T abstractFeature) { + if (featureByKey.containsKey(abstractFeature.getKey())) throw new IllegalArgumentException("DUPLICATE FEATURE DEFINITION"); + featureList.add(abstractFeature); + featureByKey.put(abstractFeature.getKey(), abstractFeature); + List<AbstractFeature> features = featuresByCategory.get(abstractFeature.getCategory()); + if (features == null) + features = new ArrayList<AbstractFeature>(); + features.add(abstractFeature); + featuresByCategory.put(abstractFeature.getCategory(), features); + + return abstractFeature; + } + + + + public static final PathfindLineProperties SECRET_LINE_PROPERTIES_GLOBAL = register(new PathfindLineProperties("Dungeon Secrets", "Global Line Settings", "Global Line Settings", "secret.lineproperties.global", true, null)); + + + public static final FeatureMechanicBrowse SECRET_BROWSE = register(new FeatureMechanicBrowse()); + public static final PathfindLineProperties SECRET_LINE_PROPERTIES_SECRET_BROWSER = register(new PathfindLineProperties("Dungeon Secrets.Secret Browser", "Line Settings", "Line Settings when pathfinding using Secret Browser", "secret.lineproperties.secretbrowser", true, SECRET_LINE_PROPERTIES_GLOBAL)); + public static final FeatureActions SECRET_ACTIONS = register(new FeatureActions()); + + public static final FeaturePathfindStrategy SECRET_PATHFIND_STRATEGY = register(new FeaturePathfindStrategy()); + public static final FeatureTogglePathfind SECRET_TOGGLE_KEY = register(new FeatureTogglePathfind()); + public static final FeatureFreezePathfind SECRET_FREEZE_LINES = register(new FeatureFreezePathfind()); + public static final FeatureCreateRefreshLine SECRET_CREATE_REFRESH_LINE = register(new FeatureCreateRefreshLine()); + static { + categoryDescription.put("ROOT.Dungeon Secrets.Keybinds", "Useful keybinds / Toggle Pathfind lines, Freeze Pathfind lines, Refresh pathfind line or Trigger pathfind (you would want to use it, if you're using Pathfind to All)"); + } + + + public static final SimpleFeature SECRET_AUTO_BROWSE_NEXT = register(new SimpleFeature("Dungeon Secrets.Legacy AutoPathfind", "Auto Pathfind to next secret", "Auto browse best next secret after current one completes.\nthe first pathfinding of first secret needs to be triggered first in order for this option to work", "secret.autobrowse", false)); + public static final SimpleFeature SECRET_AUTO_START = register(new SimpleFeature("Dungeon Secrets.Legacy AutoPathfind", "Auto pathfind to new secret", "Auto browse best secret upon entering the room.", "secret.autouponenter", false)); + public static final SimpleFeature SECRET_NEXT_KEY = register(new SimpleFeature("Dungeon Secrets.Legacy AutoPathfind", "Auto Pathfind to new secret upon pressing a key", "Auto browse the best next secret when you press key.\nPress settings to edit the key", "secret.keyfornext", false) { + { + parameters.put("key", new FeatureParameter<Integer>("key", "Key","Press to navigate to next best secret", Keyboard.KEY_NONE, "keybind")); + } + }); + + public static final SimpleFeature SECRET_BLOOD_RUSH = register(new FeatureBloodRush()); + public static final PathfindLineProperties SECRET_BLOOD_RUSH_LINE_PROPERTIES = register(new PathfindLineProperties("Dungeon Secrets.Blood Rush", "Blood Rush Line Settings", "Line Settings to be used", "secret.lineproperties.bloodrush", false, SECRET_LINE_PROPERTIES_GLOBAL)); + + + public static final PathfindLineProperties SECRET_LINE_PROPERTIES_AUTOPATHFIND = register(new PathfindLineProperties("Dungeon Secrets.Legacy AutoPathfind", "Line Settings", "Line Settings when pathfinding using above features", "secret.lineproperties.autopathfind", true, SECRET_LINE_PROPERTIES_GLOBAL)); + + public static final FeaturePathfindToAll SECRET_PATHFIND_ALL = register(new FeaturePathfindToAll()); + public static final PathfindLineProperties SECRET_LINE_PROPERTIES_PATHFINDALL_PARENT = register(new PathfindLineProperties("Dungeon Secrets.Pathfind To All", "Parent Line Settings", "Line Settings to be used by default", "secret.lineproperties.apf.parent", false, SECRET_LINE_PROPERTIES_GLOBAL)); + public static final PathfindLineProperties SECRET_LINE_PROPERTIES_PATHFINDALL_BAT = register(new PathfindLineProperties("Dungeon Secrets.Pathfind To All", "Bat Line Settings", "Line Settings when pathfind to Bat, when using above feature", "secret.lineproperties.apf.bat", true, SECRET_LINE_PROPERTIES_PATHFINDALL_PARENT)); + public static final PathfindLineProperties SECRET_LINE_PROPERTIES_PATHFINDALL_CHEST = register(new PathfindLineProperties("Dungeon Secrets.Pathfind To All", "Chest Line Settings", "Line Settings when pathfind to Chest, when using above feature", "secret.lineproperties.apf.chest", true, SECRET_LINE_PROPERTIES_PATHFINDALL_PARENT)); + public static final PathfindLineProperties SECRET_LINE_PROPERTIES_PATHFINDALL_ESSENCE = register(new PathfindLineProperties("Dungeon Secrets.Pathfind To All", "Essence Line Settings", "Line Settings when pathfind to Essence, when using above feature", "secret.lineproperties.apf.essence", true, SECRET_LINE_PROPERTIES_PATHFINDALL_PARENT)); + public static final PathfindLineProperties SECRET_LINE_PROPERTIES_PATHFINDALL_ITEM_DROP = register(new PathfindLineProperties("Dungeon Secrets.Pathfind To All", "Item Drop Line Settings", "Line Settings when pathfind to Item Drop, when using above feature", "secret.lineproperties.apf.itemdrop", true, SECRET_LINE_PROPERTIES_PATHFINDALL_PARENT)); + + public static final FeatureSolverRiddle SOLVER_RIDDLE = register(new FeatureSolverRiddle()); + public static final FeatureSolverTictactoe SOLVER_TICTACTOE = register(new FeatureSolverTictactoe()); + public static final SimpleFeature SOLVER_WATERPUZZLE = register(new SimpleFeature("Solver.Any Floor", "Waterboard (Advanced)", "Calculates solution for waterboard puzzle and displays it to user", "solver.waterboard")); + public static final SimpleFeature SOLVER_CREEPER = register(new SimpleFeature("Solver.Any Floor", "Creeper", "Draws line between prismarine lamps in creeper room", "solver.creeper")); + public static final FeatureSolverTeleport SOLVER_TELEPORT = register(new FeatureSolverTeleport()); + public static final FeatureSolverBlaze SOLVER_BLAZE = register(new FeatureSolverBlaze()); + public static final FeatureSolverIcefill SOLVER_ICEPATH = register(new FeatureSolverIcefill()); + public static final FeatureSolverSilverfish SOLVER_SILVERFISH = register(new FeatureSolverSilverfish()); + public static final FeatureSolverBox SOLVER_BOX = register(new FeatureSolverBox()); + public static final FeatureSolverKahoot SOLVER_KAHOOT = register(new FeatureSolverKahoot()); + public static final FeatureSolverBombdefuse SOLVER_BOMBDEFUSE = register(new FeatureSolverBombdefuse()); + + + public static final FeatureDungeonMap DUNGEON_MAP = register(new FeatureDungeonMap()); + public static final FeatureDungeonRoomName DUNGEON_ROOMNAME = register(new FeatureDungeonRoomName()); + public static final FeaturePressAnyKeyToCloseChest DUNGEON_CLOSECHEST = register(new FeaturePressAnyKeyToCloseChest()); + public static final FeatureBoxSkelemaster DUNGEON_BOXSKELEMASTER = register(new FeatureBoxSkelemaster()); + public static final FeatureBoxBats DUNGEON_BOXBAT = register(new FeatureBoxBats()); + public static final FeatureBoxStarMobs DUNGEON_BOXSTARMOBS = register(new FeatureBoxStarMobs()); + public static final FeatureWatcherWarning DUNGEON_WATCHERWARNING = register(new FeatureWatcherWarning()); + public static final FeatureDungeonDeaths DUNGEON_DEATHS = register(new FeatureDungeonDeaths()); + public static final FeatureDungeonMilestone DUNGEON_MILESTONE = register(new FeatureDungeonMilestone()); + public static final FeatureDungeonRealTime DUNGEON_REALTIME = register(new FeatureDungeonRealTime()); + public static final FeatureDungeonSBTime DUNGEON_SBTIME = register(new FeatureDungeonSBTime()); + public static final FeatureDungeonSecrets DUNGEON_SECRETS = register(new FeatureDungeonSecrets()); + public static final FeatureDungeonCurrentRoomSecrets DUNGEON_SECRETS_ROOM = register(new FeatureDungeonCurrentRoomSecrets()); + public static final FeatureDungeonTombs DUNGEON_TOMBS = register(new FeatureDungeonTombs()); + public static final FeatureDungeonScore DUNGEON_SCORE = register(new FeatureDungeonScore()); + public static final FeatureWarnLowHealth DUNGEON_LOWHEALTH_WARN = register(new FeatureWarnLowHealth()); + public static final SimpleFeature DUNGEON_INTERMODCOMM = register(new SimpleFeature("Dungeon.Teammates", "Communicate With Other's Dungeons Guide", "Sends total secret in the room to others\nSo that they can use the data to calculate total secret in dungeon run\n\nThis automates player chatting action, (chatting data) Thus it might be against hypixel's rules.\nBut mods like auto-gg which also automate player action and is kinda allowed mod exist so I'm leaving this feature.\nThis option is use-at-your-risk and you'll be responsible for ban if you somehow get banned because of this feature\n(Although it is not likely to happen)\nDefaults to off", "dungeon.intermodcomm", false)); + public static final FeaturePlayerESP DUNGEON_PLAYERESP = register(new FeaturePlayerESP()); + public static final FeatureHideNameTags DUNGEON_HIDENAMETAGS = register(new FeatureHideNameTags()); + public static final FeatureSoulRoomWarning DUNGEON_FAIRYSOUL = register(new FeatureSoulRoomWarning()); + + public static final FeatureWarningOnPortal BOSSFIGHT_WARNING_ON_PORTAL = register(new FeatureWarningOnPortal()); + public static final SimpleFeature BOSSFIGHT_CHESTPRICE = register(new FeatureChestPrice()); + public static final FeatureAutoReparty BOSSFIGHT_AUTOREPARTY = register(new FeatureAutoReparty()); + public static final FeatureBossHealth BOSSFIGHT_HEALTH = register(new FeatureBossHealth()); + public static final FeatureHideAnimals BOSSFIGHT_HIDE_ANIMALS = register(new FeatureHideAnimals()); + public static final FeatureThornBearPercentage BOSSFIGHT_BEAR_PERCENT = register(new FeatureThornBearPercentage()); + public static final FeatureThornSpiritBowTimer BOSSFIGHT_BOW_TIMER = register(new FeatureThornSpiritBowTimer()); + public static final FeatureBoxRealLivid BOSSFIGHT_BOX_REALLIVID = register(new FeatureBoxRealLivid()); + public static final FeatureTerracotaTimer BOSSFIGHT_TERRACOTTA_TIMER = register(new FeatureTerracotaTimer()); + public static final FeatureCurrentPhase BOSSFIGHT_CURRENT_PHASE = register(new FeatureCurrentPhase()); + public static final FeatureTerminalSolvers BOSSFIGHT_TERMINAL_SOLVERS = register(new FeatureTerminalSolvers()); + public static final FeatureSimonSaysSolver BOSSFIGHT_SIMONSAYS_SOLVER = register(new FeatureSimonSaysSolver()); + + public static final APIKey PARTYKICKER_APIKEY = register(new APIKey()); + public static final FeatureViewPlayerOnJoin PARTYKICKER_VIEWPLAYER = register(new FeatureViewPlayerOnJoin()); + public static final FeatureCustomPartyFinder PARTYKICKER_CUSTOM = register(new FeatureCustomPartyFinder()); + public static final FeaturePartyList PARTY_LIST = register(new FeaturePartyList()); + public static final FeaturePartyReady PARTY_READY = register(new FeaturePartyReady()); + + public static final FeatureTooltipDungeonStat ETC_DUNGEONSTAT = register(new FeatureTooltipDungeonStat()); + public static final FeatureTooltipPrice ETC_PRICE = register(new FeatureTooltipPrice()); + public static final FeatureAbilityCooldown ETC_ABILITY_COOLDOWN = register(new FeatureAbilityCooldown()); + public static final FeatureCooldownCounter ETC_COOLDOWN = register(new FeatureCooldownCounter()); + public static final FeatureRepartyCommand ETC_REPARTY = register(new FeatureRepartyCommand()); + public static final FeatureDecreaseExplosionSound ETC_EXPLOSION_SOUND = register(new FeatureDecreaseExplosionSound()); + public static final FeatureAutoAcceptReparty ETC_AUTO_ACCEPT_REPARTY = register(new FeatureAutoAcceptReparty()); + public static final FeatureUpdateAlarm ETC_TEST = register(new FeatureUpdateAlarm()); + + public static final SimpleFeature FIX_SPIRIT_BOOTS = register(new SimpleFeature("Misc", "Spirit Boots Fixer", "Fix Spirit boots messing up with inventory", "fixes.spirit", true)); + public static final FeatureDisableMessage FIX_MESSAGES = register(new FeatureDisableMessage()); + + public static final FeatureCopyMessages ETC_COPY_MSG = register(new FeatureCopyMessages()); + + public static final FeaturePenguins ETC_PENGUIN = register(new FeaturePenguins()); + + public static final FeatureCollectScore ETC_COLLECT_SCORE = register(new FeatureCollectScore()); + + + + + + public static final FeatureNicknamePrefix COSMETIC_PREFIX = register(new FeatureNicknamePrefix()); + public static final FeatureNicknameColor COSMETIC_NICKNAMECOLOR = register(new FeatureNicknameColor()); + + + + public static final SimpleFeature DISCORD_RICHPRESENCE = register(new SimpleFeature("Discord", "Discord RPC", "Enable Discord rich presence", "advanced.richpresence", true) { + { + parameters.put("disablenotskyblock", new FeatureParameter<Boolean>("disablenotskyblock", "Disable When not on Skyblock", "Disable When not on skyblock", false, "boolean")); + } + }); + public static final PartyInviteViewer DISCORD_ASKTOJOIN = register(new PartyInviteViewer()); + public static final PlayingDGAlarm DISCORD_ONLINEALARM = register(new PlayingDGAlarm()); + public static final SimpleFeature DISCORD_DONOTUSE = register(new SimpleFeature("Discord", "Disable Native Library", "Disables usage of jna for discord rpc support.\nBreaks any discord related feature in the mod.\nRequires mod restart to get affected.\n\nThis feature is only for those whose minecraft crashes due to discord gamesdk crash.", "discord.rpc", false)); + + + public static final SimpleFeature DEBUG = register(new FeatureDebug()); + public static final SimpleFeature ADVANCED_ROOMEDIT = register(new SimpleFeature("Advanced", "Room Edit", "Allow editing dungeon rooms\n\nWarning: using this feature can break or freeze your Minecraft\nThis is only for advanced users only", "advanced.roomedit", false){ + { + parameters.put("key", new FeatureParameter<Integer>("key", "Key","Press to edit room", Keyboard.KEY_R, "keybind")); + } + }); + + public static final FeatureRoomDebugInfo ADVANCED_DEBUG_ROOM = register(new FeatureRoomDebugInfo()); + public static final FeatureDebuggableMap ADVANCED_DEBUGGABLE_MAP = register(new FeatureDebuggableMap()); + public static final FeatureRoomCoordDisplay ADVANCED_COORDS = register(new FeatureRoomCoordDisplay()); + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/GuiFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/GuiFeature.java new file mode 100644 index 00000000..527a1054 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/GuiFeature.java @@ -0,0 +1,164 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features; + +import com.google.gson.JsonObject; +import kr.syeyoung.dungeonsguide.config.guiconfig.GuiConfigV2; +import kr.syeyoung.dungeonsguide.config.guiconfig.location.GuiGuiLocationConfig; +import kr.syeyoung.dungeonsguide.config.types.GUIRectangle; +import kr.syeyoung.dungeonsguide.config.types.TypeConverterRegistry; +import kr.syeyoung.dungeonsguide.features.listener.ScreenRenderListener; +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MPassiveLabelAndElement; +import kr.syeyoung.dungeonsguide.gui.elements.MToggleButton; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +@Getter +public abstract class GuiFeature extends AbstractFeature implements ScreenRenderListener { + @Setter + private GUIRectangle featureRect; + @Setter(value = AccessLevel.PROTECTED) + private boolean keepRatio; + @Setter(value = AccessLevel.PROTECTED) + private double defaultWidth; + @Setter(value = AccessLevel.PROTECTED) + private double defaultHeight; + private final double defaultRatio; + + protected GuiFeature(String category, String name, String description, String key, boolean keepRatio, int width, int height) { + super(category, name, description, key); + this.keepRatio = keepRatio; + this.defaultWidth = width; + this.defaultHeight = height; + this.defaultRatio = defaultWidth / defaultHeight; + this.featureRect = new GUIRectangle(0, 0, width, height); + } + + @Override + public void drawScreen(float partialTicks) { + if (!isEnabled()) return; + + GlStateManager.pushMatrix(); + Rectangle featureRect = this.featureRect.getRectangleNoScale(); + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + GlStateManager.scale(1.0/scaledResolution.getScaleFactor(), 1.0/scaledResolution.getScaleFactor(), 1); + clip(featureRect.x, featureRect.y, featureRect.width, featureRect.height); + GL11.glEnable(GL11.GL_SCISSOR_TEST); + + GlStateManager.translate(featureRect.x, featureRect.y, 0); + drawHUD(partialTicks); + + GL11.glDisable(GL11.GL_SCISSOR_TEST); + GlStateManager.popMatrix(); + + + GlStateManager.enableBlend(); + GlStateManager.color(1,1,1,1); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + } + + + public abstract void drawHUD(float partialTicks); + + public void drawDemo(float partialTicks) { + drawHUD(partialTicks); + } + + private void clip(int x, int y, int width, int height) { +// int scale = resolution.getScaleFactor(); + int scale = 1; + GL11.glScissor((x ) * scale, Minecraft.getMinecraft().displayHeight - (y + height) * scale, (width) * scale, height * scale); + } + + public static FontRenderer getFontRenderer() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + return fr; + } + + @Override + public void loadConfig(JsonObject jsonObject) { + super.loadConfig(jsonObject); + this.featureRect = TypeConverterRegistry.getTypeConverter("guirect",GUIRectangle.class).deserialize(jsonObject.get("$bounds")); + } + + @Override + public JsonObject saveConfig() { + JsonObject object = super.saveConfig(); + object.add("$bounds", TypeConverterRegistry.getTypeConverter("guirect", GUIRectangle.class).serialize(featureRect)); + return object; + } + + public List<MPanel> getTooltipForEditor(GuiGuiLocationConfig guiGuiLocationConfig) { + ArrayList<MPanel> mPanels = new ArrayList<>(); + mPanels.add(new MLabel(){ + { + setText(getName()); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(Minecraft.getMinecraft().fontRendererObj.getStringWidth(getName()), 20); + } + }); + mPanels.add(new MButton() { + { + setText("Edit"); + setOnActionPerformed(() -> { + GuiScreen guiScreen = guiGuiLocationConfig.getBefore(); + if (guiScreen == null) { + guiScreen = new GuiConfigV2(); + } + Minecraft.getMinecraft().displayGuiScreen(guiScreen); + if (guiScreen instanceof GuiConfigV2) { + ((GuiConfigV2) guiScreen).getRootConfigPanel().setCurrentPageAndPushHistory(getEditRoute(((GuiConfigV2) guiScreen).getRootConfigPanel())); + } + }); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(100,20); + } + }); + mPanels.add(new MPassiveLabelAndElement("Enabled", new MToggleButton() {{ + setEnabled(GuiFeature.this.isEnabled()); + setOnToggle(() ->{ + GuiFeature.this.setEnabled(isEnabled()); + }); } + })); + return mPanels; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/SimpleFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/SimpleFeature.java new file mode 100644 index 00000000..11adeb67 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/SimpleFeature.java @@ -0,0 +1,33 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features; + +public class SimpleFeature extends AbstractFeature { + protected SimpleFeature(String category, String name, String key) { + this(category, name, name, key); + } + protected SimpleFeature(String category, String name, String description, String key) { + this(category, name, description, key, true); + } + + protected SimpleFeature(String category, String name, String description, String key, boolean enabled) { + super(category, name, description, key); + this.setEnabled(enabled); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureDebug.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureDebug.java new file mode 100644 index 00000000..3e8b0a09 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureDebug.java @@ -0,0 +1,65 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.advanced; + +import com.google.common.base.Supplier; +import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.config.guiconfig.MFeatureEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.MParameterEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.RootConfigPanel; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.gui.MPanel; + +public class FeatureDebug extends SimpleFeature { + public FeatureDebug() { + super("Advanced", "Debug", "Toggles debug mode", "debug", false); + parameters.put("Key", new FeatureParameter<String>("Key", "Secret Key given by syeyoung", "Put the debug enable key here to enable debug mode", "","string")); + } + @Override + public boolean isEnabled() { + return "just hide it".equals(this.<String>getParameter("Key").getValue()); + } + @Override + public boolean isDisyllable() { + return false; + } + + @Override + public String getEditRoute(RootConfigPanel rootConfigPanel) { + ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() { + @Override + public MPanel get() { + MFeatureEdit featureEdit = new MFeatureEdit(FeatureDebug.this, rootConfigPanel); + for (FeatureParameter parameter: getParameters()) { + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeatureDebug.this, parameter, rootConfigPanel)); + } + featureEdit.addParameterEdit("IsEnabled", new MParameterEdit(FeatureDebug.this, new FeatureParameter("Key Status", "Key Status", "Key Enabled? Or not?", "", "idk"), rootConfigPanel, new MLabel() { + @Override + public String getText() { + return isEnabled() ? "Enabled!" : "Incorrect Key"; + } + }, (a) -> false)); + return featureEdit; + } + }); + return "base." + getKey() ; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureDebuggableMap.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureDebuggableMap.java new file mode 100644 index 00000000..d2c3b7f6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureDebuggableMap.java @@ -0,0 +1,88 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.advanced; + +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.GuiFeature; +import kr.syeyoung.dungeonsguide.utils.MapUtils; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiChat; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.client.config.GuiUtils; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.Arrays; + +public class FeatureDebuggableMap extends GuiFeature { + public FeatureDebuggableMap() { + super("Advanced", "Display Debug Info included map", "ONLY WORKS WITH SECRET SETTING", "advanced.debug.map", true, 128, 128); + this.setEnabled(false); + } + + + DynamicTexture dynamicTexture = new DynamicTexture(128, 128); + ResourceLocation location = Minecraft.getMinecraft().renderEngine.getDynamicTextureLocation("dungeons/map/", dynamicTexture); + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + @Override + public void drawHUD(float partialTicks) { +// if (!skyblockStatus.isOnDungeon()) return; + if (!FeatureRegistry.DEBUG.isEnabled()) return; +// DungeonContext context = skyblockStatus.getContext(); +// if (context == null) return; + + GlStateManager.pushMatrix(); + double factor = getFeatureRect().getRectangle().getWidth() / 128; + GlStateManager.scale(factor, factor, 1); + int[] textureData = dynamicTexture.getTextureData(); + MapUtils.getImage().getRGB(0, 0, 128, 128, textureData, 0, 128); + dynamicTexture.updateDynamicTexture(); + Minecraft.getMinecraft().getTextureManager().bindTexture(location); + GlStateManager.enableAlpha(); + GuiScreen.drawModalRectWithCustomSizedTexture(0, 0, 0, 0, 128, 128, 128, 128); + GlStateManager.popMatrix(); + + + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChat)) return; + Rectangle featureRect = this.getFeatureRect().getRectangleNoScale(); + + int i = (int) ((int) (Mouse.getEventX() - featureRect.getX()) / factor); + int j = (int) ((int) (Minecraft.getMinecraft().displayHeight - Mouse.getEventY() - featureRect.getY())/ factor); + if (i >= 0 && j>= 0 && i <= 128 && j <= 128 && MapUtils.getColors() != null) { + GuiUtils.drawHoveringText(Arrays.asList(i+","+j,"Color: "+MapUtils.getColors()[j * 128 + i]),(int)(Mouse.getEventX() - featureRect.getX()), (int) (Minecraft.getMinecraft().displayHeight - Mouse.getEventY() - featureRect.getY()), Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight, -1, Minecraft.getMinecraft().fontRendererObj); + } + } + + @Override + public void drawDemo(float partialTicks) { + FontRenderer fr = getFontRenderer(); + Rectangle featureRect = getFeatureRect().getRectangle(); + GL11.glLineWidth(2); + RenderUtils.drawUnfilledBox(0,0,featureRect.width, featureRect.height, 0xff000000, false); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureRoomCoordDisplay.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureRoomCoordDisplay.java new file mode 100644 index 00000000..9762893b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureRoomCoordDisplay.java @@ -0,0 +1,93 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.advanced; + +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.GuiFeature; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.BlockPos; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; + +public class FeatureRoomCoordDisplay extends GuiFeature { + public FeatureRoomCoordDisplay() { + super("Advanced", "Display Coordinate Relative to the Dungeon Room and room's rotation", "X: 0 Y: 3 Z: 5 Facing: Z+" , "advanced.coords", false, getFontRenderer().getStringWidth("X: 48 Y: 100 Z: 48 Facing: Z+"), 10); + this.setEnabled(false); + parameters.put("color", new FeatureParameter<Color>("color", "Color", "Color of text", Color.yellow, "color")); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + private static final String[] facing = {"Z+", "X-", "Z-", "X+"}; + @Override + public void drawHUD(float partialTicks) { + if (!skyblockStatus.isOnDungeon()) return; + DungeonContext context = skyblockStatus.getContext(); + if (context == null) return; + + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom == null) { + return; + } + + int facing = (int) (thePlayer.rotationYaw + 45) % 360; + if (facing < 0) facing += 360; + int real = (facing / 90 + dungeonRoom.getRoomMatcher().getRotation()) % 4; + + OffsetPoint offsetPoint = new OffsetPoint(dungeonRoom, new BlockPos((int)thePlayer.posX, (int)thePlayer.posY, (int)thePlayer.posZ)); + + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj; + + double scale = getFeatureRect().getRectangle().getHeight() / fontRenderer.FONT_HEIGHT; + GlStateManager.scale(scale, scale, 0); + + int color = this.<Color>getParameter("color").getValue().getRGB(); + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fontRenderer.drawString("X: "+offsetPoint.getX()+" Y: "+offsetPoint.getY()+" Z: "+offsetPoint.getZ()+" Facing: "+ FeatureRoomCoordDisplay.facing[real], 0, 0, color); + } + + @Override + public void drawDemo(float partialTicks) { + FontRenderer fr = getFontRenderer(); + int facing = (int) (Minecraft.getMinecraft().thePlayer.rotationYaw + 45) % 360; + if (facing < 0) facing += 360; + double scale = getFeatureRect().getRectangle().getHeight() / fr.FONT_HEIGHT; + GlStateManager.scale(scale, scale, 0); + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("X: 0 Y: 3 Z: 5 Facing: "+FeatureRoomCoordDisplay.facing[(facing / 90) % 4], 0,0, this.<Color>getParameter("color").getValue().getRGB()); + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureRoomDebugInfo.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureRoomDebugInfo.java new file mode 100644 index 00000000..8ad1b470 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/advanced/FeatureRoomDebugInfo.java @@ -0,0 +1,94 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.advanced; + +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.GuiFeature; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import org.apache.commons.lang3.StringUtils; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; + +public class FeatureRoomDebugInfo extends GuiFeature { + public FeatureRoomDebugInfo() { + super("Advanced", "Display Room Debug Info", "ONLY WORKS WITH SECRET SETTING", "advanced.debug.roominfo", false, getFontRenderer().getStringWidth("longestplayernamepos: 100"), getFontRenderer().FONT_HEIGHT * 6); + this.setEnabled(false); + parameters.put("color", new FeatureParameter<Color>("color", "Color", "Color of text", Color.white, "color")); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + @Override + public void drawHUD(float partialTicks) { + if (!skyblockStatus.isOnDungeon()) return; + if (!FeatureRegistry.DEBUG.isEnabled()) return; + DungeonContext context = skyblockStatus.getContext(); + if (context == null) return; + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj; + int color = this.<Color>getParameter("color").getValue().getRGB(); + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + if (dungeonRoom == null) { + if (context.getBossfightProcessor() == null) { + fontRenderer.drawString("Where are you?!", 0, 0, 0xFFFFFF); + } else { + fontRenderer.drawString("You're prob in bossfight", 0, 0, color); + fontRenderer.drawString("processor: "+context.getBossfightProcessor(), 0, 10, color); + fontRenderer.drawString("phase: "+context.getBossfightProcessor().getCurrentPhase(), 0, 20, color); + fontRenderer.drawString("nextPhase: "+ StringUtils.join(context.getBossfightProcessor().getNextPhases(), ","), 0, 30, color); + fontRenderer.drawString("phases: "+ StringUtils.join(context.getBossfightProcessor().getPhases(), ","), 0, 40, color); + } + } else { + fontRenderer.drawString("you're in the room... color/shape/rot " + dungeonRoom.getColor() + " / " + dungeonRoom.getShape() + " / "+dungeonRoom.getRoomMatcher().getRotation(), 0, 0, color); + fontRenderer.drawString("room uuid: " + dungeonRoom.getDungeonRoomInfo().getUuid() + (dungeonRoom.getDungeonRoomInfo().isRegistered() ? "" : " (not registered)"), 0, 10, color); + fontRenderer.drawString("room name: " + dungeonRoom.getDungeonRoomInfo().getName(), 0, 20, color); + fontRenderer.drawString("room state / max secret: " + dungeonRoom.getCurrentState() + " / "+dungeonRoom.getTotalSecrets(), 0, 30, color); + + } + } + + @Override + public void drawDemo(float partialTicks) { + FontRenderer fr = getFontRenderer(); + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Line 1", 0,0, this.<Color>getParameter("color").getValue().getRGB()); + fr.drawString("Line 2", 0,10, this.<Color>getParameter("color").getValue().getRGB()); + fr.drawString("Line 3", 0,20, this.<Color>getParameter("color").getValue().getRGB()); + fr.drawString("Line 4", 0,30, this.<Color>getParameter("color").getValue().getRGB()); + fr.drawString("Line 5", 0,40, this.<Color>getParameter("color").getValue().getRGB()); + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureAutoReparty.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureAutoReparty.java new file mode 100644 index 00000000..418b1654 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureAutoReparty.java @@ -0,0 +1,34 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.features.listener.DungeonQuitListener; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +public class FeatureAutoReparty extends SimpleFeature implements DungeonQuitListener { + public FeatureAutoReparty() { + super("Party.Reparty", "Auto reparty when dungeon finishes","Auto reparty on dungeon finish\n\nThis automates player chatting action, (disbanding, repartying) Thus it might be against hypixel's rules.\nBut mods like auto-gg exist so I'm leaving this feature.\nThis option is use-at-your-risk and you'll be responsible for ban if you somehow get banned because of this feature\n(Although it is not likely to happen)\nDefaults to off", "bossfight.autoreparty", false); + } + + @Override + public void onDungeonQuit() { + if (isEnabled()) DungeonsGuide.getDungeonsGuide().getCommandReparty().requestReparty(true); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureBossHealth.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureBossHealth.java new file mode 100644 index 00000000..fb858adf --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureBossHealth.java @@ -0,0 +1,103 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.HealthData; +import kr.syeyoung.dungeonsguide.utils.TextUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureBossHealth extends TextHUDFeature { + public FeatureBossHealth() { + super("Bossfight", "Display Boss Health(s)", "Show the health of boss and minibosses in bossfight (Guardians, Priests..)", "bossfight.health", false, getFontRenderer().getStringWidth("The Professor: 4242m"), getFontRenderer().FONT_HEIGHT * 5); + this.setEnabled(true); + parameters.put("totalHealth", new FeatureParameter<Boolean>("totalHealth", "show total health", "Show total health along with current health", false, "boolean")); + parameters.put("formatHealth", new FeatureParameter<Boolean>("formatHealth", "format health", "1234568 -> 1m", true, "boolean")); + parameters.put("ignoreInattackable", new FeatureParameter<Boolean>("ignoreInattackable", "Don't show health of in-attackable enemy", "For example, do not show guardians health when they're not attackable", false, "boolean")); + + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("health", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator2", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("maxHealth", new AColor(0x55, 0x55,0xFF,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + + @Override + public boolean doesScaleWithHeight() { + return false; + } + + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon() && skyblockStatus.getContext() != null && skyblockStatus.getContext().getBossfightProcessor() != null; + } + + @Override + public java.util.List<String> getUsedTextStyle() { + return Arrays.asList("title", "separator", "health", "separator2", "maxHealth"); + } + + @Override + public java.util.List<StyledText> getDummyText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + addLine(new HealthData("The Professor", 3300000, 5000000, false), actualBit); + addLine(new HealthData("Chaos Guardian", 500000, 2000000, true), actualBit); + addLine(new HealthData("Healing Guardian", 1000000, 3000000, true), actualBit); + addLine(new HealthData("Laser Guardian", 5000000, 5000000, true), actualBit); + addLine(new HealthData("Giant", 10000000, 20000000, false), actualBit); + return actualBit; + } + + public void addLine(HealthData data, List<StyledText> actualBit) { + boolean format = this.<Boolean>getParameter("formatHealth").getValue(); + boolean total = this.<Boolean>getParameter("totalHealth").getValue(); + boolean ignore = this.<Boolean>getParameter("ignoreInattackable").getValue(); + if (ignore && !data.isAttackable()) return; + + actualBit.add(new StyledText(data.getName(),"title")); + actualBit.add(new StyledText(": ","separator")); + actualBit.add(new StyledText( (format ? TextUtils.format(data.getHealth()) : data.getHealth()) + (total ? "" : "\n"),"health")); + if (total) { + actualBit.add(new StyledText("/", "separator2")); + actualBit.add(new StyledText( (format ? TextUtils.format(data.getMaxHealth()) : data.getMaxHealth()) +"\n","maxHealth")); + } + } + + @Override + public java.util.List<StyledText> getText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + List<HealthData> healths = skyblockStatus.getContext().getBossfightProcessor().getHealths(); + for (HealthData heal : healths) { + addLine(heal, actualBit); + } + return actualBit; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureBoxRealLivid.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureBoxRealLivid.java new file mode 100644 index 00000000..f70ced10 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureBoxRealLivid.java @@ -0,0 +1,54 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.WorldRenderListener; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessorLivid; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.util.AxisAlignedBB; + + +public class FeatureBoxRealLivid extends SimpleFeature implements WorldRenderListener { + public FeatureBoxRealLivid() { + super("Bossfight.Floor 5", "Box Real Livid", "Box Real Livid in bossfight", "bossfight.realLividBox", true); + parameters.put("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Livid", new AColor(0,255,0,150), "acolor")); + } + + + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + @Override + public void drawWorld(float partialTicks) { + if (!isEnabled()) return; + if (!skyblockStatus.isOnDungeon()) return; + if (skyblockStatus.getContext() == null) return; + if (skyblockStatus.getContext().getBossfightProcessor() == null) return; + if (!(skyblockStatus.getContext().getBossfightProcessor() instanceof BossfightProcessorLivid)) return; + EntityOtherPlayerMP playerMP = ((BossfightProcessorLivid) skyblockStatus.getContext().getBossfightProcessor()).getRealLivid(); + + AColor c = this.<AColor>getParameter("color").getValue(); + if (playerMP != null) + RenderUtils.highlightBox(playerMP, AxisAlignedBB.fromBounds(-0.4,0,-0.4,0.4,1.8,0.4), c, partialTicks, true); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureChestPrice.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureChestPrice.java new file mode 100644 index 00000000..de3873ba --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureChestPrice.java @@ -0,0 +1,174 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.features.listener.GuiBackgroundRenderListener; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.utils.AhUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.client.event.GuiScreenEvent; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.util.Comparator; +import java.util.Set; +import java.util.TreeSet; + +public class FeatureChestPrice extends SimpleFeature implements GuiBackgroundRenderListener { + public FeatureChestPrice() { + super("Bossfight", "Show Profit of Dungeon Chests","Show Profit of Dungeon Chests", "bossfight.profitchest", false); + } + + @Override + public void onGuiBGRender(GuiScreenEvent.BackgroundDrawnEvent rendered) { + if (!isEnabled()) return; + if (!(rendered.gui instanceof GuiChest)) return; + if (!DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnDungeon()) return; + + GlStateManager.disableLighting(); + + ContainerChest chest = (ContainerChest) ((GuiChest) rendered.gui).inventorySlots; + if (!chest.getLowerChestInventory().getName().endsWith("Chest")) return; + IInventory actualChest = chest.getLowerChestInventory(); + + int chestPrice = 0; + int itemPrice = 0; + for (int i = 0; i <actualChest.getSizeInventory(); i++) { + ItemStack item = actualChest.getStackInSlot(i); + if (item != null) { + if (item.getDisplayName() != null && item.getDisplayName().contains("Reward")) { + NBTTagCompound tagCompound = item.serializeNBT().getCompoundTag("tag"); + if (tagCompound != null && tagCompound.hasKey("display", 10)) { + NBTTagCompound nbttagcompound = tagCompound.getCompoundTag("display"); + + if (nbttagcompound.getTagId("Lore") == 9) { + NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8); + + if (nbttaglist1.tagCount() > 0) { + for (int j1 = 0; j1 < nbttaglist1.tagCount(); ++j1) { + String str = nbttaglist1.getStringTagAt(j1); + if (str.endsWith("Coins")) { + String coins = TextUtils.stripColor(str).replace(" Coins", "").replace(",",""); + try { + chestPrice = Integer.parseInt(coins); + } catch (Exception e) { + + } + } + } + } + } + } + } + itemPrice += getPrice(item) * item.stackSize; + } + } + + int i = 222; + int j = i - 108; + int ySize = j + (actualChest.getSizeInventory() / 9) * 18; + int left = (rendered.gui.width + 176) / 2; + int top = (rendered.gui.height - ySize ) / 2; + + int width = 120; + + GlStateManager.pushMatrix(); + GlStateManager.translate(left, top, 0); + Gui.drawRect( 0,0,width, 30, 0xFFDDDDDD); + + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString("BIN/AH Price: ", 5,5, 0xFF000000); + String str = TextUtils.format(itemPrice); + fr.drawString(str, width - fr.getStringWidth(str) - 5, 5, 0xFF000000); + + fr.drawString("Profit: ", 5,15, 0xFF000000); + str = (itemPrice > chestPrice ? "+" : "") +TextUtils.format(itemPrice - chestPrice); + fr.drawString(str, width - fr.getStringWidth(str) - 5, 15, itemPrice > chestPrice ? 0xFF00CC00 : 0xFFCC0000); + + GlStateManager.popMatrix(); + + GlStateManager.enableLighting(); + GlStateManager.enableBlend(); + } + + public static long getPrice(ItemStack itemStack) { + if (itemStack == null) return 0; + NBTTagCompound compound = itemStack.getTagCompound(); + if (compound == null) + return 0; + if (!compound.hasKey("ExtraAttributes")) + return 0; + final String id = compound.getCompoundTag("ExtraAttributes").getString("id"); + if (id.equals("ENCHANTED_BOOK")) { + final NBTTagCompound enchants = compound.getCompoundTag("ExtraAttributes").getCompoundTag("enchantments"); + Set<String> keys = enchants.getKeySet(); + Set<String> actualKeys = new TreeSet<String>(new Comparator<String>() { + public int compare(String o1, String o2) { + String id2 = id + "::" + o1 + "-" + enchants.getInteger(o1); + AhUtils.AuctionData auctionData = AhUtils.auctions.get(id2); + long price1 = (auctionData == null) ? 0 : auctionData.lowestBin; + String id3 = id + "::" + o2 + "-" + enchants.getInteger(o2); + AhUtils.AuctionData auctionData2 = AhUtils.auctions.get(id3); + long price2 = (auctionData2 == null) ? 0 : auctionData2.lowestBin; + return (compare2(price1, price2) == 0) ? o1.compareTo(o2) : compare2(price1, price2); + } + + public int compare2(long y, long x) { + return (x < y) ? -1 : ((x == y) ? 0 : 1); + } + }); + actualKeys.addAll(keys); + int totalLowestPrice = 0; + for (String key : actualKeys) { + String id2 = id + "::" + key + "-" + enchants.getInteger(key); + AhUtils.AuctionData auctionData = AhUtils.auctions.get(id2); + totalLowestPrice += auctionData.lowestBin; + } + return totalLowestPrice; + } else { + AhUtils.AuctionData auctionData = AhUtils.auctions.get(id); + if (auctionData == null) { + return 0; + } else { + if (auctionData.sellPrice == -1 && auctionData.lowestBin != -1) return auctionData.lowestBin; + else if (auctionData.sellPrice != -1 && auctionData.lowestBin == -1) return auctionData.sellPrice; + else { + long ahPrice = auctionData.lowestBin; + if (ahPrice > auctionData.sellPrice) return ahPrice; + else return auctionData.sellPrice; + } + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureCurrentPhase.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureCurrentPhase.java new file mode 100644 index 00000000..5c199c61 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureCurrentPhase.java @@ -0,0 +1,74 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureCurrentPhase extends TextHUDFeature { + public FeatureCurrentPhase() { + super("Bossfight", "Display Current Phase", "Displays the current phase of bossfight", "bossfight.phasedisplay", false, getFontRenderer().getStringWidth("Current Phase: fight-2-idk-howlng"), getFontRenderer().FONT_HEIGHT); + this.setEnabled(true); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("phase", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + private static final List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Current Phase","title")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("fight-2","phase")); + } + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon() && skyblockStatus.getContext() != null && skyblockStatus.getContext().getBossfightProcessor() != null; + } + + @Override + public List<String> getUsedTextStyle() { + return Arrays.asList("title", "separator", "phase"); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public List<StyledText> getText() { + String currentPhsae =skyblockStatus.getContext().getBossfightProcessor().getCurrentPhase(); + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("Current Phase","title")); + actualBit.add(new StyledText(": ","separator")); + actualBit.add(new StyledText(currentPhsae,"phase")); + return actualBit; + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureHideAnimals.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureHideAnimals.java new file mode 100644 index 00000000..837b3d71 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureHideAnimals.java @@ -0,0 +1,69 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.features.listener.EntityLivingRenderListener; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessorThorn; +import net.minecraft.entity.passive.*; +import net.minecraftforge.client.event.RenderLivingEvent; + + +public class FeatureHideAnimals extends SimpleFeature implements EntityLivingRenderListener { + public FeatureHideAnimals() { + super("Bossfight.Floor 4", "Hide animals on f4", "Hide Spirit Animals on F4. \nClick on Edit for precise setting", "bossfight.hideanimals", false); + parameters.put("sheep", new FeatureParameter<Boolean>("sheep", "Hide Sheeps", "Hide Sheeps", true, "boolean")); + parameters.put("cow", new FeatureParameter<Boolean>("cow", "Hide Cows", "Hide Cows", true, "boolean")); + parameters.put("chicken", new FeatureParameter<Boolean>("chicken", "Hide Chickens", "Hide Chickens", true, "boolean")); + parameters.put("wolf", new FeatureParameter<Boolean>("wolf", "Hide Wolves", "Hide Wolves", true, "boolean")); + parameters.put("rabbit", new FeatureParameter<Boolean>("rabbit", "Hide Rabbits", "Hide Rabbits", true, "boolean")); + } + + + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + @Override + public void onEntityRenderPre(RenderLivingEvent.Pre renderPlayerEvent) { + if (!isEnabled()) return; + if (!skyblockStatus.isOnDungeon()) return; + if (skyblockStatus.getContext() == null) return; + if (skyblockStatus.getContext().getBossfightProcessor() == null) return; + if (!(skyblockStatus.getContext().getBossfightProcessor() instanceof BossfightProcessorThorn)) return; + + if (renderPlayerEvent.entity instanceof EntitySheep && this.<Boolean>getParameter("sheep").getValue()) { + renderPlayerEvent.setCanceled(true); + } else if (renderPlayerEvent.entity instanceof EntityCow && this.<Boolean>getParameter("cow").getValue() ) { + renderPlayerEvent.setCanceled(true); + } else if (renderPlayerEvent.entity instanceof EntityChicken && this.<Boolean>getParameter("chicken").getValue()) { + renderPlayerEvent.setCanceled(true); + } else if (renderPlayerEvent.entity instanceof EntityWolf && this.<Boolean>getParameter("wolf").getValue()) { + renderPlayerEvent.setCanceled(true); + } else if (renderPlayerEvent.entity instanceof EntityRabbit && this.<Boolean>getParameter("rabbit").getValue()) { + renderPlayerEvent.setCanceled(true); + } + } + + @Override + public void onEntityRenderPost(RenderLivingEvent.Post renderPlayerEvent) { + + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureTerracotaTimer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureTerracotaTimer.java new file mode 100644 index 00000000..a581ad0f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureTerracotaTimer.java @@ -0,0 +1,77 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessorSadan; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.entity.boss.BossStatus; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureTerracotaTimer extends TextHUDFeature { + public FeatureTerracotaTimer() { + super("Bossfight.Floor 6", "Display Terracotta phase timer", "Displays Terracotta phase timer", "bossfight.terracota", true, getFontRenderer().getStringWidth("Terracottas: 1m 99s"), getFontRenderer().FONT_HEIGHT); + this.setEnabled(true); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("time", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + private static final List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Terracottas","title")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("1m 99s","time")); + } + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon() && skyblockStatus.getContext() != null && skyblockStatus.getContext().getBossfightProcessor() instanceof BossfightProcessorSadan && + "fight-1".equalsIgnoreCase(skyblockStatus.getContext().getBossfightProcessor().getCurrentPhase()); + } + + @Override + public List<String> getUsedTextStyle() { + return Arrays.asList("title", "separator", "number", "unit"); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public List<StyledText> getText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("Terracottas","title")); + actualBit.add(new StyledText(": ","separator")); + actualBit.add(new StyledText(TextUtils.formatTime((long) (BossStatus.healthScale * 1000 * 60 * 1.5)),"time")); + return actualBit; + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureThornBearPercentage.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureThornBearPercentage.java new file mode 100644 index 00000000..c9249df9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureThornBearPercentage.java @@ -0,0 +1,78 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessorThorn; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureThornBearPercentage extends TextHUDFeature { + public FeatureThornBearPercentage() { + super("Bossfight.Floor 4", "Display Spirit Bear Summon Percentage", "Displays spirit bear summon percentage in hud", "bossfight.spiritbear", true, getFontRenderer().getStringWidth("Spirit Bear: 100%"), getFontRenderer().FONT_HEIGHT); + this.setEnabled(true); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("number", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("unit", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + private static final java.util.List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Spirit Bear","title")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("50","number")); + dummyText.add(new StyledText("%","unit")); + } + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon() && skyblockStatus.getContext() != null && skyblockStatus.getContext().getBossfightProcessor() instanceof BossfightProcessorThorn; + } + + @Override + public java.util.List<String> getUsedTextStyle() { + return Arrays.asList("title", "separator", "number", "unit"); + } + + @Override + public java.util.List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public java.util.List<StyledText> getText() { + int percentage = (int) (((BossfightProcessorThorn) skyblockStatus.getContext().getBossfightProcessor()).calculatePercentage() * 100); + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("Spirit Bear","title")); + actualBit.add(new StyledText(": ","separator")); + actualBit.add(new StyledText(percentage+"","number")); + actualBit.add(new StyledText("%","unit")); + return actualBit; + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureThornSpiritBowTimer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureThornSpiritBowTimer.java new file mode 100644 index 00000000..c6470692 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureThornSpiritBowTimer.java @@ -0,0 +1,110 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss; + +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.ChatListener; +import kr.syeyoung.dungeonsguide.features.listener.TitleListener; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessorThorn; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.network.play.server.S45PacketTitle; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureThornSpiritBowTimer extends TextHUDFeature implements ChatListener, TitleListener { + public FeatureThornSpiritBowTimer() { + super("Bossfight.Floor 4", "Display Spirit bow timer", "Displays how long until spirit bow gets destroyed", "bossfight.spiritbowdisplay", false, getFontRenderer().getStringWidth("Spirit Bow Destruction: 2m 00s"), getFontRenderer().FONT_HEIGHT); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("time", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + private static final List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Spirit Bow Destruction","title")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("1s","time")); + } + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon() && skyblockStatus.getContext() != null && skyblockStatus.getContext().getBossfightProcessor() instanceof BossfightProcessorThorn && time > System.currentTimeMillis(); + } + + @Override + public List<String> getUsedTextStyle() { + return Arrays.asList("title", "separator", "time"); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public List<StyledText> getText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("Spirit Bow Destruction","title")); + actualBit.add(new StyledText(": ","separator")); + actualBit.add(new StyledText(TextUtils.formatTime(time - System.currentTimeMillis()),"time")); + return actualBit; + } + private long time = 0; + + @Override + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + if (!(skyblockStatus.isOnDungeon() && skyblockStatus.getContext() != null && skyblockStatus.getContext().getBossfightProcessor() instanceof BossfightProcessorThorn)) return; + String text = clientChatReceivedEvent.message.getFormattedText(); + if (text.equals("§r§a§lThe §r§5§lSpirit Bow §r§a§lhas dropped!§r")) { + time = System.currentTimeMillis() + 16000; + } else if (text.startsWith("§r§c[BOSS] Thorn§r§f: ")) { + if (text.contains("another wound") + || text.contains("My energy, it goes away") + || text.contains("dizzy") + || text.contains("a delicate feeling")) { + time = 0; + } + } else if (text.startsWith("§r§b[CROWD]")) { + if (text.contains("That wasn't fair!!!") || text.contains("how to damage") || text.contains("Cheaters!") || text.contains("BOOOO")) { + time = 0; + } else if (text.contains("missing easy shots like that") || text.contains("missed the shot!") || text.contains("Keep dodging") || text.contains("no thumbs") || text.contains("can't aim")) { + time = 0; + } + } else if (text.equals("§r§cThe §r§5Spirit Bow§r§c disintegrates as you fire off the shot!§r")) { + time = 0; + } + } + + @Override + public void onTitle(S45PacketTitle renderPlayerEvent) { + if (!(skyblockStatus.isOnDungeon() && skyblockStatus.getContext() != null && skyblockStatus.getContext().getBossfightProcessor() instanceof BossfightProcessorThorn)) return; + if (renderPlayerEvent.getMessage().getFormattedText().contains("picked up")) { + time = System.currentTimeMillis() + 21000; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureWarningOnPortal.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureWarningOnPortal.java new file mode 100644 index 00000000..555c982d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/FeatureWarningOnPortal.java @@ -0,0 +1,204 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss; + +import com.google.common.base.Supplier; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator; +import kr.syeyoung.dungeonsguide.config.guiconfig.MFeatureEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.MParameterEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.RootConfigPanel; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.impl.dungeon.FeatureDungeonScore; +import kr.syeyoung.dungeonsguide.features.text.PanelTextParameterConfig; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.StyledTextProvider; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.features.text.*; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.TextUtils; + +import java.util.*; + +public class FeatureWarningOnPortal extends SimpleFeature implements StyledTextProvider { + public FeatureWarningOnPortal() { + super("Dungeon.Blood Room", "Score Warning on Watcher portal", "Display warnings such as\n- 'NOT ALL ROOMS DISCOVERED'\n- 'NOT ALL ROOMS COMPLETED'\n- 'Expected Score: 304'\n- 'MISSING 3 CRYPTS'\non portal", "bossfight.warningonportal"); + this.parameters.put("textStyles", new FeatureParameter<List<TextStyle>>("textStyles", "", "", new ArrayList<TextStyle>(), "list_textStyle")); + getStyles().add(new TextStyle("warning", new AColor(255, 0,0,255), new AColor(255, 255,255,255), false)); + getStyles().add(new TextStyle("field_name", new AColor(255, 72,255,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("field_separator", new AColor(204, 204,204,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("field_value", new AColor(255, 255,0,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("field_etc", new AColor(204, 204,204,255), new AColor(0, 0,0,0), false)); + } + + + private static final List<StyledText> dummyText = new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("!!!WARNING!!! <- text changes in boss-room\n", "warning")); + + dummyText.add(new StyledText("Total Secrets","field_name")); + dummyText.add(new StyledText(": ","field_separator")); + dummyText.add(new StyledText("103/100 of 50","field_value")); + dummyText.add(new StyledText("(103% 41.2 Explorer)","field_etc")); + + + dummyText.add(new StyledText("Crypts","field_name")); + dummyText.add(new StyledText(": ","field_separator")); + dummyText.add(new StyledText("5/5\n","field_value")); + + + dummyText.add(new StyledText("Deaths","field_name")); + dummyText.add(new StyledText(": ","field_separator")); + dummyText.add(new StyledText("0\n","field_value")); + + dummyText.add(new StyledText("Score Estimate","field_name")); + dummyText.add(new StyledText(": ","field_separator")); + dummyText.add(new StyledText("1000 ","field_value")); + dummyText.add(new StyledText("(S++++)\n","field_etc")); + + + dummyText.add(new StyledText("Skill","field_name")); + dummyText.add(new StyledText(": ","field_separator")); + dummyText.add(new StyledText("100 ","field_value")); + dummyText.add(new StyledText("(0 Deaths: 0 pts)\n","field_etc")); + + dummyText.add(new StyledText("Explorer","field_name")); + dummyText.add(new StyledText(": ","field_separator")); + dummyText.add(new StyledText("100 ","field_value")); + dummyText.add(new StyledText("(100% + secrets)\n","field_etc")); + + dummyText.add(new StyledText("Time","field_name")); + dummyText.add(new StyledText(": ","field_separator")); + dummyText.add(new StyledText("100 ","field_value")); + dummyText.add(new StyledText("(-30m 29s)\n","field_etc")); + + dummyText.add(new StyledText("Bonus","field_name")); + dummyText.add(new StyledText(": ","field_separator")); + dummyText.add(new StyledText("5\n","field_value")); + } + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + @Override + public List<StyledText> getText() { + ArrayList<StyledText> texts = new ArrayList<StyledText>(); + DungeonContext context = skyblockStatus.getContext(); + FeatureDungeonScore.ScoreCalculation scoreCalculation = FeatureRegistry.DUNGEON_SCORE.calculateScore(); + + boolean failed = context.getDungeonRoomList().stream().anyMatch(a -> a.getCurrentState() == DungeonRoom.RoomState.FAILED); + if (context.getMapProcessor().getUndiscoveredRoom() > 0) { + texts.add(new StyledText("There are at least "+context.getMapProcessor().getUndiscoveredRoom()+" undiscovered rooms!\n", "warning")); + } else if (failed) { + texts.add(new StyledText("There is a failed puzzle room! Yikes!\n", "warning")); + } else if (!scoreCalculation.isFullyCleared()) { + texts.add(new StyledText("Some rooms are not fully cleared!\n", "warning")); + } else if (scoreCalculation.getTombs() < 5) { + texts.add(new StyledText("Only less than 5 crypts are blown up!\n", "warning")); + } else { + texts.add(new StyledText("\n", "warning")); + } + + texts.add(new StyledText("Total Secrets","field_name")); + texts.add(new StyledText(": ","field_separator")); + texts.add(new StyledText(scoreCalculation.getSecrets() +"/" + scoreCalculation.getEffectiveTotalSecrets()+" of "+scoreCalculation.getTotalSecrets(),"field_value")); + texts.add(new StyledText(" ("+(int)(scoreCalculation.getSecrets() / (float)scoreCalculation.getEffectiveTotalSecrets() * 100.0f)+"% "+(int)Math.ceil(scoreCalculation.getSecrets() / (float)scoreCalculation.getEffectiveTotalSecrets() * 40.0f)+" Explorer)\n","field_etc")); + + + texts.add(new StyledText("Crypts","field_name")); + texts.add(new StyledText(": ","field_separator")); + texts.add(new StyledText(scoreCalculation.getTombs() +"/5\n","field_value")); + + + texts.add(new StyledText("Deaths","field_name")); + texts.add(new StyledText(": ","field_separator")); + texts.add(new StyledText(scoreCalculation.getDeaths() + "\n","field_value")); + + int sum = scoreCalculation.getTime() + scoreCalculation.getExplorer() + scoreCalculation.getSkill() + scoreCalculation.getBonus(); + texts.add(new StyledText("Score Estimate","field_name")); + texts.add(new StyledText(": ","field_separator")); + texts.add(new StyledText(sum+" ","field_value")); + texts.add(new StyledText("("+FeatureRegistry.DUNGEON_SCORE.getLetter(sum)+")\n","field_etc")); + + + texts.add(new StyledText("Skill","field_name")); + texts.add(new StyledText(": ","field_separator")); + texts.add(new StyledText(scoreCalculation.getSkill()+" ","field_value")); + texts.add(new StyledText("("+scoreCalculation.getDeaths()+" Deaths: "+(scoreCalculation.getDeaths() * -2)+" pts)\n","field_etc")); + + texts.add(new StyledText("Explorer","field_name")); + texts.add(new StyledText(": ","field_separator")); + texts.add(new StyledText(scoreCalculation.getExplorer()+" ","field_value")); + texts.add(new StyledText("("+FeatureRegistry.DUNGEON_SCORE.getPercentage()+"% + secrets)\n","field_etc")); + + texts.add(new StyledText("Time","field_name")); + texts.add(new StyledText(": ","field_separator")); + texts.add(new StyledText(scoreCalculation.getTime()+" ","field_value")); + texts.add(new StyledText("("+ TextUtils.formatTime(FeatureRegistry.DUNGEON_SBTIME.getTimeElapsed())+")\n","field_etc")); + + texts.add(new StyledText("Bonus","field_name")); + texts.add(new StyledText(": ","field_separator")); + texts.add(new StyledText(scoreCalculation.getBonus()+"\n","field_value")); + + + return texts; + } + + public List<TextStyle> getStyles() { + return this.<List<TextStyle>>getParameter("textStyles").getValue(); + } + private Map<String, TextStyle> stylesMap; + public Map<String, TextStyle> getStylesMap() { + if (stylesMap == null) { + List<TextStyle> styles = getStyles(); + Map<String, TextStyle> res = new HashMap<String, TextStyle>(); + for (TextStyle ts : styles) { + res.put(ts.getGroupName(), ts); + } + stylesMap = res; + } + return stylesMap; + } + + + @Override + public String getEditRoute(RootConfigPanel rootConfigPanel) { + ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() { + @Override + public MPanel get() { + MFeatureEdit featureEdit = new MFeatureEdit(FeatureWarningOnPortal.this, rootConfigPanel); + featureEdit.addParameterEdit("textStyles", new PanelTextParameterConfig(FeatureWarningOnPortal.this)); + for (FeatureParameter parameter: getParameters()) { + if (parameter.getKey().equals("textStyles")) continue; + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeatureWarningOnPortal.this, parameter, rootConfigPanel)); + } + return featureEdit; + } + }); + return "base." + getKey() ; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/CorrectThePaneSolutionProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/CorrectThePaneSolutionProvider.java new file mode 100644 index 00000000..a4172158 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/CorrectThePaneSolutionProvider.java @@ -0,0 +1,53 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss.terminal; + +import net.minecraft.init.Blocks; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.Slot; +import net.minecraft.item.EnumDyeColor; +import net.minecraft.item.Item; + +import java.util.ArrayList; +import java.util.List; + +public class CorrectThePaneSolutionProvider implements TerminalSolutionProvider { + @Override + public TerminalSolution provideSolution(ContainerChest chest, List<Slot> clicked) { + TerminalSolution ts = new TerminalSolution(); + ts.setCurrSlots(new ArrayList<Slot>()); + for (Slot inventorySlot : chest.inventorySlots) { + if (inventorySlot.inventory != chest.getLowerChestInventory()) continue; + if (inventorySlot.getHasStack() && inventorySlot.getStack() != null) { + if (inventorySlot.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) && + inventorySlot.getStack().getItemDamage() == EnumDyeColor.RED.getMetadata()) { + ts.getCurrSlots().add(inventorySlot); + } + } + } + + + return ts; + } + + @Override + public boolean isApplicable(ContainerChest chest) { + return chest.getLowerChestInventory().getName().equals("Correct all the panes!"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/FeatureSimonSaysSolver.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/FeatureSimonSaysSolver.java new file mode 100644 index 00000000..bd90f724 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/FeatureSimonSaysSolver.java @@ -0,0 +1,115 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss.terminal; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.features.listener.InteractListener; +import kr.syeyoung.dungeonsguide.features.listener.TickListener; +import kr.syeyoung.dungeonsguide.features.listener.WorldRenderListener; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessorNecron; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +import java.awt.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +public class FeatureSimonSaysSolver extends SimpleFeature implements WorldRenderListener, TickListener, InteractListener { + public FeatureSimonSaysSolver() { + super("Solver.Floor 7+.Bossfight","Simon Says Solver","Solver for Simon says puzzle", "bossfight.simonsays2"); + } + + private final SkyblockStatus ss = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + private final List<BlockPos> orderbuild = new ArrayList<BlockPos>(); + private final LinkedList<BlockPos> orderclick = new LinkedList<BlockPos>(); + + @Override + public void drawWorld(float partialTicks) { + if (!isEnabled()) return; + DungeonContext dc = ss.getContext(); + if (dc == null) { + return; + } + if (!(dc.getBossfightProcessor() instanceof BossfightProcessorNecron)) return; + if (Minecraft.getMinecraft().thePlayer.getPosition().distanceSq(309,123,291) > 400) return; + + + if (orderclick.size() >= 1) + RenderUtils.highlightBlock(orderclick.get(0), new Color(0, 255 ,255, 100), partialTicks, false); + if (orderclick.size() >= 2) + RenderUtils.highlightBlock(orderclick.get(1), new Color(255, 170, 0, 100), partialTicks, false); + } + private boolean wasButton = false; + @Override + public void onTick() { + DungeonContext dc = ss.getContext(); + if (dc == null) { + wasButton = false; + return; + } + if (!(dc.getBossfightProcessor() instanceof BossfightProcessorNecron)) return; + + World w = dc.getWorld(); + + if (wasButton && w.getBlockState(new BlockPos(309, 123, 291)).getBlock() == Blocks.air) { + orderclick.clear(); + orderbuild.clear(); + wasButton = false; + } else if (!wasButton && w.getBlockState(new BlockPos(309, 123, 291)).getBlock() == Blocks.stone_button){ + orderclick.addAll(orderbuild); + wasButton = true; + } + + + if (!wasButton) { + for (BlockPos allInBox : BlockPos.getAllInBox(new BlockPos(310, 123, 291), new BlockPos(310, 120, 294))) { + if (w.getBlockState(allInBox).getBlock() == Blocks.sea_lantern && !orderbuild.contains(allInBox)) { + orderbuild.add(allInBox); + } + } + } + } + + @Override + public void onInteract(PlayerInteractEvent event) { + if (!isEnabled()) return; + + DungeonContext dc = ss.getContext(); + if (dc == null) return; + if (!(dc.getBossfightProcessor() instanceof BossfightProcessorNecron)) return; + if (event.action != PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) return; + World w = dc.getWorld(); + + BlockPos pos = event.pos.add(1,0,0); + if (120 <= pos.getY() && pos.getY() <= 123 && pos.getX() == 310 && 291 <= pos.getZ() && pos.getZ() <= 294) { + if (w.getBlockState(event.pos).getBlock() != Blocks.stone_button) return; + if (pos.equals(orderclick.peek())) { + orderclick.poll(); + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/FeatureTerminalSolvers.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/FeatureTerminalSolvers.java new file mode 100644 index 00000000..e6e03318 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/FeatureTerminalSolvers.java @@ -0,0 +1,154 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss.terminal; + +import kr.syeyoung.dungeonsguide.features.listener.*; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.features.listener.*; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.Slot; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import org.lwjgl.input.Mouse; + +import java.util.ArrayList; +import java.util.List; + +public class FeatureTerminalSolvers extends SimpleFeature implements GuiOpenListener, TickListener, GuiPostRenderListener, GuiClickListener, TooltipListener { + public FeatureTerminalSolvers() { + super("Solver.Floor 7+.Bossfight","F7 GUI Terminal Solver", "Solve f7 gui terminals. (color, startswith, order, navigate, correct panes)", "bossfight.terminals"); + } + + public static final List<TerminalSolutionProvider> solutionProviders = new ArrayList<TerminalSolutionProvider>(); + + static { + solutionProviders.add(new WhatStartsWithSolutionProvider()); + solutionProviders.add(new SelectAllColorSolutionProivider()); + solutionProviders.add(new SelectInOrderSolutionProvider()); + solutionProviders.add(new NavigateMazeSolutionProvider()); + solutionProviders.add(new CorrectThePaneSolutionProvider()); + } + + private TerminalSolutionProvider solutionProvider; + private TerminalSolution solution; + private final List<Slot> clicked = new ArrayList<Slot>(); + + @Override + public void onGuiOpen(GuiOpenEvent event) { + if (!isEnabled()) return; + solution = null; + solutionProvider = null; + clicked.clear(); + if (event.gui instanceof GuiChest) { + ContainerChest cc = (ContainerChest) ((GuiChest) event.gui).inventorySlots; + for (TerminalSolutionProvider solutionProvider : solutionProviders) { + if (solutionProvider.isApplicable(cc)) { + solution = solutionProvider.provideSolution(cc, clicked); + this.solutionProvider = solutionProvider; + } + } + } + } + + @Override + public void onTick() { + if (!isEnabled()) return; + if (solutionProvider == null) return; + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChest)) { + solution = null; + solutionProvider = null; + clicked.clear(); + return; + } + ContainerChest cc = (ContainerChest) ((GuiChest) Minecraft.getMinecraft().currentScreen).inventorySlots; + + solution = solutionProvider.provideSolution(cc, clicked); + } + + @Override + public void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered) { + if (!isEnabled()) return; + if (solutionProvider == null) return; + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChest)) { + solution = null; + solutionProvider = null; + clicked.clear(); + return; + } + + if (solution != null) { + int i = 222; + int j = i - 108; + int ySize = j + (((ContainerChest)(((GuiChest) Minecraft.getMinecraft().currentScreen).inventorySlots)).getLowerChestInventory().getSizeInventory() / 9) * 18; + int left = (rendered.gui.width - 176) / 2; + int top = (rendered.gui.height - ySize ) / 2; + GlStateManager.pushMatrix(); + GlStateManager.disableDepth(); + GlStateManager.disableLighting(); + GlStateManager.colorMask(true, true, true, false); + GlStateManager.translate(left, top, 0); + if (solution.getCurrSlots() != null) { + for (Slot currSlot : solution.getCurrSlots()) { + int x = currSlot.xDisplayPosition; + int y = currSlot.yDisplayPosition; + Gui.drawRect(x, y, x + 16, y + 16, 0x7700FFFF); + } + } + if (solution.getNextSlots() != null) { + for (Slot nextSlot : solution.getNextSlots()) { + int x = nextSlot.xDisplayPosition; + int y = nextSlot.yDisplayPosition; + Gui.drawRect(x, y, x + 16, y + 16, 0x77FFFF00); + } + } + GlStateManager.colorMask(true, true, true, true); + GlStateManager.popMatrix(); + } + GlStateManager.enableBlend(); + GlStateManager.enableLighting(); + } + + @Override + public void onMouseInput(GuiScreenEvent.MouseInputEvent.Pre mouseInputEvent) { + if (!isEnabled()) return; + if (Mouse.getEventButton() == -1) return; + if (solutionProvider == null) return; + if (solution == null) return; + if (solution.getCurrSlots() == null) { + return; + } + Slot s = ((GuiChest) Minecraft.getMinecraft().currentScreen).getSlotUnderMouse(); + if (solution.getCurrSlots().contains(s)) { + clicked.add(s); + return; + } + } + + @Override + public void onTooltip(ItemTooltipEvent event) { + if (!isEnabled()) return; + if (solutionProvider == null) return; + event.toolTip.clear(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/NavigateMazeSolutionProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/NavigateMazeSolutionProvider.java new file mode 100644 index 00000000..78a64733 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/NavigateMazeSolutionProvider.java @@ -0,0 +1,144 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss.terminal; + +import net.minecraft.init.Blocks; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.Slot; +import net.minecraft.item.EnumDyeColor; +import net.minecraft.item.Item; + +import java.util.ArrayList; +import java.util.List; + +public class NavigateMazeSolutionProvider implements TerminalSolutionProvider { + @Override + public TerminalSolution provideSolution(ContainerChest chest, List<Slot> clicked) { + TerminalSolution ts = new TerminalSolution(); + ts.setCurrSlots(new ArrayList<Slot>()); + Slot solution = null; + for (Slot inventorySlot : chest.inventorySlots) { + if (inventorySlot.inventory != chest.getLowerChestInventory()) continue; + if (inventorySlot.getHasStack() && inventorySlot.getStack() != null) { + if (inventorySlot.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) && + inventorySlot.getStack().getItemDamage() == EnumDyeColor.WHITE.getMetadata()) { + int x = inventorySlot.slotNumber % 9; + int y = inventorySlot.slotNumber / 9; + + if (x > 0) { + Slot toChk = chest.inventorySlots.get(y * 9 + x - 1); + + if (toChk.getHasStack() && toChk.getStack() != null && + toChk.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) && + toChk.getStack().getItemDamage() == EnumDyeColor.LIME.getMetadata()) { + solution = inventorySlot; + break; + } + } + if (x < 8) { + Slot toChk = chest.inventorySlots.get(y * 9 + x + 1); + + if (toChk.getHasStack() && toChk.getStack() != null && + toChk.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) && + toChk.getStack().getItemDamage() == EnumDyeColor.LIME.getMetadata()) { + solution = inventorySlot; + break; + } + } + if (y > 0) { + Slot toChk = chest.inventorySlots.get((y-1) * 9 + x); + + if (toChk.getHasStack() && toChk.getStack() != null && + toChk.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) && + toChk.getStack().getItemDamage() == EnumDyeColor.LIME.getMetadata()) { + solution = inventorySlot; + break; + } + } + if (y < chest.getLowerChestInventory().getSizeInventory() / 9 - 1) { + Slot toChk = chest.inventorySlots.get((y+1) * 9 + x); + + if (toChk.getHasStack() && toChk.getStack() != null && + toChk.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) && + toChk.getStack().getItemDamage() == EnumDyeColor.LIME.getMetadata()) { + solution = inventorySlot; + break; + } + } + } + } + } + + if (solution == null) return null; + ts.getCurrSlots().add(solution); + ts.setNextSlots(new ArrayList<Slot>()); + { + int x = solution.slotNumber % 9; + int y = solution.slotNumber / 9; + + if (x > 0) { + Slot toChk = chest.inventorySlots.get(y * 9 + x - 1); + + if (toChk.getHasStack() && toChk.getStack() != null && + toChk.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) && + toChk.getStack().getItemDamage() == EnumDyeColor.WHITE.getMetadata()) { + ts.getNextSlots().add(toChk); + return ts; + } + } + if (x < 8) { + Slot toChk = chest.inventorySlots.get(y * 9 + x + 1); + + if (toChk.getHasStack() && toChk.getStack() != null && + toChk.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) && + toChk.getStack().getItemDamage() == EnumDyeColor.WHITE.getMetadata()) { + ts.getNextSlots().add(toChk); + return ts; + } + } + if (y > 0) { + Slot toChk = chest.inventorySlots.get((y-1) * 9 + x); + + if (toChk.getHasStack() && toChk.getStack() != null && + toChk.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) && + toChk.getStack().getItemDamage() == EnumDyeColor.WHITE.getMetadata()) { + ts.getNextSlots().add(toChk); + return ts; + } + } + if (y < chest.getLowerChestInventory().getSizeInventory() / 9 - 1) { + Slot toChk = chest.inventorySlots.get((y+1) * 9 + x); + + if (toChk.getHasStack() && toChk.getStack() != null && + toChk.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) && + toChk.getStack().getItemDamage() == EnumDyeColor.WHITE.getMetadata()) { + ts.getNextSlots().add(toChk); + return ts; + } + } + } + + return ts; + } + + @Override + public boolean isApplicable(ContainerChest chest) { + return chest.getLowerChestInventory().getName().equals("Navigate the maze!"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/SelectAllColorSolutionProivider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/SelectAllColorSolutionProivider.java new file mode 100644 index 00000000..36a1834f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/SelectAllColorSolutionProivider.java @@ -0,0 +1,60 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss.terminal; + +import net.minecraft.init.Items; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.Slot; +import net.minecraft.item.EnumDyeColor; + +import java.util.ArrayList; +import java.util.List; + +public class SelectAllColorSolutionProivider implements TerminalSolutionProvider { + @Override + public TerminalSolution provideSolution(ContainerChest chest, List<Slot> clicked) { + TerminalSolution ts = new TerminalSolution(); + ts.setCurrSlots(new ArrayList<Slot>()); + String name = chest.getLowerChestInventory().getName(); + EnumDyeColor edc = null; + for (EnumDyeColor edc2 : EnumDyeColor.values()) { + if (name.contains(edc2.getName().toUpperCase().replace("_"," "))) { + edc = edc2; + break; + } + } + if (edc == null) return null; + + for (Slot inventorySlot : chest.inventorySlots) { + if (inventorySlot.inventory != chest.getLowerChestInventory()) continue; + if (inventorySlot.getHasStack() && inventorySlot.getStack() != null && !inventorySlot.getStack().isItemEnchanted()) { + if (inventorySlot.getStack().getItem() != Items.dye && inventorySlot.getStack().getItemDamage() == edc.getMetadata()) + ts.getCurrSlots().add(inventorySlot); + else if (inventorySlot.getStack().getItem() == Items.dye && inventorySlot.getStack().getItemDamage() == edc.getDyeDamage()) + ts.getCurrSlots().add(inventorySlot); + } + } + return ts; + } + + @Override + public boolean isApplicable(ContainerChest chest) { + return chest.getLowerChestInventory().getName().startsWith("Select all the "); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/SelectInOrderSolutionProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/SelectInOrderSolutionProvider.java new file mode 100644 index 00000000..7295a899 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/SelectInOrderSolutionProvider.java @@ -0,0 +1,72 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss.terminal; + +import net.minecraft.init.Blocks; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.Slot; +import net.minecraft.item.EnumDyeColor; +import net.minecraft.item.Item; + +import java.util.ArrayList; +import java.util.List; + +public class SelectInOrderSolutionProvider implements TerminalSolutionProvider { + @Override + public TerminalSolution provideSolution(ContainerChest chest, List<Slot> clicked) { + TerminalSolution ts = new TerminalSolution(); + ts.setCurrSlots(new ArrayList<Slot>()); + int lowest = 1000; + Slot slotLowest = null; + for (Slot inventorySlot : chest.inventorySlots) { + if (inventorySlot.inventory != chest.getLowerChestInventory()) continue; + if (inventorySlot.getHasStack() && inventorySlot.getStack() != null && inventorySlot.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) + && inventorySlot.getStack().getItemDamage() == EnumDyeColor.RED.getMetadata()) { + if (inventorySlot.getStack().stackSize < lowest) { + lowest = inventorySlot.getStack().stackSize; + slotLowest = inventorySlot; + } + } + } + if (slotLowest != null) + ts.getCurrSlots().add(slotLowest); + + Slot next = null; + for (Slot inventorySlot : chest.inventorySlots) { + if (inventorySlot.inventory != chest.getLowerChestInventory()) continue; + if (inventorySlot.getHasStack() && inventorySlot.getStack() != null && inventorySlot.getStack().getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) + && inventorySlot.getStack().getItemDamage() == EnumDyeColor.RED.getMetadata()) { + if (inventorySlot.getStack().stackSize == lowest + 1) { + next = inventorySlot; + } + } + } + if (next != null) { + ts.setNextSlots(new ArrayList<Slot>()); + ts.getNextSlots().add(next); + } + + return ts; + } + + @Override + public boolean isApplicable(ContainerChest chest) { + return chest.getLowerChestInventory().getName().equals("Click in order!"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/TerminalSolution.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/TerminalSolution.java new file mode 100644 index 00000000..a3f3f558 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/TerminalSolution.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss.terminal; + +import lombok.Data; +import net.minecraft.inventory.Slot; + +import java.util.List; + +@Data +public class TerminalSolution { + private List<Slot> currSlots; + private List<Slot> nextSlots; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/TerminalSolutionProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/TerminalSolutionProvider.java new file mode 100644 index 00000000..b04b5094 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/TerminalSolutionProvider.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss.terminal; + +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.Slot; + +import java.util.List; + +public interface TerminalSolutionProvider { + TerminalSolution provideSolution(ContainerChest chest, List<Slot> clicked); + boolean isApplicable(ContainerChest chest); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/WhatStartsWithSolutionProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/WhatStartsWithSolutionProvider.java new file mode 100644 index 00000000..dc9828fb --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/boss/terminal/WhatStartsWithSolutionProvider.java @@ -0,0 +1,50 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.boss.terminal; + +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.Slot; + +import java.util.ArrayList; +import java.util.List; + +public class WhatStartsWithSolutionProvider implements TerminalSolutionProvider{ + @Override + public TerminalSolution provideSolution(ContainerChest chest, List<Slot> clicked) { + String that = chest.getLowerChestInventory().getName().replace("What starts with: '", "").replace("'?", "").trim().toLowerCase(); + + TerminalSolution ts = new TerminalSolution(); + ts.setCurrSlots(new ArrayList<Slot>()); + for (Slot inventorySlot : chest.inventorySlots) { + if (inventorySlot.inventory != chest.getLowerChestInventory()) continue; + if (inventorySlot.getHasStack() && inventorySlot.getStack() != null && !inventorySlot.getStack().isItemEnchanted() ) { + String name = TextUtils.stripColor(inventorySlot.getStack().getDisplayName()).toLowerCase(); + if (name.startsWith(that)) + ts.getCurrSlots().add(inventorySlot); + } + } + return ts; + } + + @Override + public boolean isApplicable(ContainerChest chest) { + return chest.getLowerChestInventory().getName().startsWith("What starts with: '"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/cosmetics/FeatureNicknameColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/cosmetics/FeatureNicknameColor.java new file mode 100644 index 00000000..89d80ca5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/cosmetics/FeatureNicknameColor.java @@ -0,0 +1,49 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.cosmetics; + +import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator; +import kr.syeyoung.dungeonsguide.config.guiconfig.RootConfigPanel; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +public class FeatureNicknameColor extends SimpleFeature { + public FeatureNicknameColor() { + super("Cosmetics", "Nickname Color", "Click on Edit to choose nickname color cosmetic", "cosmetic.nickname"); + this.parameters.put("dummy", new FeatureParameter("dummy", "dummy", "dummy", "dummy", "string")); + } + + @Override + public String getEditRoute(RootConfigPanel rootConfigPanel) { + ConfigPanelCreator.map.put("base." + getKey() , () -> new PrefixSelectorGUI("color", new String[] { + "§9Party §8> §r§a[RANK§6+§a] %prefix%%name%§f: TEST", + "§2Guild > §r§a[RANK§6+§a] %prefix%%name% §3[Vet]§f: TEST", + "§dTo §r§r§a[RANK§r§6+§r§a] %prefix%%name%§r§7: §r§7TEST§r", + "§dFrom §r§r§a[RANK§r§6+§r§a] %prefix%%name%§r§7: §r§7TEST§r", + "§r§b[RANK§c+§b] %prefix%%name%§f: TEST", + "§r§bCo-op > §r§a[RANK§6+§a] %prefix%%name%§f: §rTEST§r" + }, a -> (a.replace("&", "§")+"Color "+(a.replace("&", "§").equals("§z") ? "(Rainbow on sba)" : "")))); + return "base." + getKey(); + } + + @Override + public boolean isDisyllable() { + return false; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/cosmetics/FeatureNicknamePrefix.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/cosmetics/FeatureNicknamePrefix.java new file mode 100644 index 00000000..78a9c1c8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/cosmetics/FeatureNicknamePrefix.java @@ -0,0 +1,49 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.cosmetics; + +import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator; +import kr.syeyoung.dungeonsguide.config.guiconfig.RootConfigPanel; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +public class FeatureNicknamePrefix extends SimpleFeature { + public FeatureNicknamePrefix() { + super("Cosmetics", "Nickname Prefix", "Click on Edit to choose prefix cosmetic", "cosmetic.prefix"); + this.parameters.put("dummy", new FeatureParameter("dummy", "dummy", "dummy", "dummy", "string")); + } + + @Override + public String getEditRoute(RootConfigPanel rootConfigPanel) { + ConfigPanelCreator.map.put("base." + getKey() , () -> new PrefixSelectorGUI("prefix", new String[] { + "§9Party §8> §r%prefix% §a[RANK§6+§a] %name%§f: TEST", + "§2Guild > §r%prefix% §a[RANK§6+§a] %name% §3[Vet]§f: TEST", + "§dTo §r%prefix% §r§a[RANK§r§6+§r§a] %name%§r§7: §r§7TEST§r", + "§dFrom §r%prefix% §r§a[RANK§r§6+§r§a] %name%§r§7: §r§7TEST§r", + "§r%prefix% §b[RANK§c+§b] %name%§f: TEST", + "§r§bCo-op > §r%prefix% §a[RANK§6+§a] %name%§f: §rTEST§r" + }, a->a.replace("&", "§"))); + return "base." + getKey(); + } + + @Override + public boolean isDisyllable() { + return false; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/cosmetics/PrefixSelectorGUI.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/cosmetics/PrefixSelectorGUI.java new file mode 100644 index 00000000..4750831e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/cosmetics/PrefixSelectorGUI.java @@ -0,0 +1,188 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.cosmetics; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.cosmetics.ActiveCosmetic; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticData; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticsManager; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.*; +import java.util.List; +import java.util.function.Function; + +public class PrefixSelectorGUI extends MPanel { + private String cosmeticType; + private Function<String, String> optionTransformer; + + public PrefixSelectorGUI(String cosmeticType, String[] previews, Function<String, String> optionTransformer) { + this.cosmeticType = cosmeticType; + this.previews = previews; + this.optionTransformer = optionTransformer; + CosmeticsManager cosmeticsManager = DungeonsGuide.getDungeonsGuide().getCosmeticsManager(); + List<ActiveCosmetic> activeCosmeticList = cosmeticsManager.getActiveCosmeticByPlayer().computeIfAbsent(Minecraft.getMinecraft().thePlayer.getGameProfile().getId(), (a) -> new ArrayList<>()); + for (ActiveCosmetic activeCosmetic : activeCosmeticList) { + CosmeticData cosmeticData = cosmeticsManager.getCosmeticDataMap().get(activeCosmetic.getCosmeticData()); + if (cosmeticData != null && cosmeticData.getCosmeticType().equals(cosmeticType)) { + selected = cosmeticData; + return; + } + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + private CosmeticData selected; + // §9Party §8> §a[VIP§6+§a] syeyoung§f: ty + // §2Guild > §a[VIP§6+§a] syeyoung §3[Vet]§f + // §dTo §r§a[VIP§r§6+§r§a] SlashSlayer§r§7: §r§7what§r + // §dFrom §r§a[VIP§r§6+§r§a] SlashSlayer§r§7: §r§7?§r + // §7Rock_Bird§7§r§7: SELLING 30 DIAMOD BLOCK /p me§r + // §b[MVP§c+§b] Probutnoobgamer§f: quitting skyblock! highe + // §r§bCo-op > §a[VIP§6+§a] syeyoung§f: §rwhat§r + String[] previews; + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + CosmeticsManager cosmeticsManager = DungeonsGuide.getDungeonsGuide().getCosmeticsManager(); + + List<ActiveCosmetic> activeCosmeticList2 = cosmeticsManager.getActiveCosmeticByPlayer().get(Minecraft.getMinecraft().thePlayer.getGameProfile().getId()); + Set<UUID> activeCosmeticList = new HashSet<>(); + if (activeCosmeticList2 !=null) { + for (ActiveCosmetic activeCosmetic : activeCosmeticList2) { + activeCosmeticList.add(activeCosmetic.getCosmeticData()); + } + } + + + + GlStateManager.translate(0,2,0); + Gui.drawRect(0,0,getBounds().width, getBounds().height-2, 0xFF444444); + Gui.drawRect(5,5,265, getBounds().height-7, 0xFF222222); + Gui.drawRect(6,17,264, getBounds().height-8, 0xFF555555); + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Preview", (270 - fr.getStringWidth("Preview")) / 2, 7, 0xFFFFFFFF); + + { + String prefix = selected != null ? selected.getData() : "[DG]"; + GlStateManager.pushMatrix(); + GlStateManager.translate(6,17,0); + for (int i = 0; i < previews.length; i++) { + fr.drawString(previews[i].replace("%name%", Minecraft.getMinecraft().getSession().getUsername()).replace("%prefix%", prefix.replace("&", "§")), 0, i*fr.FONT_HEIGHT, -1); + } + GlStateManager.popMatrix(); + } + { + GlStateManager.pushMatrix(); + GlStateManager.translate(270,17,0); + int relX = relMousex0 - 270, relY = relMousey0 - 19; + int cnt = 0; + for (CosmeticData value : cosmeticsManager.getCosmeticDataMap().values()) { + if (value.getCosmeticType().equals(cosmeticType)) { + if (!cosmeticsManager.getPerms().contains(value.getReqPerm()) && value.getReqPerm().startsWith("invis_")) continue; + Gui.drawRect(0,0,220, fr.FONT_HEIGHT+3, 0xFF222222); + Gui.drawRect(1,1, 219, fr.FONT_HEIGHT+2, 0xFF555555); + Gui.drawRect(120,1,160, fr.FONT_HEIGHT+2, new Rectangle(120,cnt * (fr.FONT_HEIGHT+4) + 2,40,fr.FONT_HEIGHT+1).contains(relX, relY) ? 0xFF859DF0 : 0xFF7289da); + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(optionTransformer.apply(value.getData()), 2, 2, -1); + fr.drawString("TEST", (280-fr.getStringWidth("TEST"))/2, 2, -1); + + if (cosmeticsManager.getPerms().contains(value.getReqPerm())) { + Gui.drawRect(161,1,219, fr.FONT_HEIGHT+2, new Rectangle(161,cnt * (fr.FONT_HEIGHT+4) + 2,58,fr.FONT_HEIGHT+1).contains(relX, relY) ? 0xFF859DF0 : 0xFF7289da); + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + if (activeCosmeticList.contains(value.getId())) { + fr.drawString("UNSELECT", (381 - fr.getStringWidth("UNSELECT")) / 2, 2, -1); + } else { + fr.drawString("SELECT", (381 - fr.getStringWidth("SELECT")) / 2, 2, -1); + } + } else { + Gui.drawRect(161,1,219, fr.FONT_HEIGHT+2, 0xFFFF3333); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Locked", (381 - fr.getStringWidth("Locked")) / 2, 2, -1); + } + GlStateManager.translate(0,fr.FONT_HEIGHT+4, 0); + + cnt++; + } + } + GlStateManager.popMatrix(); + } + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + CosmeticsManager cosmeticsManager = DungeonsGuide.getDungeonsGuide().getCosmeticsManager(); + + int relX = relMouseX - 270, relY = relMouseY - 19; + int cnt = 0; + + List<ActiveCosmetic> activeCosmeticList = cosmeticsManager.getActiveCosmeticByPlayer().computeIfAbsent(Minecraft.getMinecraft().thePlayer.getGameProfile().getId(), (a) -> new ArrayList<>()); + + for (CosmeticData value : cosmeticsManager.getCosmeticDataMap().values()) { + if (value.getCosmeticType().equals(cosmeticType)) { + if (!cosmeticsManager.getPerms().contains(value.getReqPerm()) && value.getReqPerm().startsWith("invis_")) continue; + if (new Rectangle(120,cnt * (fr.FONT_HEIGHT+4) + 2,40,fr.FONT_HEIGHT+1).contains(relX, relY)) { + selected = value; + return; + } + try { + if (new Rectangle(161, cnt * (fr.FONT_HEIGHT + 4) + 2, 58, fr.FONT_HEIGHT + 1).contains(relX, relY) && cosmeticsManager.getPerms().contains(value.getReqPerm())) { + for (ActiveCosmetic activeCosmetic : activeCosmeticList) { + if (activeCosmetic.getCosmeticData().equals(value.getId())) { + cosmeticsManager.removeCosmetic(activeCosmetic); + return; + } + } + cosmeticsManager.setCosmetic(value); + selected = value; + } + } catch (Exception e) { + e.printStackTrace(); + } + + cnt++; + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/ImageTexture.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/ImageTexture.java new file mode 100644 index 00000000..730fe355 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/ImageTexture.java @@ -0,0 +1,118 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer; + + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.ResourceLocation; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Iterator; + +@Data +public class ImageTexture { + private String url; + private BufferedImage image; + private DynamicTexture previewTexture; + private ResourceLocation resourceLocation; + + private int width; + private int height; + private int frames; + private int size; + + @Getter @Setter + private int lastFrame = 0; + + public void buildGLThings() { + previewTexture = new DynamicTexture(image); + resourceLocation = Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation("dgurl/"+url, previewTexture); + } + + public ImageTexture(String url) throws IOException { + this.url = url; + + URL urlObj = new URL(url); + HttpURLConnection huc = (HttpURLConnection) urlObj.openConnection(); + huc.addRequestProperty("User-Agent", "DungeonsGuideMod (dungeons.guide, 1.0)"); + ImageInputStream imageInputStream = ImageIO.createImageInputStream(huc.getInputStream()); + Iterator<ImageReader> readers = ImageIO.getImageReaders(imageInputStream); + if(!readers.hasNext()) throw new IOException("No image reader what" + url); + ImageReader reader = readers.next(); + reader.setInput(imageInputStream); + frames = reader.getNumImages(true); + BufferedImage dummyFrame = reader.read(0); + width = dummyFrame.getWidth(); height = dummyFrame.getHeight(); + + + image = new BufferedImage(width, height * frames, dummyFrame.getType()); + Graphics2D graphics2D = image.createGraphics(); + + for (int i = 0; i < frames; i++) { + BufferedImage bufferedImage = reader.read(i); + graphics2D.drawImage(bufferedImage, 0, i*height, null); + } + reader.dispose(); imageInputStream.close(); huc.disconnect(); + } + + public void drawFrame(int frame, int x, int y, int width, int height) { + if (getResourceLocation() == null) + buildGLThings(); + + TextureManager textureManager = Minecraft.getMinecraft().getTextureManager(); + textureManager.bindTexture(getResourceLocation()); + + GlStateManager.color(1, 1, 1, 1.0F); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer.pos((double)x, (double)(y + height), 0.0D) + .tex(0,((frame+1) * height)/ ((double)frames * height)).endVertex(); + worldrenderer.pos((double)(x + width), (double)(y + height), 0.0D) + .tex(1, ((frame+1) * height)/ ((double)frames * height)).endVertex(); + worldrenderer.pos((double)(x + width), (double)y, 0.0D) + .tex(1,(frame * height)/ ((double)frames * height)).endVertex(); + worldrenderer.pos((double)x, (double)y, 0.0D) + .tex(0, (frame * height) / ((double)frames * height)).endVertex(); + tessellator.draw(); + } + + public void drawFrameAndIncrement(int x, int y, int width, int height) { + drawFrame(lastFrame, x,y,width,height); + lastFrame++; + if (lastFrame >= frames) lastFrame = 0; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyInviteViewer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyInviteViewer.java new file mode 100644 index 00000000..ad40a91c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyInviteViewer.java @@ -0,0 +1,315 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.features.listener.*; +import kr.syeyoung.dungeonsguide.events.DiscordUserJoinRequestEvent; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.features.listener.*; +import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityJoinRequestReply; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraftforge.client.event.GuiScreenEvent; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.util.*; +import java.util.List; +import java.util.concurrent.*; + +public class PartyInviteViewer extends SimpleFeature implements GuiPostRenderListener, ScreenRenderListener, TickListener, GuiClickListener, DiscordUserJoinRequestListener { + public PartyInviteViewer() { + super("Discord", "Party Invite Viewer","Simply type /dg asktojoin or /dg atj to toggle whether ask-to-join would be presented as option on discord!\n\nRequires Discord RPC to be enabled", "discord.party_invite_viewer"); + } + + @Override + public boolean isDisyllable() { + return false; + } + + @Override + public void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered) { + renderRequests(true); + } + + @Override + public void drawScreen(float partialTicks) { + if (!isEnabled()) return; + try { + renderRequests(false); + } catch (Throwable t) { + t.printStackTrace(); + } + } + @Override + public void onTick() { + try { + List<PartyJoinRequest> partyJoinRequestList = new ArrayList<>(); + boolean isOnHypixel = DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnHypixel(); + for (PartyJoinRequest joinRequest:joinRequests) { + if (joinRequest.getTtl() != -1) { + joinRequest.setTtl(joinRequest.getTtl() - 1); + if (joinRequest.getTtl() == 0 || !isOnHypixel) { + partyJoinRequestList.add(joinRequest); + } + } else if (!isOnHypixel){ +// DiscordRPC.discordRespond(joinRequest.getDiscordUser().userId, DiscordRPC.DiscordReply.NO); + partyJoinRequestList.add(joinRequest); + } else if (joinRequest.getExpire() < System.currentTimeMillis()) { + partyJoinRequestList.add(joinRequest); + } + } + joinRequests.removeAll(partyJoinRequestList); + } catch (Throwable e) {e.printStackTrace();} + } + + + @Override + public void onMouseInput(GuiScreenEvent.MouseInputEvent.Pre mouseInputEvent) { + if (!isEnabled()) return; + int mouseX = Mouse.getX(); + int mouseY = Minecraft.getMinecraft().displayHeight - Mouse.getY() +3; + for (PartyJoinRequest joinRequest:joinRequests) { + if (joinRequest.getWholeRect() != null && joinRequest.getWholeRect().contains(mouseX, mouseY)) { + mouseInputEvent.setCanceled(true); + + if (Mouse.getEventButton() == -1) return; + + if (joinRequest.getReply() != null) { + joinRequests.remove(joinRequest); + return; + } + + if (!joinRequest.isInvite()) { + if (joinRequest.getAcceptRect().contains(mouseX, mouseY)) { + joinRequest.setReply(PartyJoinRequest.Reply.ACCEPT); + joinRequest.setTtl(60); + RichPresenceManager.INSTANCE.respond(joinRequest.getDiscordUser().id, EDiscordActivityJoinRequestReply.DiscordActivityJoinRequestReply_Yes); + return; + } + + if (joinRequest.getDenyRect().contains(mouseX, mouseY)) { + joinRequest.setReply(PartyJoinRequest.Reply.DENY); + joinRequest.setTtl(60); + RichPresenceManager.INSTANCE.respond(joinRequest.getDiscordUser().id, EDiscordActivityJoinRequestReply.DiscordActivityJoinRequestReply_No); + return; + } + + if (joinRequest.getIgnoreRect().contains(mouseX, mouseY)) { + joinRequest.setReply(PartyJoinRequest.Reply.IGNORE); + joinRequest.setTtl(60); + RichPresenceManager.INSTANCE.respond(joinRequest.getDiscordUser().id, EDiscordActivityJoinRequestReply.DiscordActivityJoinRequestReply_Ignore); + return; + } + } else { + if (joinRequest.getAcceptRect().contains(mouseX, mouseY)) { + joinRequest.setReply(PartyJoinRequest.Reply.ACCEPT); + joinRequest.setTtl(60); + RichPresenceManager.INSTANCE.accept(joinRequest.getDiscordUser().id); + return; + } + + if (joinRequest.getDenyRect().contains(mouseX, mouseY)) { + joinRequest.setReply(PartyJoinRequest.Reply.DENY); + joinRequest.setTtl(60); + return; + } + } + + return; + } + } + } + + + + public CopyOnWriteArrayList<PartyJoinRequest> joinRequests = new CopyOnWriteArrayList<>(); + + ExecutorService executorService = Executors.newFixedThreadPool(3); + public Map<String, Future<ImageTexture>> futureMap = new HashMap<>(); + public Map<String, ImageTexture> imageMap = new HashMap<>(); + + public Future<ImageTexture> loadImage(String url) { + if (imageMap.containsKey(url)) return CompletableFuture.completedFuture(imageMap.get(url)); + if (futureMap.containsKey(url)) return futureMap.get(url); + Future<ImageTexture> future = executorService.submit(() -> { + try { + ImageTexture imageTexture = new ImageTexture(url); + imageMap.put(url, imageTexture); + return imageTexture; + } catch (Exception e) { + throw e; + } + }); + futureMap.put(url,future); + return future; + } + + + public void renderRequests(boolean hover) { + try { + GlStateManager.pushMatrix(); + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + GlStateManager.scale(1.0 / sr.getScaleFactor(), 1.0 / sr.getScaleFactor(), 1.0); + int height = 90; + int gap = 5; + int x = 5; + int y = 5; + for (PartyJoinRequest partyJoinRequest : joinRequests) { + renderRequest(partyJoinRequest, x, y, 350,height, hover); + y += height + gap; + } + GlStateManager.popMatrix(); + GlStateManager.enableBlend(); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + + public void renderRequest(PartyJoinRequest partyJoinRequest, int x, int y, int width, int height, boolean hover) { + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + + int mouseX = Mouse.getX(); + int mouseY = Minecraft.getMinecraft().displayHeight - Mouse.getY() +3; + + partyJoinRequest.getWholeRect().setBounds(x,y,width,height); + + + GlStateManager.pushMatrix(); + GlStateManager.translate(x,y,0); + + Gui.drawRect(0, 0,width,height, 0xFF23272a); + Gui.drawRect(2, 2, width-2, height-2, 0XFF2c2f33); + { + String avatar = "https://cdn.discordapp.com/avatars/"+Long.toUnsignedString(partyJoinRequest.getDiscordUser().id.longValue())+"/"+partyJoinRequest.getAvatar()+"."+(partyJoinRequest.getAvatar().startsWith("a_") ? "gif":"png"); + Future<ImageTexture> loadedImageFuture = loadImage(avatar); + ImageTexture loadedImage = null; + if (loadedImageFuture.isDone()) { + try { + loadedImage = loadedImageFuture.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + if (loadedImage != null) { + loadedImage.drawFrameAndIncrement( 7,7,height-14,height-14); + } else { + Gui.drawRect(7, 7, height - 7, height-7, 0xFF4E4E4E); + } + } + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GlStateManager.pushMatrix(); + GlStateManager.translate(height +3,7, 0); + + GlStateManager.pushMatrix(); + GlStateManager.scale(3.0,3.0,1.0); + fr.drawString(partyJoinRequest.getUsername()+"", 0,0, 0xFFFFFFFF, true); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + GlStateManager.translate(fr.getStringWidth(partyJoinRequest.getUsername()+"") * 3 + 1, (int)(fr.FONT_HEIGHT*1.5), 0); + fr.drawString("#"+partyJoinRequest.getDiscriminator(), 0,0,0xFFaaaaaa, true); + GlStateManager.popMatrix(); + GlStateManager.pushMatrix(); + GlStateManager.translate(0, fr.FONT_HEIGHT * 3 + 5, 0); + GlStateManager.scale(1.0,1.0,1.0); + if (partyJoinRequest.isInvite()) + fr.drawString("§ewants to you to join their party! ("+(TextUtils.formatTime(partyJoinRequest.getExpire() - System.currentTimeMillis()))+")", 0,0,0xFFFFFFFF,false); + else + fr.drawString("wants to join your party! ("+(TextUtils.formatTime(partyJoinRequest.getExpire() - System.currentTimeMillis()))+")", 0,0,0xFFFFFFFF,false); + GlStateManager.popMatrix(); + GlStateManager.popMatrix(); + if (partyJoinRequest.getReply() == null) { + GlStateManager.pushMatrix(); + GlStateManager.translate(height + 3, height - 32, 0); + int widthForTheThing = (width - height) / 3; + GlStateManager.pushMatrix(); + String text = "Accept"; + partyJoinRequest.getAcceptRect().setBounds(x + height + 3, y + height - 25, widthForTheThing - 10, 25); + Gui.drawRect(0, 0, widthForTheThing - 10, 25, hover && partyJoinRequest.getAcceptRect().contains(mouseX, mouseY) ? 0xFF859DF0 : 0xFF7289da); + GlStateManager.translate((widthForTheThing - 10 - fr.getStringWidth(text) * 2) / 2, 15 - fr.FONT_HEIGHT, 0); + + GlStateManager.scale(2.0f, 2.0f, 1.0f); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(text, 0, 0, 0xFFFFFFFF); + GlStateManager.popMatrix(); + GlStateManager.translate(widthForTheThing, 0, 0); + partyJoinRequest.getDenyRect().setBounds(x + height + 3 + widthForTheThing, y + height - 25, widthForTheThing - 10, 25); + Gui.drawRect(0, 0, widthForTheThing - 10, 25, hover && partyJoinRequest.getDenyRect().contains(mouseX, mouseY) ? 0xFFAEC0CB : 0xFF99aab5); + GlStateManager.pushMatrix(); + text = "Deny"; + GlStateManager.translate((widthForTheThing - 10 - fr.getStringWidth(text) * 2) / 2, 15 - fr.FONT_HEIGHT, 0); + GlStateManager.scale(2.0f, 2.0f, 1.0f); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(text, 0, 0, 0xFFFFFFFF); + GlStateManager.popMatrix(); + if (!partyJoinRequest.isInvite()) { + GlStateManager.translate(widthForTheThing, 0, 0); + partyJoinRequest.getIgnoreRect().setBounds(x + height + 3 + widthForTheThing + widthForTheThing, y + height - 25, widthForTheThing - 10, 25); + Gui.drawRect(0, 0, widthForTheThing - 10, 25, hover && partyJoinRequest.getIgnoreRect().contains(mouseX, mouseY) ? 0xFFAEC0CB : 0xFF99aab5); // AEC0CB + + GlStateManager.pushMatrix(); + text = "Ignore"; + GlStateManager.translate((widthForTheThing - 10 - fr.getStringWidth(text) * 2) / 2, 15 - fr.FONT_HEIGHT, 0); + GlStateManager.scale(2.0f, 2.0f, 1.0f); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(text, 0, 0, 0xFFFFFFFF); + GlStateManager.popMatrix(); + } + GlStateManager.popMatrix(); + } else { + GlStateManager.pushMatrix(); + GlStateManager.translate(height + 3, height - 28, 0); + GlStateManager.scale(2.0f,2.0f,1.0f); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(partyJoinRequest.getReply().getPast()+" the invite.",0,0,0xFFFFFFFF); + GlStateManager.popMatrix(); + } + GlStateManager.popMatrix(); + } + + @Override + public void onDiscordUserJoinRequest(DiscordUserJoinRequestEvent event) { + PartyJoinRequest partyInvite = new PartyJoinRequest(); + partyInvite.setDiscordUser(event.getDiscordUser()); + partyInvite.setExpire(System.currentTimeMillis() + 30000L); + partyInvite.setInvite(event.isInvite()); + joinRequests.add(partyInvite); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyJoinRequest.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyJoinRequest.java new file mode 100644 index 00000000..de025698 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyJoinRequest.java @@ -0,0 +1,59 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer; + +import kr.syeyoung.dungeonsguide.gamesdk.GameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordUser; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; + +import java.awt.*; + +@Data +public class PartyJoinRequest { + private DiscordUser discordUser; + + public void setDiscordUser(DiscordUser discordUser) { + this.discordUser = discordUser; + username = GameSDK.readString(discordUser.username); + discriminator = GameSDK.readString(discordUser.discriminator); + avatar = GameSDK.readString(discordUser.avatar); + } + + private String username, discriminator, avatar; + private long expire; + + private Rectangle wholeRect = new Rectangle(); + private Rectangle acceptRect = new Rectangle(); + private Rectangle denyRect = new Rectangle(); + private Rectangle ignoreRect = new Rectangle(); + + private boolean isInvite; + private int ttl = -1; + private Reply reply; + + @AllArgsConstructor + public enum Reply { + ACCEPT("Accepted"), DENY("Denied"), IGNORE("Ignored"); + + @Getter + private final String past; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/invteTooltip/MTooltipInvite.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/invteTooltip/MTooltipInvite.java new file mode 100644 index 00000000..fdeda8d3 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/invteTooltip/MTooltipInvite.java @@ -0,0 +1,128 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.discord.invteTooltip; + +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityActionType; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordRelationshipType; +import kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct.IDiscordActivityManager; +import kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct.IDiscordCore; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.rpc.JDiscordRelation; +import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.renderer.GlStateManager; + +import java.awt.*; +import java.util.HashSet; +import java.util.Set; + +public class MTooltipInvite extends MModal { + private MScrollablePanel mScrollablePanel; + private MList list; + private MTextField search; + private MButton close; + private Set<Long> invited = new HashSet<>(); + public MTooltipInvite() { + setTitle("Invite Discord Friend"); + mScrollablePanel = new MScrollablePanel(1); + mScrollablePanel.setHideScrollBarWhenNotNecessary(true); + add(mScrollablePanel); + + list = new MList() { + @Override + public void resize(int parentWidth, int parentHeight) { + setSize(new Dimension(parentWidth, 9999)); + realignChildren(); + } + }; + list.setGap(1); + list.setDrawLine(true); + list.setGapLineColor(RenderUtils.blendAlpha(0x141414, 0.13f)); + mScrollablePanel.add(list); + mScrollablePanel.getScrollBarY().setWidth(5); + + search = new MTextField() { + @Override + public void edit(String str) { + super.edit(str); resetListContent(); + } + }; + search.setPlaceHolder("Search..."); + add(search); + + close = new MButton(); + close.setText("X"); + close.setBackground( RenderUtils.blendAlpha(0x141414, 0.20f)); + close.setHover( RenderUtils.blendAlpha(0x141414, 0.25f)); + close.setClicked( RenderUtils.blendAlpha(0x141414, 0.24f)); + close.setOnActionPerformed(this::close); + addSuper(close); + resetListContent(); + } + + @Override + public void onBoundsUpdate() { + super.onBoundsUpdate(); + Dimension effDim = getModalContent().getSize(); + search.setBounds(new Rectangle(5,2,effDim.width-10, 15)); + mScrollablePanel.setBounds(new Rectangle(10,18,effDim.width-20, effDim.height-25)); + close.setBounds(new Rectangle(getModalContent().getBounds().x + effDim.width-15,getModalContent().getBounds().y - 16,15,15)); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + GlStateManager.pushMatrix(); + super.render(absMousex, absMousey, relMousex0, relMousey0, partialTicks, scissor); + GlStateManager.popMatrix(); + + Dimension modalSize = getModalSize(); + Dimension effDim = getEffectiveDimension(); + int x = (effDim.width-modalSize.width)/2; + int y = (effDim.height - modalSize.height)/2; + GlStateManager.translate(x,y, 0); + } + + private void resetListContent() { + for (MPanel childComponent : list.getChildComponents()) { + list.remove(childComponent); + } + + String searchTxt = search.getText().trim().toLowerCase(); + for (JDiscordRelation value : RichPresenceManager.INSTANCE.getRelationMap().values()) { +// if (value.getDiscordActivity().getApplicationId() != 816298079732498473L) continue; + if (value.getDiscordRelationshipType() == EDiscordRelationshipType.DiscordRelationshipType_Blocked) continue; + if (!searchTxt.isEmpty() && !(value.getDiscordUser().getUsername().toLowerCase().contains(searchTxt))) continue; + list.add(new MTooltipInviteElement(value, invited.contains(value.getDiscordUser().getId()), this::invite)); + } + setBounds(getBounds()); + } + + public void invite(long id) { + invited.add(id); + IDiscordCore iDiscordCore = RichPresenceManager.INSTANCE.getIDiscordCore(); + IDiscordActivityManager iDiscordActivityManager = iDiscordCore.GetActivityManager.getActivityManager(iDiscordCore); + iDiscordActivityManager.SendInvite.sendInvite(iDiscordActivityManager, new DiscordSnowflake(id), EDiscordActivityActionType.DiscordActivityActionType_Join, "Dungeons Guide RPC Invite TESt", Pointer.NULL, (callbackData, result) -> { + System.out.println("Discord returned "+result+" For inviting "+id); + }); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/invteTooltip/MTooltipInviteElement.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/invteTooltip/MTooltipInviteElement.java new file mode 100644 index 00000000..9a7cad07 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/invteTooltip/MTooltipInviteElement.java @@ -0,0 +1,109 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.discord.invteTooltip; + +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer.ImageTexture; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.rpc.JDiscordRelation; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; + +import java.awt.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.function.Consumer; + +public class MTooltipInviteElement extends MPanel { + private JDiscordRelation relation; + private MButton invite; + public MTooltipInviteElement(JDiscordRelation jDiscordRelation, boolean invited, Consumer<Long> inviteCallback) { + this.relation = jDiscordRelation; + this.invite = new MButton(); + if (!invited) { + invite.setText("Invite"); + invite.setRoundness(2); + invite.setBorder(0xFF02EE67); + invite.setHover(RenderUtils.blendAlpha(0x141414, 0.2f)); + invite.setBackground(RenderUtils.blendAlpha(0x141414, 0.17f)); + invite.setForeground(new Color(0xFF02EE67)); + + invite.setOnActionPerformed(() -> { + if (invite.isEnabled()) + inviteCallback.accept(jDiscordRelation.getDiscordUser().getId()); + + invite.setText("Sent"); + invite.setRoundness(2); + invite.setHover(0); invite.setBorder(0); + invite.setBackground(0); invite.setDisabled(0); invite.setEnabled(false); + invite.setForeground(new Color(0xFF02EE67)); + }); + } else { + invite.setText("Sent"); + invite.setRoundness(2); + invite.setHover(0); + invite.setBackground(0); invite.setDisabled(0); invite.setEnabled(false); + invite.setForeground(new Color(0xFF02EE67)); + } + + add(invite); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + if (lastAbsClip.contains(absMousex, absMousey) && getTooltipsOpen() == 0) { + RenderUtils.drawRoundedRectangle(0,0,bounds.width, bounds.height, 3, Math.PI/8, RenderUtils.blendAlpha(0x141414, 0.17f)); + GlStateManager.enableTexture2D(); + } + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + if (!relation.getDiscordUser().getAvatar().isEmpty()){ + String avatar = "https://cdn.discordapp.com/avatars/"+Long.toUnsignedString(relation.getDiscordUser().getId())+"/"+relation.getDiscordUser().getAvatar()+"."+(relation.getDiscordUser().getAvatar().startsWith("a_") ? "gif":"png"); + Future<ImageTexture> loadedImageFuture = FeatureRegistry.DISCORD_ASKTOJOIN.loadImage(avatar); + ImageTexture loadedImage = null; + if (loadedImageFuture.isDone()) { + try { + loadedImage = loadedImageFuture.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + if (loadedImage != null) { + loadedImage.drawFrameAndIncrement( 3,3,bounds.height-6,bounds.height-6); + } else { + Gui.drawRect(3, 3, bounds.height - 6, bounds.height-6, 0xFF4E4E4E); + } + } + fr.drawString(relation.getDiscordUser().getUsername()+"#"+relation.getDiscordUser().getDiscriminator(), bounds.height,(bounds.height-fr.FONT_HEIGHT)/2, -1); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(100, 20); + } + + @Override + public void onBoundsUpdate() { + invite.setBounds(new Rectangle(bounds.width-53,2,50,bounds.height-4)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/onlinealarm/PlayingDGAlarm.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/onlinealarm/PlayingDGAlarm.java new file mode 100644 index 00000000..c475ce36 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/onlinealarm/PlayingDGAlarm.java @@ -0,0 +1,170 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.discord.onlinealarm; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.features.listener.DiscordUserUpdateListener; +import kr.syeyoung.dungeonsguide.features.listener.ScreenRenderListener; +import kr.syeyoung.dungeonsguide.features.listener.TickListener; +import kr.syeyoung.dungeonsguide.events.DiscordUserUpdateEvent; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer.ImageTexture; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordRelationshipType; +import kr.syeyoung.dungeonsguide.rpc.JDiscordActivity; +import kr.syeyoung.dungeonsguide.rpc.JDiscordRelation; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public class PlayingDGAlarm extends SimpleFeature implements DiscordUserUpdateListener, ScreenRenderListener, TickListener { + public PlayingDGAlarm() { + super("Discord", "Friend Online Notification","Notifies you in bottom when your discord friend has launched a Minecraft with DG!\n\nRequires the Friend's Discord RPC to be enabled", "discord.playingalarm"); + } + private List<PlayerOnline> notif = new CopyOnWriteArrayList<>(); + + @Override + public void onTick() { + try { + List<PlayerOnline> partyJoinRequestList = new ArrayList<>(); + boolean isOnHypixel = DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnHypixel(); + for (PlayerOnline joinRequest:notif) { + if (!isOnHypixel){ + partyJoinRequestList.add(joinRequest); + } else if (joinRequest.getEnd() < System.currentTimeMillis()) { + partyJoinRequestList.add(joinRequest); + } + } + notif.removeAll(partyJoinRequestList); + } catch (Throwable e) {e.printStackTrace();} + } + + + + @Override + public void drawScreen(float partialTicks) { + if (!isEnabled()) return; + try { + GlStateManager.pushMatrix(); + GlStateManager.translate(0,0,100); + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + GlStateManager.scale(1.0 / sr.getScaleFactor(), 1.0 / sr.getScaleFactor(), 1.0); + int height = 90; + int gap = 5; + int x = Minecraft.getMinecraft().displayWidth-350-gap; + int y = Minecraft.getMinecraft().displayHeight-(height+gap)*notif.size(); + for (PlayerOnline partyJoinRequest : notif) { + renderRequest(partyJoinRequest, x, y, 350,height); + y += height + gap; + } + GlStateManager.popMatrix(); + GlStateManager.enableBlend(); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + public void renderRequest(PlayerOnline online, int x, int y, int width, int height) { + GlStateManager.pushMatrix(); + GlStateManager.translate(x,y,0); + + Gui.drawRect(0, 0,width,height, 0xFF23272a); + Gui.drawRect(2, 2, width-2, height-2, 0XFF2c2f33); + { + String avatar = "https://cdn.discordapp.com/avatars/"+Long.toUnsignedString(online.getJDiscordRelation().getDiscordUser().getId())+"/"+online.getJDiscordRelation().getDiscordUser().getAvatar()+"."+(online.getJDiscordRelation().getDiscordUser().getAvatar().startsWith("a_") ? "gif":"png"); + Future<ImageTexture> loadedImageFuture = FeatureRegistry.DISCORD_ASKTOJOIN.loadImage(avatar); + ImageTexture loadedImage = null; + if (loadedImageFuture.isDone()) { + try { + loadedImage = loadedImageFuture.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + if (loadedImage != null) { + loadedImage.drawFrameAndIncrement( 7,7,height-14,height-14); + } else { + Gui.drawRect(7, 7, height - 7, height-7, 0xFF4E4E4E); + } + } + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GlStateManager.pushMatrix(); + GlStateManager.translate(height +3,7, 0); + + GlStateManager.pushMatrix(); + GlStateManager.scale(3.0,3.0,1.0); + fr.drawString(online.getJDiscordRelation().getDiscordUser().getUsername()+"", 0,0, 0xFFFFFFFF, true); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + GlStateManager.translate(fr.getStringWidth(online.getJDiscordRelation().getDiscordUser().getUsername()+"") * 3 + 1, (int)(fr.FONT_HEIGHT*1.5), 0); + fr.drawString("#"+online.getJDiscordRelation().getDiscordUser().getDiscriminator(), 0,0,0xFFaaaaaa, true); + GlStateManager.popMatrix(); + GlStateManager.pushMatrix(); + GlStateManager.translate(0, fr.FONT_HEIGHT * 3 + 5, 0); + GlStateManager.scale(1.0,1.0,1.0); + fr.drawString("Started Playing Skyblock! (Dismissed in "+(TextUtils.formatTime(online.getEnd() - System.currentTimeMillis()))+")", 0,0,0xFFFFFFFF,false); + GlStateManager.popMatrix(); + GlStateManager.popMatrix(); + GlStateManager.popMatrix(); + } + + + @Data @AllArgsConstructor + public static class PlayerOnline { + private JDiscordRelation jDiscordRelation; + private long end; + } + + @Override + public void onDiscordUserUpdate(DiscordUserUpdateEvent event) { + JDiscordRelation prev = event.getPrev(), current = event.getCurrent(); + if (!isDisplayable(prev) && isDisplayable(current)) { + notif.add(new PlayerOnline(current, System.currentTimeMillis()+3000)); + } + } + + public boolean isDisplayable(JDiscordRelation jDiscordRelation) { + EDiscordRelationshipType relationshipType = jDiscordRelation.getDiscordRelationshipType(); + if (relationshipType == EDiscordRelationshipType.DiscordRelationshipType_Blocked) return false; + if (relationshipType == EDiscordRelationshipType.DiscordRelationshipType_None) return false; + if (relationshipType == EDiscordRelationshipType.DiscordRelationshipType_PendingIncoming) return false; + if (relationshipType == EDiscordRelationshipType.DiscordRelationshipType_PendingOutgoing) return false; + + JDiscordActivity jDiscordActivity = jDiscordRelation.getDiscordActivity(); + return jDiscordActivity.getApplicationId() == 816298079732498473L; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureBoxBats.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureBoxBats.java new file mode 100644 index 00000000..c8ed9cd3 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureBoxBats.java @@ -0,0 +1,68 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import com.google.common.base.Predicate; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.WorldRenderListener; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.passive.EntityBat; +import net.minecraft.util.BlockPos; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + + +public class FeatureBoxBats extends SimpleFeature implements WorldRenderListener { + public FeatureBoxBats() { + super("Dungeon.Mobs", "Box Bats", "Box bats in dungeons\nDoes not appear through walls", "dungeon.batbox", true); + parameters.put("radius", new FeatureParameter<Integer>("radius", "Highlight Radius", "The maximum distance between player and bats to be boxed", 20, "integer")); + parameters.put("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Bats", new AColor(255,0,0,50), "acolor")); + } + + + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + @Override + public void drawWorld(float partialTicks) { + if (!isEnabled()) return; + if (!skyblockStatus.isOnDungeon()) return; + + final BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + int val = this.<Integer>getParameter("radius").getValue(); + final int sq = val * val; + + List<EntityBat> skeletonList = Minecraft.getMinecraft().theWorld.getEntities(EntityBat.class, new Predicate<EntityBat>() { + @Override + public boolean apply(@Nullable EntityBat input) { + if (input != null && input.isInvisible()) return false; + return input != null && input.getDistanceSq(player) < sq; + } + }); + AColor c = this.<AColor>getParameter("color").getValue(); + for (EntityBat entitySkeleton : skeletonList) { + if (!entitySkeleton.isInvisible()) + RenderUtils.highlightBox(entitySkeleton, c, partialTicks, true); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureBoxSkelemaster.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureBoxSkelemaster.java new file mode 100644 index 00000000..f21de67b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureBoxSkelemaster.java @@ -0,0 +1,68 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import com.google.common.base.Predicate; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.WorldRenderListener; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.util.BlockPos; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + + +public class FeatureBoxSkelemaster extends SimpleFeature implements WorldRenderListener { + public FeatureBoxSkelemaster() { + super("Dungeon.Mobs", "Box Skeleton Masters", "Box skeleton masters in dungeons", "dungeon.skeletonmasterbox", true); + parameters.put("radius", new FeatureParameter<Integer>("radius", "Highlight Radius", "The maximum distance between player and skeletonmaster to be boxed", 20, "integer")); + parameters.put("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Skeleton master", new AColor(255,0,0,50), "acolor")); + } + + + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + @Override + public void drawWorld(float partialTicks) { + if (!isEnabled()) return; + if (!skyblockStatus.isOnDungeon()) return; + + final BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + int val = this.<Integer>getParameter("radius").getValue(); + final int sq = val * val; + + List<EntityArmorStand> skeletonList = Minecraft.getMinecraft().theWorld.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() { + @Override + public boolean apply(@Nullable EntityArmorStand input) { + if (player.distanceSq(input.getPosition()) > sq) return false; + if (!input.getAlwaysRenderNameTag()) return false; + return input.getName().contains("Skeleton Master"); + } + }); + AColor c = this.<AColor>getParameter("color").getValue(); + for (EntityArmorStand entitySkeleton : skeletonList) { + RenderUtils.highlightBox(entitySkeleton, c, partialTicks, true); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureBoxStarMobs.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureBoxStarMobs.java new file mode 100644 index 00000000..eeda16d0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureBoxStarMobs.java @@ -0,0 +1,68 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import com.google.common.base.Predicate; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.WorldRenderListener; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.util.BlockPos; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + + +public class FeatureBoxStarMobs extends SimpleFeature implements WorldRenderListener { + public FeatureBoxStarMobs() { + super("Dungeon.Mobs", "Box Starred mobs", "Box Starred mobs in dungeons", "dungeon.starmobbox", false); + parameters.put("radius", new FeatureParameter<Integer>("radius", "Highlight Radius", "The maximum distance between player and starred mobs to be boxed", 20, "integer")); + parameters.put("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Starred mobs", new AColor(0,255,255,50), "acolor")); + } + + + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + @Override + public void drawWorld(float partialTicks) { + if (!isEnabled()) return; + if (!skyblockStatus.isOnDungeon()) return; + + final BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + int val = this.<Integer>getParameter("radius").getValue(); + final int sq = val * val; + + List<EntityArmorStand> skeletonList = Minecraft.getMinecraft().theWorld.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() { + @Override + public boolean apply(@Nullable EntityArmorStand input) { + if (player.distanceSq(input.getPosition()) > sq) return false; + if (!input.getAlwaysRenderNameTag()) return false; + return input.getName().contains("✯"); + } + }); + AColor c = this.<AColor>getParameter("color").getValue(); + for (EntityArmorStand entitySkeleton : skeletonList) { + RenderUtils.highlightBox(entitySkeleton, c, partialTicks, true); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureCollectScore.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureCollectScore.java new file mode 100644 index 00000000..897d8b64 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureCollectScore.java @@ -0,0 +1,27 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +public class FeatureCollectScore extends SimpleFeature { + public FeatureCollectScore() { + super("Misc", "Collect Speed Score", "Collect Speed score, run time, and floor and send that to developer's server for speed formula. This data is completely anonymous, opt out of the feature by disabling this feature", "misc.gatherscoredata", true); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonCurrentRoomSecrets.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonCurrentRoomSecrets.java new file mode 100644 index 00000000..5f68187e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonCurrentRoomSecrets.java @@ -0,0 +1,108 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.ChatListener; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureDungeonCurrentRoomSecrets extends TextHUDFeature implements ChatListener { + public FeatureDungeonCurrentRoomSecrets() { + super("Dungeon.Dungeon Information", "Display # Secrets in current room", "Display what your actionbar says", "dungeon.stats.secretsroom", true, getFontRenderer().getStringWidth("Secrets In Room: 8/8"), getFontRenderer().FONT_HEIGHT); + this.setEnabled(false); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("currentSecrets", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator2", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("totalSecrets", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + + private static final List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Secrets In Room","title")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("5","currentSecrets")); + dummyText.add(new StyledText("/","separator2")); + dummyText.add(new StyledText("8","totalSecrets")); + } + + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon(); + } + + @Override + public List<String> getUsedTextStyle() { + return Arrays.asList("title", "separator", "currentSecrets", "separator2", "totalSecrets"); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + private int latestCurrSecrets = 0; + private int latestTotalSecrets = 0; + + + @Override + public List<StyledText> getText() { + if (skyblockStatus.getContext().getBossfightProcessor() != null) return new ArrayList<StyledText>(); + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("Secrets In Room","title")); + actualBit.add(new StyledText(": ","separator")); + actualBit.add(new StyledText(latestCurrSecrets +"","currentSecrets")); + actualBit.add(new StyledText("/","separator2")); + actualBit.add(new StyledText(latestTotalSecrets +"","totalSecrets")); + return actualBit; + } + + @Override + public void onChat(ClientChatReceivedEvent chat) { + if (chat.type != 2) return; + String text = chat.message.getFormattedText(); + if (!text.contains("/")) return; + + int secretsIndex = text.indexOf("Secrets"); + if (secretsIndex != -1) { + int theindex = 0; + for (int i = secretsIndex; i >= 0; i--) { + if (text.startsWith("§7", i)) { + theindex = i; + } + } + String it = text.substring(theindex + 2, secretsIndex - 1); + + latestCurrSecrets = Integer.parseInt(it.split("/")[0]); + latestTotalSecrets = Integer.parseInt(it.split("/")[1]); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonDeaths.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonDeaths.java new file mode 100644 index 00000000..3dafd79e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonDeaths.java @@ -0,0 +1,167 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.dungeon.events.DungeonDeathEvent; +import kr.syeyoung.dungeonsguide.features.listener.ChatListener; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.util.ChatComponentText; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.*; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FeatureDungeonDeaths extends TextHUDFeature implements ChatListener { + public FeatureDungeonDeaths() { + super("Dungeon.Dungeon Information", "Display Deaths", "Display names of player and death count in dungeon run", "dungeon.stats.deaths", false, getFontRenderer().getStringWidth("longestplayernamepos: 100"), getFontRenderer().FONT_HEIGHT * 6); + this.setEnabled(false); + getStyles().add(new TextStyle("username", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("total", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("deaths", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("totalDeaths", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + @Override + public boolean isHUDViewable() { + if (!skyblockStatus.isOnDungeon()) return false; + DungeonContext context = skyblockStatus.getContext(); + return context != null; + } + + @Override + public boolean doesScaleWithHeight() { + return false; + } + + @Override + public List<String> getUsedTextStyle() { + return Arrays.asList("username", "separator", "deaths", "total", "totalDeaths"); + } + + @Override + public List<StyledText> getText() { + + List<StyledText> text= new ArrayList<StyledText>(); + + DungeonContext context = skyblockStatus.getContext(); + Map<String, Integer> deaths = context.getDeaths(); + int i = 0; + int deathsCnt = 0; + for (Map.Entry<String, Integer> death:deaths.entrySet()) { + text.add(new StyledText(death.getKey(),"username")); + text.add(new StyledText(": ","separator")); + text.add(new StyledText(death.getValue()+"\n","deaths")); + deathsCnt += death.getValue(); + } + text.add(new StyledText("Total Deaths","total")); + text.add(new StyledText(": ","separator")); + text.add(new StyledText(getTotalDeaths()+"","totalDeaths")); + + return text; + } + + private static final List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("syeyoung","username")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("-130\n","deaths")); + dummyText.add(new StyledText("rioho","username")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("-999999\n","deaths")); + dummyText.add(new StyledText("dungeonsguide","username")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("-42\n","deaths")); + dummyText.add(new StyledText("penguinman","username")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("0\n","deaths")); + dummyText.add(new StyledText("probablysalt","username")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("0\n","deaths")); + dummyText.add(new StyledText("Total Deaths","total")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("0","totalDeaths")); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + public int getTotalDeaths() { + if (!skyblockStatus.isOnDungeon()) return 0; + for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { + String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + if (name.contains("Deaths")) { + String whatever = TextUtils.keepIntegerCharactersOnly(TextUtils.keepScoreboardCharacters(TextUtils.stripColor(name))); + if (whatever.isEmpty()) break; + return Integer.parseInt(whatever); + } + } + DungeonContext context = skyblockStatus.getContext(); + if (context == null) return 0; + int d = 0; + for (Integer value : context.getDeaths().values()) { + d += value; + } + return d; + } + + Pattern deathPattern = Pattern.compile("§r§c ☠ (.+?)§r§7 .+and became a ghost.+"); + Pattern meDeathPattern = Pattern.compile("§r§c ☠ §r§7You .+and became a ghost.+"); + + @Override + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + if (clientChatReceivedEvent.type == 2) return; + if (!skyblockStatus.isOnDungeon()) return; + DungeonContext context = skyblockStatus.getContext(); + if (context == null) return; + + String txt = clientChatReceivedEvent.message.getFormattedText(); + Matcher m = deathPattern.matcher(txt); + if (m.matches()) { + String nickname = TextUtils.stripColor(m.group(1)); + int deaths = context.getDeaths().getOrDefault(nickname, 0); + context.getDeaths().put(nickname, deaths + 1); + context.createEvent(new DungeonDeathEvent(nickname, txt, deaths)); + DungeonsGuide.sendDebugChat(new ChatComponentText("Death verified :: "+nickname+" / "+(deaths + 1))); + } + Matcher m2 = meDeathPattern.matcher(txt); + if (m2.matches()) { + String nickname = "me"; + int deaths = context.getDeaths().getOrDefault(nickname, 0); + context.getDeaths().put(nickname, deaths + 1); + context.createEvent(new DungeonDeathEvent(Minecraft.getMinecraft().thePlayer.getName(), txt, deaths)); + DungeonsGuide.sendDebugChat(new ChatComponentText("Death verified :: me / "+(deaths + 1))); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonMap.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonMap.java new file mode 100644 index 00000000..466120d6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonMap.java @@ -0,0 +1,387 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.Ordering; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.BossroomEnterListener; +import kr.syeyoung.dungeonsguide.features.listener.DungeonEndListener; +import kr.syeyoung.dungeonsguide.features.listener.DungeonStartListener; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.MapProcessor; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.GuiFeature; +import kr.syeyoung.dungeonsguide.features.listener.*; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.block.material.MapColor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EnumPlayerModelParts; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Vec4b; +import net.minecraft.world.WorldSettings; +import net.minecraft.world.storage.MapData; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.List; +import java.util.Comparator; + +public class FeatureDungeonMap extends GuiFeature implements DungeonEndListener, DungeonStartListener, BossroomEnterListener { + public FeatureDungeonMap() { + super("Dungeon", "Dungeon Map", "Display dungeon map!", "dungeon.map", true, 128,128); + this.setEnabled(false); + parameters.put("scale", new FeatureParameter<Boolean>("scale", "Scale map", "Whether to scale map to fit screen", true, "boolean")); + parameters.put("playerCenter", new FeatureParameter<Boolean>("playerCenter", "Center map at player", "Render you in the center", false, "boolean")); + parameters.put("rotate", new FeatureParameter<Boolean>("rotate", "Rotate map centered at player", "Only works with Center map at player enabled", false, "boolean")); + parameters.put("postScale", new FeatureParameter<Float>("postScale", "Scale factor of map", "Only works with Center map at player enabled", 1.0f, "float")); + parameters.put("useplayerheads", new FeatureParameter<Boolean>("useplayerheads", "Use player heads instead of arrows", "Option to use player heads instead of arrows", true, "boolean")); + parameters.put("showotherplayers", new FeatureParameter<Boolean>("showotherplayers", "Show other players", "Option to show other players in map", true, "boolean")); + parameters.put("showtotalsecrets", new FeatureParameter<Boolean>("showtotalsecrets", "Show Total secrets in the room", "Option to overlay total secrets in the specific room", true, "boolean")); + parameters.put("playerheadscale", new FeatureParameter<Float>("playerheadscale", "Player head scale", "Scale factor of player heads, defaults to 1", 1.0f, "float")); + parameters.put("textScale", new FeatureParameter<Float>("textScale", "Text scale", "Scale factor of texts on map, defaults to 1", 1.0f, "float")); + + parameters.put("border_color", new FeatureParameter<AColor>("border_color", "Color of the border", "Same as name", new AColor(255,255,255,255), "acolor")); + parameters.put("background_color", new FeatureParameter<AColor>("background_color", "Color of the background", "Same as name", new AColor(0x22000000, true), "acolor")); + parameters.put("player_color", new FeatureParameter<AColor>("player_color", "Color of the player border", "Same as name", new AColor(255,255,255,0), "acolor")); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + public static final Ordering<NetworkPlayerInfo> field_175252_a = Ordering.from(new PlayerComparator()); + + private boolean on = false; + + @Override + public void onDungeonEnd() { + on = false; + } + + @Override + public void onDungeonStart() { + on = true; + } + + @Override + public void onBossroomEnter() { + on = false; + } + + @SideOnly(Side.CLIENT) + static class PlayerComparator implements Comparator<NetworkPlayerInfo> + { + private PlayerComparator() + { + } + + public int compare(NetworkPlayerInfo p_compare_1_, NetworkPlayerInfo p_compare_2_) + { + ScorePlayerTeam scoreplayerteam = p_compare_1_.getPlayerTeam(); + ScorePlayerTeam scoreplayerteam1 = p_compare_2_.getPlayerTeam(); + return ComparisonChain.start().compareTrueFirst(p_compare_1_.getGameType() != WorldSettings.GameType.SPECTATOR, p_compare_2_.getGameType() != WorldSettings.GameType.SPECTATOR).compare(scoreplayerteam != null ? scoreplayerteam.getRegisteredName() : "", scoreplayerteam1 != null ? scoreplayerteam1.getRegisteredName() : "").compare(p_compare_1_.getGameProfile().getName(), p_compare_2_.getGameProfile().getName()).result(); + } + } + @Override + public void drawHUD(float partialTicks) { + if (!skyblockStatus.isOnDungeon()) return; + if (skyblockStatus.getContext() == null || !skyblockStatus.getContext().getMapProcessor().isInitialized()) return; + if (!on) return; + + DungeonContext context = skyblockStatus.getContext(); + MapProcessor mapProcessor = context.getMapProcessor(); + MapData mapData = mapProcessor.getLastMapData2(); + Rectangle featureRect =getFeatureRect().getRectangle(); + Gui.drawRect(0,0,featureRect.width, featureRect.height, RenderUtils.getColorAt(featureRect.x, featureRect.y, this.<AColor>getParameter("background_color").getValue())); + GlStateManager.color(1,1,1,1); + GlStateManager.pushMatrix(); + if (mapData == null) { + Gui.drawRect(0,0,featureRect.width, featureRect.height, 0xFFFF0000); + } else { + renderMap(partialTicks,mapProcessor,mapData,context); + } + GlStateManager.popMatrix(); + GL11.glLineWidth(2); + RenderUtils.drawUnfilledBox(0,0,featureRect.width, featureRect.height, this.<AColor>getParameter("border_color").getValue()); + } + + @Override + public void drawDemo(float partialTicks) { + if (skyblockStatus.isOnDungeon() && skyblockStatus.getContext() != null && skyblockStatus.getContext().getMapProcessor().isInitialized() && on) { + drawHUD(partialTicks); + return; + } + Rectangle featureRect =getFeatureRect().getRectangle(); + Gui.drawRect(0,0,featureRect.width, featureRect.height, RenderUtils.getColorAt(featureRect.x, featureRect.y, this.<AColor>getParameter("background_color").getValue())); + FontRenderer fr = getFontRenderer(); + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Please join a dungeon to see preview", featureRect.width / 2 - fr.getStringWidth("Please join a dungeon to see preview") / 2, featureRect.height / 2 - fr.FONT_HEIGHT / 2, 0xFFFFFFFF); + GL11.glLineWidth(2); + RenderUtils.drawUnfilledBox(0,0,featureRect.width, featureRect.height, this.<AColor>getParameter("border_color").getValue()); + } + + public void renderMap(float partialTicks, MapProcessor mapProcessor, MapData mapData, DungeonContext context){ + float postScale = this.<Boolean>getParameter("playerCenter").getValue() ? this.<Float>getParameter("postScale").getValue() : 1; + Rectangle featureRect =getFeatureRect().getRectangle(); + int width = featureRect.width; + float scale = (this.<Boolean>getParameter("scale").getValue() ? width / 128.0f : 1); + GlStateManager.translate(width / 2, width / 2, 0); + GlStateManager.scale(scale, scale, 0); + GlStateManager.scale(postScale, postScale,0); + EntityPlayer p = Minecraft.getMinecraft().thePlayer; + Point pt = mapProcessor.worldPointToMapPoint(p.getPositionEyes(partialTicks)); + double yaw = p.prevRotationYawHead + (p.rotationYaw - p.prevRotationYawHead) * partialTicks; + if (this.<Boolean>getParameter("playerCenter").getValue()) { + if (this.<Boolean>getParameter("rotate").getValue()) { + GlStateManager.rotate((float) (180.0 - yaw), 0,0,1); + } + GlStateManager.translate( -pt.x, -pt.y, 0); + } else { + GlStateManager.translate( -64, -64, 0); + } + updateMapTexture(mapData.colors, mapProcessor, context.getDungeonRoomList()); + render(mapData, false); + + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(1, 771, 0, 1); + + if (this.<Boolean>getParameter("useplayerheads").getValue()) { + renderHeads(mapProcessor, mapData, scale, postScale, partialTicks); + } else { + renderArrows(mapProcessor, mapData, scale, postScale, partialTicks); + } + + + FontRenderer fr = getFontRenderer(); + if (this.<Boolean>getParameter("showtotalsecrets").getValue()) { + for (DungeonRoom dungeonRoom : context.getDungeonRoomList()) { + GlStateManager.pushMatrix(); + + Point mapPt = mapProcessor.roomPointToMapPoint(dungeonRoom.getUnitPoints().get(0)); + GlStateManager.translate(mapPt.x + mapProcessor.getUnitRoomDimension().width / 2, mapPt.y + mapProcessor.getUnitRoomDimension().height / 2, 0); + + if (this.<Boolean>getParameter("playerCenter").getValue() && this.<Boolean>getParameter("rotate").getValue()) { + GlStateManager.rotate((float) (yaw - 180), 0, 0, 1); + } + GlStateManager.scale(1 / scale, 1 / scale, 0); + GlStateManager.scale(1 / postScale, 1 / postScale, 0); + float s = this.<Float>getParameter("textScale").getValue(); + GlStateManager.scale(s,s,0); + String str = ""; + str += dungeonRoom.getTotalSecrets() == -1 ? "?" : String.valueOf(dungeonRoom.getTotalSecrets()); + str += " "; + if (dungeonRoom.getCurrentState() == DungeonRoom.RoomState.FINISHED) { + str += "✔"; + } else if (dungeonRoom.getCurrentState() == DungeonRoom.RoomState.COMPLETE_WITHOUT_SECRETS) { + str += "☑"; + } else if (dungeonRoom.getCurrentState() == DungeonRoom.RoomState.DISCOVERED) { + str += "☐"; + } else if (dungeonRoom.getCurrentState() == DungeonRoom.RoomState.FAILED) { + str += "❌"; + } + + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(str, -(fr.getStringWidth(str) / 2), -(fr.FONT_HEIGHT / 2), dungeonRoom.getCurrentState() == DungeonRoom.RoomState.FINISHED ? 0xFF00FF00 : (dungeonRoom.getColor() == 74 ? 0xff000000 : 0xFFFFFFFF)); + + GlStateManager.popMatrix(); + } + } + + } + + + + private final DynamicTexture mapTexture = new DynamicTexture(128, 128); + private final ResourceLocation location = Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation("dungeonmap/map", mapTexture); + private final int[] mapTextureData = mapTexture.getTextureData(); + + private void updateMapTexture(byte[] colors, MapProcessor mapProcessor, List<DungeonRoom> dungeonRooms) { + for (int i = 0; i < 16384; ++i) { + int j = colors[i] & 255; + + if (j / 4 == 0) { + this.mapTextureData[i] = 0x00000000; + } else { + this.mapTextureData[i] = MapColor.mapColorArray[j / 4].getMapColor(j & 3); + } + } + + if (this.<Boolean>getParameter("showtotalsecrets").getValue()) { + for (DungeonRoom dungeonRoom : dungeonRooms) { + for (Point pt : dungeonRoom.getUnitPoints()) { + for (int y1 = 0; y1 < mapProcessor.getUnitRoomDimension().height; y1++) { + for (int x1 = 0; x1 < mapProcessor.getUnitRoomDimension().width; x1++) { + int x = MathHelper.clamp_int(pt.x * (mapProcessor.getUnitRoomDimension().width + mapProcessor.getDoorDimension().height) + x1 + mapProcessor.getTopLeftMapPoint().x, 0, 128); + int y = MathHelper.clamp_int(pt.y * (mapProcessor.getUnitRoomDimension().height + mapProcessor.getDoorDimension().height) + y1 + mapProcessor.getTopLeftMapPoint().y, 0, 128); + int i = y * 128 + x; + int j = dungeonRoom.getColor(); + + if (j / 4 == 0) { + this.mapTextureData[i] = 0x00000000; + } else { + this.mapTextureData[i] = MapColor.mapColorArray[j / 4].getMapColor(j & 3); + } + } + } + } + } + } + + + this.mapTexture.updateDynamicTexture(); + } + + private void renderHeads(MapProcessor mapProcessor, MapData mapData, float scale, float postScale, float partialTicks) { + List<NetworkPlayerInfo> list = field_175252_a.sortedCopy(Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()); + if (list.size() < 40) return; + for (int i = 1; i < 20; i++) { + NetworkPlayerInfo networkPlayerInfo = list.get(i); + String name = networkPlayerInfo.getDisplayName() != null ? networkPlayerInfo.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfo.getPlayerTeam(), networkPlayerInfo.getGameProfile().getName()); + if (name.trim().equals("§r") || name.startsWith("§r ")) continue; + String actual = TextUtils.stripColor(name).trim().split(" ")[0]; + EntityPlayer entityplayer = Minecraft.getMinecraft().theWorld.getPlayerEntityByName(actual); + if (TextUtils.stripColor(name).endsWith("(DEAD)") && entityplayer != Minecraft.getMinecraft().thePlayer) { + continue; + } + Point pt2; + double yaw2; + + if (entityplayer != null && (!entityplayer.isInvisible() || entityplayer == Minecraft.getMinecraft().thePlayer)) { + pt2 = mapProcessor.worldPointToMapPoint(entityplayer.getPositionEyes(partialTicks)); + yaw2 = entityplayer.prevRotationYawHead + (entityplayer.rotationYawHead - entityplayer.prevRotationYawHead) * partialTicks; + } else { + String iconName = mapProcessor.getMapIconToPlayerMap().get(actual); + if (iconName == null) continue; + Vec4b vec = mapData.mapDecorations.get(iconName); + if (vec == null) { + continue; + } else { + pt2 = new Point(vec.func_176112_b() / 2 + 64, vec.func_176113_c() / 2 + 64); + yaw2 = vec.func_176111_d() * 360 / 16.0f ; + } + } + GlStateManager.pushMatrix(); + if (entityplayer == Minecraft.getMinecraft().thePlayer || this.<Boolean>getParameter("showotherplayers").getValue()) + { + boolean flag1 = entityplayer != null && entityplayer.isWearing(EnumPlayerModelParts.CAPE); + GlStateManager.enableTexture2D(); + Minecraft.getMinecraft().getTextureManager().bindTexture(networkPlayerInfo.getLocationSkin()); + int l2 = 8 + (flag1 ? 8 : 0); + int i3 = 8 * (flag1 ? -1 : 1); + + GlStateManager.translate(pt2.x, pt2.y, 0); + GlStateManager.rotate((float) (yaw2 - 180), 0, 0, 1); + + GlStateManager.scale(1 / scale, 1 / scale, 0); + GlStateManager.scale(1 / postScale, 1 / postScale, 0); + float s = this.<Float>getParameter("playerheadscale").getValue(); + GlStateManager.scale(s,s,0); + Gui.drawScaledCustomSizeModalRect(-4, -4, 8.0F, (float) l2, 8, i3, 8, 8, 64.0F, 64.0F); + GL11.glLineWidth(1); + RenderUtils.drawUnfilledBox(-4,-4,4, 4, this.<AColor>getParameter("player_color").getValue()); + } + GlStateManager.popMatrix(); + } + } + private static final ResourceLocation mapIcons = new ResourceLocation("textures/map/map_icons.png"); + + private void renderArrows(MapProcessor mapProcessor, MapData mapData, float scale, float postScale, float partialTicks) { + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + int k = 0; + Minecraft.getMinecraft().getTextureManager().bindTexture(mapIcons); + for (Vec4b vec4b : mapData.mapDecorations.values()) { + if (vec4b.func_176110_a() == 1 || this.<Boolean>getParameter("showotherplayers").getValue()) { + GlStateManager.pushMatrix(); + GlStateManager.translate((float)vec4b.func_176112_b() / 2.0F + 64.0F, (float)vec4b.func_176113_c() / 2.0F + 64.0F, -0.02F); + GlStateManager.rotate((float)(vec4b.func_176111_d() * 360) / 16.0F, 0.0F, 0.0F, 1.0F); + + GlStateManager.scale(1 / scale, 1 / scale, 0); + GlStateManager.scale(1 / postScale, 1 / postScale, 0); + float s = this.<Float>getParameter("playerheadscale").getValue(); + GlStateManager.scale(s * 5,s * 5,0); + + GlStateManager.translate(-0.125F, 0.125F, 0.0F); + byte b0 = vec4b.func_176110_a(); + float f1 = (float)(b0 % 4) / 4.0F; + float f2 = (float)(b0 / 4) / 4.0F; + float f3 = (float)(b0 % 4 + 1) / 4.0F; + float f4 = (float)(b0 / 4 + 1) / 4.0F; + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + float f5 = -0.001F; + worldrenderer.pos(-1.0D, 1.0D, (float)k * -0.001F).tex(f1, f2).endVertex(); + worldrenderer.pos(1.0D, 1.0D, (float)k * -0.001F).tex(f3, f2).endVertex(); + worldrenderer.pos(1.0D, -1.0D, (float)k * -0.001F).tex(f3, f4).endVertex(); + worldrenderer.pos(-1.0D, -1.0D, (float)k * -0.001F).tex(f1, f4).endVertex(); + tessellator.draw(); + GlStateManager.popMatrix(); + ++k; + } + } + } + + private void render(MapData mapData, boolean noOverlayRendering) { + int i = 0; + int j = 0; + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + float f = 0.0F; + Minecraft.getMinecraft().getTextureManager().bindTexture(this.location); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(1, 771, 0, 1); + GlStateManager.disableAlpha(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer.pos((float)(i) + f, (float)(j + 128) - f, -0.009999999776482582D).tex(0.0D, 1.0D).endVertex(); + worldrenderer.pos((float)(i + 128) - f, (float)(j + 128) - f, -0.009999999776482582D).tex(1.0D, 1.0D).endVertex(); + worldrenderer.pos((float)(i + 128) - f, (float)(j) + f, -0.009999999776482582D).tex(1.0D, 0.0D).endVertex(); + worldrenderer.pos((float)(i) + f, (float)(j) + f, -0.009999999776482582D).tex(0.0D, 0.0D).endVertex(); + tessellator.draw(); + GlStateManager.enableAlpha(); + GlStateManager.disableBlend(); + + GlStateManager.pushMatrix(); + GlStateManager.translate(0.0F, 0.0F, -0.04F); + GlStateManager.scale(1.0F, 1.0F, 1.0F); + GlStateManager.popMatrix(); + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonMilestone.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonMilestone.java new file mode 100644 index 00000000..5fe72cc9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonMilestone.java @@ -0,0 +1,109 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.ChatListener; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.util.ChatComponentText; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +public class FeatureDungeonMilestone extends TextHUDFeature implements ChatListener { + public FeatureDungeonMilestone() { + super("Dungeon.Dungeon Information", "Display Current Class Milestone", "Display current class milestone of yourself", "dungeon.stats.milestone", true, getFontRenderer().getStringWidth("Milestone: 12"), getFontRenderer().FONT_HEIGHT); + this.setEnabled(false); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("number", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + private static final List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Milestone","title")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("9","number")); + } + + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon(); + } + + @Override + public List<String> getUsedTextStyle() { + return Arrays.asList("title", "separator", "number"); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public List<StyledText> getText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("Milestone","title")); + actualBit.add(new StyledText(": ","separator")); + for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { + String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + if (name.startsWith("§r Milestone: §r")) { + String milestone = TextUtils.stripColor(name).substring(13); + actualBit.add(new StyledText(milestone+"","number")); + break; + } + } + return actualBit; + } + + public static final Pattern milestone_pattern = Pattern.compile("§r§e§l(.+) Milestone §r§e(.)§r§7: .+ §r§a(.+)§r"); + + + @Override + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + if (clientChatReceivedEvent.type == 2) return; + if (!skyblockStatus.isOnDungeon()) return; + DungeonContext context = skyblockStatus.getContext(); + if (context == null) return; + String txt = clientChatReceivedEvent.message.getFormattedText(); + if (milestone_pattern.matcher(txt).matches()) { + context.getMilestoneReached().add(new String[] { + TextUtils.formatTime(FeatureRegistry.DUNGEON_REALTIME.getTimeElapsed()), + TextUtils.formatTime(FeatureRegistry.DUNGEON_SBTIME.getTimeElapsed()) + }); + DungeonsGuide.sendDebugChat(new ChatComponentText("Reached Milestone At " + TextUtils.formatTime(FeatureRegistry.DUNGEON_REALTIME.getTimeElapsed()) + " / "+TextUtils.formatTime(FeatureRegistry.DUNGEON_SBTIME.getTimeElapsed()))); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonRealTime.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonRealTime.java new file mode 100644 index 00000000..88bfe8fe --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonRealTime.java @@ -0,0 +1,91 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.DungeonQuitListener; +import kr.syeyoung.dungeonsguide.features.listener.DungeonStartListener; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.utils.TextUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureDungeonRealTime extends TextHUDFeature implements DungeonStartListener, DungeonQuitListener { + public FeatureDungeonRealTime() { + super("Dungeon.Dungeon Information", "Display Real Time-Dungeon Time", "Display how much real time has passed since dungeon run started", "dungeon.stats.realtime", true, getFontRenderer().getStringWidth("Time(Real): 59m 59s"), getFontRenderer().FONT_HEIGHT); + this.setEnabled(false); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("discriminator", new AColor(0xAA,0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("number", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + private long started = -1; + + public long getTimeElapsed() { + return System.currentTimeMillis() - started; + } + + private static final java.util.List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Time","title")); + dummyText.add(new StyledText("(Real)","discriminator")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("-42h","number")); + } + + @Override + public boolean isHUDViewable() { + return started != -1; + } + + @Override + public java.util.List<String> getUsedTextStyle() { + return Arrays.asList("title", "discriminator", "separator", "number"); + } + + @Override + public java.util.List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public java.util.List<StyledText> getText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("Time","title")); + actualBit.add(new StyledText("(Real)","discriminator")); + actualBit.add(new StyledText(": ","separator")); + actualBit.add(new StyledText(TextUtils.formatTime(getTimeElapsed()),"number")); + return actualBit; + } + + @Override + public void onDungeonStart() { + started= System.currentTimeMillis(); + } + + @Override + public void onDungeonQuit() { + started = -1; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonRoomName.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonRoomName.java new file mode 100644 index 00000000..512ec964 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonRoomName.java @@ -0,0 +1,95 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureDungeonRoomName extends TextHUDFeature { + public FeatureDungeonRoomName() { + super("Dungeon.Dungeon Information", "Display name of the room you are in", "Display name of the room you are in", "dungeon.roomname", false, getFontRenderer().getStringWidth("You're in puzzle-tictactoe"), getFontRenderer().FONT_HEIGHT); + getStyles().add(new TextStyle("in", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("roomname", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + public int getTotalSecretsInt() { + DungeonContext context = skyblockStatus.getContext(); + int totalSecrets = 0; + for (DungeonRoom dungeonRoom : context.getDungeonRoomList()) { + if (dungeonRoom.getTotalSecrets() != -1) + totalSecrets += dungeonRoom.getTotalSecrets(); + } + return totalSecrets; + } + + private static final List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("You're in ","in")); + dummyText.add(new StyledText("puzzle-tictactoe","roomname")); + } + + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon() && skyblockStatus.getContext() != null && skyblockStatus.getContext().getMapProcessor() != null; + } + + @Override + public List<String> getUsedTextStyle() { + return Arrays.asList("roomname", "in"); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public List<StyledText> getText() { + EntityPlayerSP player = Minecraft.getMinecraft().thePlayer; + + Point roomPt = skyblockStatus.getContext().getMapProcessor().worldPointToRoomPoint(player.getPosition()); + DungeonRoom dungeonRoom = skyblockStatus.getContext().getRoomMapper().get(roomPt); + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("You're in ","in")); + if (dungeonRoom == null) { + actualBit.add(new StyledText("Unknown","roomname")); + } else { + actualBit.add(new StyledText(dungeonRoom.getDungeonRoomInfo().getName(),"roomname")); + } + + + return actualBit; + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonSBTime.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonSBTime.java new file mode 100644 index 00000000..00928806 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonSBTime.java @@ -0,0 +1,119 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.scoreboard.Score; +import net.minecraft.scoreboard.ScoreObjective; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.scoreboard.Scoreboard; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +public class FeatureDungeonSBTime extends TextHUDFeature { + + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + public FeatureDungeonSBTime() { + super("Dungeon.Dungeon Information", "Display Ingame Dungeon Time", "Display how much time skyblock thinks has passed since dungeon run started", "dungeon.stats.igtime", true, getFontRenderer().getStringWidth("Time(IG): 1h 59m 59s"), getFontRenderer().FONT_HEIGHT); + this.setEnabled(false); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("discriminator", new AColor(0xAA,0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("number", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + public int getTimeElapsed() { + Scoreboard scoreboard = Minecraft.getMinecraft().theWorld.getScoreboard(); + ScoreObjective objective = scoreboard.getObjectiveInDisplaySlot(1); + Collection<Score> scores = scoreboard.getSortedScores(objective); + String time = "idkyet"; + for (Score sc:scores) { + ScorePlayerTeam scorePlayerTeam = scoreboard.getPlayersTeam(sc.getPlayerName()); + String strippedLine = TextUtils.keepScoreboardCharacters(TextUtils.stripColor(ScorePlayerTeam.formatPlayerName(scorePlayerTeam, sc.getPlayerName()))).trim(); + if (strippedLine.startsWith("Time Elapsed: ")) { + time = strippedLine.substring(14); + } + } + time = time.replace(" ", ""); + int hour = time.indexOf('h') == -1 ? 0 : Integer.parseInt(time.substring(0, time.indexOf('h'))); + if (time.contains("h")) time = time.substring(time.indexOf('h') + 1); + int minute = time.indexOf('m') == -1 ? 0 : Integer.parseInt(time.substring(0, time.indexOf('m'))); + if (time.contains("m")) time = time.substring(time.indexOf('m') + 1); + int second = time.indexOf('s') == -1 ? 0 : Integer.parseInt(time.substring(0, time.indexOf('s'))); + + int time2 = hour * 60 * 60 + minute * 60 + second; + return time2 * 1000; + } + + private static final java.util.List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Time","title")); + dummyText.add(new StyledText("(Ig)","discriminator")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("-42h","number")); + } + + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon(); + } + + @Override + public java.util.List<String> getUsedTextStyle() { + return Arrays.asList("title", "discriminator", "separator", "number"); + } + + @Override + public java.util.List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public java.util.List<StyledText> getText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("Time","title")); + actualBit.add(new StyledText("(Ig)","discriminator")); + actualBit.add(new StyledText(": ","separator")); + Scoreboard scoreboard = Minecraft.getMinecraft().theWorld.getScoreboard(); + ScoreObjective objective = scoreboard.getObjectiveInDisplaySlot(1); + Collection<Score> scores = scoreboard.getSortedScores(objective); + String time = "unknown"; + for (Score sc:scores) { + ScorePlayerTeam scorePlayerTeam = scoreboard.getPlayersTeam(sc.getPlayerName()); + String strippedLine = TextUtils.keepScoreboardCharacters(TextUtils.stripColor(ScorePlayerTeam.formatPlayerName(scorePlayerTeam, sc.getPlayerName()))).trim(); + if (strippedLine.startsWith("Time Elapsed: ")) { + time = strippedLine.substring(14); + } + } + actualBit.add(new StyledText(time,"number")); + return actualBit; + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonScore.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonScore.java new file mode 100644 index 00000000..b62df644 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonScore.java @@ -0,0 +1,354 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import kr.syeyoung.dungeonsguide.utils.TimeScoreUtil; +import kr.syeyoung.dungeonsguide.wsresource.StaticResource; +import kr.syeyoung.dungeonsguide.wsresource.StaticResourceCache; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.util.MathHelper; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +public class FeatureDungeonScore extends TextHUDFeature { + public FeatureDungeonScore() { + super("Dungeon.Dungeon Information", "Display Current Score", "Calculate and Display current score\nThis data is from pure calculation and can be different from actual score.", "dungeon.stats.score", false, 200, getFontRenderer().FONT_HEIGHT * 4); + this.setEnabled(false); + parameters.put("verbose", new FeatureParameter<Boolean>("verbose", "Show each score instead of sum", "Skill: 100 Explore: 58 S->S+(5 tombs) instead of Score: 305", true, "boolean")); + + getStyles().add(new TextStyle("scorename", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("score", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("brackets", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("etc", new AColor(0xAA,0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("currentScore", new AColor(0xFF, 0xAA,0x00,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("arrow", new AColor(0xAA,0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("nextScore", new AColor(0xFF, 0xAA,0x00,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("required", new AColor(0xAA,0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon(); + } + + private static final java.util.List<StyledText> dummyText= new ArrayList<StyledText>(); + private static final java.util.List<StyledText> dummyText2= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Score","scorename")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("305 ","score")); + dummyText.add(new StyledText("(","brackets")); + dummyText.add(new StyledText("S+","currentScore")); + dummyText.add(new StyledText(")","brackets")); + + + + dummyText2.add(new StyledText("Skill","scorename")); + dummyText2.add(new StyledText(": ","separator")); + dummyText2.add(new StyledText("100 ","score")); + dummyText2.add(new StyledText("(","brackets")); + dummyText2.add(new StyledText("0 Deaths","etc")); + dummyText2.add(new StyledText(")\n","brackets")); + dummyText2.add(new StyledText("Explorer","scorename")); + dummyText2.add(new StyledText(": ","separator")); + dummyText2.add(new StyledText("99 ","score")); + dummyText2.add(new StyledText("(","brackets")); + dummyText2.add(new StyledText("Rooms O Secrets 39/40","etc")); + dummyText2.add(new StyledText(")\n","brackets")); + dummyText2.add(new StyledText("Time","scorename")); + dummyText2.add(new StyledText(": ","separator")); + dummyText2.add(new StyledText("100 ","score")); + dummyText2.add(new StyledText("Bonus","scorename")); + dummyText2.add(new StyledText(": ","separator")); + dummyText2.add(new StyledText("0 ","score")); + dummyText2.add(new StyledText("Total","scorename")); + dummyText2.add(new StyledText(": ","separator")); + dummyText2.add(new StyledText("299\n","score")); + dummyText2.add(new StyledText("S","currentScore")); + dummyText2.add(new StyledText("->","arrow")); + dummyText2.add(new StyledText("S+ ","nextScore")); + dummyText2.add(new StyledText("(","brackets")); + dummyText2.add(new StyledText("1 Required 1 crypt","required")); + dummyText2.add(new StyledText(")","brackets")); + + } + + @Override + public java.util.List<String> getUsedTextStyle() { + return Arrays.asList("scorename", "separator", "score", "brackets", "etc", "currentScore", "arrow", "nextScore", "required"); + + } + + @Override + public java.util.List<StyledText> getDummyText() { + + if (this.<Boolean>getParameter("verbose").getValue()) {return dummyText2;} else return dummyText; + } + + @Override + public java.util.List<StyledText> getText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + + ScoreCalculation score = calculateScore(); + if (score == null) return new ArrayList<StyledText>(); + int sum = score.time + score.skill + score.explorer + score.bonus; + if (this.<Boolean>getParameter("verbose").getValue()) { + actualBit.add(new StyledText("Skill", "scorename")); + actualBit.add(new StyledText(": ", "separator")); + actualBit.add(new StyledText(score.skill + " ", "score")); + actualBit.add(new StyledText("(", "brackets")); + actualBit.add(new StyledText(score.deaths + " Deaths", "etc")); + actualBit.add(new StyledText(")\n", "brackets")); + actualBit.add(new StyledText("Explorer", "scorename")); + actualBit.add(new StyledText(": ", "separator")); + actualBit.add(new StyledText(score.explorer + " ", "score")); + actualBit.add(new StyledText("(", "brackets")); + actualBit.add(new StyledText("Rooms " + (score.fullyCleared ? "O" : "X") + " Secrets " + score.secrets + "/" + score.effectiveTotalSecrets +" of "+score.getTotalSecrets() + (score.totalSecretsKnown ? "" : "?"), "etc")); + actualBit.add(new StyledText(")\n", "brackets")); + actualBit.add(new StyledText("Time", "scorename")); + actualBit.add(new StyledText(": ", "separator")); + actualBit.add(new StyledText(score.time + " ", "score")); + actualBit.add(new StyledText("Bonus", "scorename")); + actualBit.add(new StyledText(": ", "separator")); + actualBit.add(new StyledText(score.bonus + " ", "score")); + actualBit.add(new StyledText("Total", "scorename")); + actualBit.add(new StyledText(": ", "separator")); + actualBit.add(new StyledText(sum + "\n", "score")); + actualBit.addAll(buildRequirement(score)); + } else { + String letter = getLetter(sum); + actualBit.add(new StyledText("Score", "scorename")); + actualBit.add(new StyledText(": ", "separator")); + actualBit.add(new StyledText(sum + " ", "score")); + actualBit.add(new StyledText("(", "brackets")); + actualBit.add(new StyledText(letter, "currentScore")); + actualBit.add(new StyledText(")", "brackets")); + } + + return actualBit; + } + + @Data + @AllArgsConstructor + public static class ScoreCalculation { + private int skill, explorer, time, bonus, tombs; + private boolean fullyCleared; + private int secrets, totalSecrets, effectiveTotalSecrets; + private boolean totalSecretsKnown; + private int deaths; + } + + public int getPercentage() { + return skyblockStatus.getPercentage(); + } + public int getCompleteRooms() { + for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { + String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + if (name.startsWith("§r Completed Rooms: §r")) { + String milestone = TextUtils.stripColor(name).substring(18); + return Integer.parseInt(milestone); + } + } + return 0; + } + public int getTotalRooms() { + int compRooms = getCompleteRooms(); + if (compRooms == 0) return 100; + return (int) (100 * (compRooms / (double)getPercentage())); + } + public int getUndiscoveredPuzzles() { + int cnt = 0; + for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { + String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + if (name.startsWith("§r ???: ")) { + cnt ++; + } + } + return cnt; + } + + public ScoreCalculation calculateScore() { + if (!skyblockStatus.isOnDungeon()) return null; + DungeonContext context = skyblockStatus.getContext(); + if (context == null) return null; + if (!context.getMapProcessor().isInitialized()) return null; + + int skill = 100; + int deaths = 0; + { + deaths = FeatureRegistry.DUNGEON_DEATHS.getTotalDeaths(); + skill -= FeatureRegistry.DUNGEON_DEATHS.getTotalDeaths() * 2; + int totalCompRooms= 0; + int roomCnt = 0; + int roomSkillPenalty = 0; +// boolean bossroomIncomplete = true; + boolean traproomIncomplete = context.isTrapRoomGen(); + int incompletePuzzles = getUndiscoveredPuzzles(); + + for (DungeonRoom dungeonRoom : context.getDungeonRoomList()) { +// if (dungeonRoom.getColor() == 74 && dungeonRoom.getCurrentState() != DungeonRoom.RoomState.DISCOVERED) +// bossroomIncomplete = false; + if (dungeonRoom.getColor() == 62 && dungeonRoom.getCurrentState() != DungeonRoom.RoomState.DISCOVERED) + traproomIncomplete = false; + if (dungeonRoom.getCurrentState() != DungeonRoom.RoomState.DISCOVERED) + totalCompRooms += dungeonRoom.getUnitPoints().size(); + if (dungeonRoom.getColor() == 66 && (dungeonRoom.getCurrentState() == DungeonRoom.RoomState.DISCOVERED || dungeonRoom.getCurrentState() == DungeonRoom.RoomState.FAILED)) // INCOMPLETE PUZZLE ON MAP + incompletePuzzles++; + roomCnt += dungeonRoom.getUnitPoints().size(); + } + roomSkillPenalty += incompletePuzzles * 10; + if (context.getMapProcessor().getUndiscoveredRoom() != 0) + roomCnt = getTotalRooms(); + roomSkillPenalty += (roomCnt - totalCompRooms) * 4; +// if (bossroomIncomplete) roomSkillPenalty -=1; + if (traproomIncomplete) roomSkillPenalty -=1; + + + skill -= roomSkillPenalty; + + + + skill = MathHelper.clamp_int(skill, 0, 100); + } + int explorer = 0; + boolean fullyCleared = false; + boolean totalSecretsKnown = true; + int totalSecrets = 0; + int secrets = 0; + { + int completed = 0; + double total = 0; + + for (DungeonRoom dungeonRoom : context.getDungeonRoomList()) { + if (dungeonRoom.getCurrentState() != DungeonRoom.RoomState.DISCOVERED && dungeonRoom.getCurrentState() != DungeonRoom.RoomState.FAILED) + completed += dungeonRoom.getUnitPoints().size(); + total += dungeonRoom.getUnitPoints().size(); + } + + totalSecrets = FeatureRegistry.DUNGEON_SECRETS.getTotalSecretsInt() ; + totalSecretsKnown = FeatureRegistry.DUNGEON_SECRETS.sureOfTotalSecrets(); + + fullyCleared = completed >= getTotalRooms() && context.getMapProcessor().getUndiscoveredRoom() == 0; + explorer += MathHelper.clamp_int((int) Math.floor(6.0 / 10.0 * (context.getMapProcessor().getUndiscoveredRoom() != 0 ? getPercentage() : completed / total * 100)), 0, 60); + explorer += MathHelper.clamp_int((int) Math.floor(40 * (secrets = FeatureRegistry.DUNGEON_SECRETS.getSecretsFound()) / Math.ceil(totalSecrets * context.getSecretPercentage())),0,40); + } + int time = 0; + { + int maxTime = context.getMaxSpeed(); +// int timeSec = FeatureRegistry.DUNGEON_SBTIME.getTimeElapsed() / 1000 - maxTime + 480; +// +// if (timeSec <= 480) time = 100; +// else if (timeSec <= 580) time = (int) Math.ceil(148 - 0.1 * timeSec); +// else if (timeSec <= 980) time = (int) Math.ceil(119 - 0.05 * timeSec); +// else if (timeSec < 3060) time = (int) Math.ceil(3102 - (1/30.0) * timeSec); +// time = MathHelper.clamp_int(time, 0, 100); // just in case. + time = TimeScoreUtil.estimate(FeatureRegistry.DUNGEON_SBTIME.getTimeElapsed(), maxTime); + } + int bonus = 0; + int tombs; + { + bonus += tombs = MathHelper.clamp_int(FeatureRegistry.DUNGEON_TOMBS.getTombsFound(), 0, 5); + if (context.isGotMimic()) bonus += 2; + CompletableFuture<StaticResource> staticResourceCompletableFuture = StaticResourceCache.INSTANCE.getResource(StaticResourceCache.BONUS_SCORE); + if (staticResourceCompletableFuture.isDone()) { + try { + bonus += Integer.parseInt(staticResourceCompletableFuture.get().getValue().trim()); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + } + + // amazing thing + return new ScoreCalculation(skill, explorer, time, bonus, tombs, fullyCleared, secrets, totalSecrets, (int)Math.ceil (totalSecrets * context.getSecretPercentage()), totalSecretsKnown, deaths); + } + public String getLetter(int score) { + if (score <= 99) return "D"; + if (score <= 159) return "C"; + if (score <= 229) return "B"; + if (score <= 269) return "A"; + if (score <= 299) return "S"; + return "S+"; + } + public int getScoreRequirement(String letter) { + if (letter.equals("D")) return 0; + if (letter.equals("C")) return 100; + if (letter.equals("B")) return 160; + if (letter.equals("A")) return 230; + if (letter.equals("S")) return 270; + if (letter.equals("S+")) return 300; + return -1; + } + public String getNextLetter(String letter) { + if (letter.equals("D")) return "C"; + if (letter.equals("C")) return "B"; + if (letter.equals("B")) return "A"; + if (letter.equals("A")) return "S"; + if (letter.equals("S")) return "S+"; + else return null; + } + public List<StyledText> buildRequirement(ScoreCalculation calculation) { + List<StyledText> actualBit = new ArrayList<StyledText>(); + int current = calculation.time + calculation.bonus + calculation.explorer + calculation.skill; + String currentLetter = getLetter(current); + String nextLetter= getNextLetter(currentLetter); + if (nextLetter == null) { + actualBit.add(new StyledText("S+ Expected","nextScore")); + return actualBit; + } + int req = getScoreRequirement(nextLetter); + int reqPT2 = req- current; + int reqPT = req - current; + + int tombsBreakable = Math.min(5 - calculation.tombs, reqPT); + reqPT -= tombsBreakable; + + double secretPer = 40.0 / calculation.effectiveTotalSecrets; + int secrets = (int) Math.ceil(reqPT / secretPer); + + actualBit.add(new StyledText(currentLetter,"currentScore")); + actualBit.add(new StyledText("->","arrow")); + actualBit.add(new StyledText(nextLetter+" ","nextScore")); + actualBit.add(new StyledText("(","brackets")); + actualBit.add(new StyledText(reqPT2+" required "+tombsBreakable+" crypt "+secrets+" secrets","required")); + actualBit.add(new StyledText(")","brackets")); + return actualBit; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonSecrets.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonSecrets.java new file mode 100644 index 00000000..11de62a3 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonSecrets.java @@ -0,0 +1,144 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.scoreboard.ScorePlayerTeam; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureDungeonSecrets extends TextHUDFeature { + public FeatureDungeonSecrets() { + super("Dungeon.Dungeon Information", "Display Total # of Secrets", "Display how much total secrets have been found in a dungeon run.\n+ sign means DG does not know the correct number, but it's somewhere above that number.", "dungeon.stats.secrets", true, getFontRenderer().getStringWidth("Secrets: 999/999+ of 999+"), getFontRenderer().FONT_HEIGHT); + this.setEnabled(false); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("currentSecrets", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator2", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("totalSecrets", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("unknown", new AColor(0xFF, 0xFF,0x55,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + public int getSecretsFound() { + for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { + String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + if (name.startsWith("§r Secrets Found: §r§b") && !name.contains("%")) { + String noColor = TextUtils.stripColor(name); + return Integer.parseInt(noColor.substring(16)); + } + } + return 0; + } + public double getSecretPercentage() { + for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { + String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + if (name.startsWith("§r Secrets Found: §r") && name.contains("%")) { + String noColor = TextUtils.stripColor(name); + return Double.parseDouble(noColor.substring(16).replace("%", "")); + } + } + return 0; + } + + public int getTotalSecretsInt() { + if (getSecretsFound() != 0) return (int) Math.ceil (getSecretsFound() / getSecretPercentage() * 100); + DungeonContext context = skyblockStatus.getContext(); + int totalSecrets = 0; + for (DungeonRoom dungeonRoom : context.getDungeonRoomList()) { + if (dungeonRoom.getTotalSecrets() != -1) + totalSecrets += dungeonRoom.getTotalSecrets(); + } + return totalSecrets; + } + public boolean sureOfTotalSecrets() { + if (getSecretsFound() != 0) return true; + DungeonContext context = skyblockStatus.getContext(); + if (context.getMapProcessor().getUndiscoveredRoom() > 0) return false; + boolean allknown = true; + for (DungeonRoom dungeonRoom : context.getDungeonRoomList()) { + if (dungeonRoom.getTotalSecrets() == -1) allknown = false; + } + return allknown; + } + + public String getTotalSecrets() { + DungeonContext context = skyblockStatus.getContext(); + if (context == null) return "?"; + int totalSecrets = 0; + boolean allknown = true; + for (DungeonRoom dungeonRoom : context.getDungeonRoomList()) { + if (dungeonRoom.getTotalSecrets() != -1) + totalSecrets += dungeonRoom.getTotalSecrets(); + else allknown = false; + } + return totalSecrets + (allknown ? "":"+"); + } + + + private static final java.util.List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Secrets","title")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("999","currentSecrets")); + dummyText.add(new StyledText("/","separator2")); + dummyText.add(new StyledText("2","totalSecrets")); + dummyText.add(new StyledText("+","unknown")); + } + + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon(); + } + + @Override + public java.util.List<String> getUsedTextStyle() { + return Arrays.asList("title", "separator", "currentSecrets", "separator2", "totalSecrets", "unknown"); + } + + @Override + public java.util.List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public java.util.List<StyledText> getText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("Secrets","title")); + actualBit.add(new StyledText(": ","separator")); + actualBit.add(new StyledText(getSecretsFound() +"","currentSecrets")); + actualBit.add(new StyledText("/","separator2")); + actualBit.add(new StyledText((int)Math.ceil(getTotalSecretsInt() * DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext().getSecretPercentage())+" of "+getTotalSecretsInt(),"totalSecrets")); + actualBit.add(new StyledText(getTotalSecrets().contains("+") ? "+" : "","unknown")); + return actualBit; + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonTombs.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonTombs.java new file mode 100644 index 00000000..59c669bf --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureDungeonTombs.java @@ -0,0 +1,88 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.scoreboard.ScorePlayerTeam; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureDungeonTombs extends TextHUDFeature { + public FeatureDungeonTombs() { + super("Dungeon.Dungeon Information", "Display # of Crypts", "Display how much total crypts have been blown up in a dungeon run", "dungeon.stats.tombs", true, getFontRenderer().getStringWidth("Crypts: 42"), getFontRenderer().FONT_HEIGHT); + this.setEnabled(false); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("number", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + public int getTombsFound() { + for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { + String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + if (name.startsWith("§r Crypts: §r§6")) { + return Integer.parseInt(TextUtils.stripColor(name).substring(9)); + } + } + return 0; + } + + private static final java.util.List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Crypts","title")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("42","number")); + } + + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon(); + } + + @Override + public java.util.List<String> getUsedTextStyle() { + return Arrays.asList("title", "separator", "number"); + } + + @Override + public java.util.List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public java.util.List<StyledText> getText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("Crypts","title")); + actualBit.add(new StyledText(": ","separator")); + actualBit.add(new StyledText(getTombsFound()+"","number")); + return actualBit; + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureHideNameTags.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureHideNameTags.java new file mode 100644 index 00000000..b8985a78 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureHideNameTags.java @@ -0,0 +1,53 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.features.listener.EntityLivingRenderListener; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraftforge.client.event.RenderLivingEvent; + + +public class FeatureHideNameTags extends SimpleFeature implements EntityLivingRenderListener { + public FeatureHideNameTags() { + super("Dungeon.Mobs", "Hide mob nametags", "Hide mob nametags in dungeon", "dungeon.hidenametag", false); + } + + + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + @Override + public void onEntityRenderPre(RenderLivingEvent.Pre renderPlayerEvent) { + if (!isEnabled()) return; + if (!skyblockStatus.isOnDungeon()) return; + + if (renderPlayerEvent.entity instanceof EntityArmorStand) { + EntityArmorStand armorStand = (EntityArmorStand) renderPlayerEvent.entity; + if (armorStand.getAlwaysRenderNameTag()) + renderPlayerEvent.setCanceled(true); + } + } + + @Override + public void onEntityRenderPost(RenderLivingEvent.Post renderPlayerEvent) { + + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeaturePlayerESP.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeaturePlayerESP.java new file mode 100644 index 00000000..273a9bca --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeaturePlayerESP.java @@ -0,0 +1,111 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.features.listener.PlayerRenderListener; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; +import net.minecraftforge.client.event.RenderPlayerEvent; +import org.lwjgl.opengl.GL11; + + +public class FeaturePlayerESP extends SimpleFeature implements PlayerRenderListener { + public FeaturePlayerESP() { + super("Dungeon.Teammates", "See players through walls", "See players through walls", "dungeon.playeresp", false); + setEnabled(false); + } + + + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + private boolean preCalled = false; + @Override + public void onEntityRenderPre(RenderPlayerEvent.Pre renderPlayerEvent) { + + + if (preCalled) return; + if (!isEnabled()) return; + + + DungeonContext dungeonContext = skyblockStatus.getContext(); + if (dungeonContext == null) return; + if (!dungeonContext.getPlayers().contains(renderPlayerEvent.entityPlayer.getName())) { + return; + } + + preCalled = true; + + GL11.glEnable(GL11.GL_STENCIL_TEST); + GL11.glClearStencil(0); + GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT); + + GL11.glStencilMask(0xFF); + GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF); + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_REPLACE, GL11.GL_REPLACE); + + EntityPlayer entity = renderPlayerEvent.entityPlayer; + InventoryPlayer inv = entity.inventory; + ItemStack[] armor = inv.armorInventory; + inv.armorInventory = new ItemStack[4]; + ItemStack[] hand = inv.mainInventory; + inv.mainInventory = new ItemStack[36]; + + float f = entity.prevRotationYaw + (entity.rotationYaw - entity.prevRotationYaw) * renderPlayerEvent.partialRenderTick; + try { + renderPlayerEvent.renderer.doRender((AbstractClientPlayer) renderPlayerEvent.entityPlayer, renderPlayerEvent.x, renderPlayerEvent.y, renderPlayerEvent.z, f, renderPlayerEvent.partialRenderTick); + } catch (Throwable t) {} + + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); + GL11.glStencilFunc(GL11.GL_NOTEQUAL, 1, 0xff); + GL11.glDepthMask(false); + GL11.glDepthFunc(GL11.GL_GEQUAL); + + GlStateManager.pushMatrix(); + GlStateManager.translate(renderPlayerEvent.x, renderPlayerEvent.y + 0.9, renderPlayerEvent.z); + GlStateManager.scale(1.2f, 1.1f, 1.2f); + renderPlayerEvent.renderer.setRenderOutlines(true); + try { + renderPlayerEvent.renderer.doRender((AbstractClientPlayer) renderPlayerEvent.entityPlayer, 0,-0.9,0, f, renderPlayerEvent.partialRenderTick); + } catch (Throwable t) {} + + renderPlayerEvent.renderer.setRenderOutlines(false); + GL11.glDepthFunc(GL11.GL_LEQUAL); + GlStateManager.popMatrix(); + + GL11.glDisable(GL11.GL_STENCIL_TEST); // Turn this shit off! + + inv.armorInventory = armor; + inv.mainInventory = hand; + + preCalled = false; + + } + + @Override + public void onEntityRenderPost(RenderPlayerEvent.Post renderPlayerEvent) { + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeaturePressAnyKeyToCloseChest.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeaturePressAnyKeyToCloseChest.java new file mode 100644 index 00000000..ffff3a08 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeaturePressAnyKeyToCloseChest.java @@ -0,0 +1,89 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.features.listener.GuiClickListener; +import kr.syeyoung.dungeonsguide.features.listener.KeyInputListener; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.features.impl.boss.FeatureChestPrice; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; +import net.minecraftforge.client.event.GuiScreenEvent; +import org.lwjgl.input.Mouse; + +public class FeaturePressAnyKeyToCloseChest extends SimpleFeature implements KeyInputListener, GuiClickListener { + public FeaturePressAnyKeyToCloseChest() { + super("Dungeon", "Press Any Mouse Button or Key to close Secret Chest", "dungeon.presskeytoclose"); + parameters.put("threshold", new FeatureParameter<Integer>("threshold", "Price Threshold", "The maximum price of item for chest to be closed. Default 1m", 1000000, "integer")); + } + + @Override + public void onKeyInput(GuiScreenEvent.KeyboardInputEvent keyboardInputEvent) { + GuiScreen screen = Minecraft.getMinecraft().currentScreen; + if (!isEnabled()) return; + if (!DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnDungeon()) return; + + if (screen instanceof GuiChest){ + ContainerChest ch = (ContainerChest) ((GuiChest)screen).inventorySlots; + if (!("Large Chest".equals(ch.getLowerChestInventory().getName()) + || "Chest".equals(ch.getLowerChestInventory().getName()))) return; + IInventory actualChest = ch.getLowerChestInventory(); + + int priceSum = 0; + for (int i = 0; i < actualChest.getSizeInventory(); i++) { + priceSum += FeatureChestPrice.getPrice(actualChest.getStackInSlot(i)); + } + + int threshold = this.<Integer>getParameter("threshold").getValue(); + if (priceSum < threshold) { + Minecraft.getMinecraft().thePlayer.closeScreen(); + } + } + } + + @Override + public void onMouseInput(GuiScreenEvent.MouseInputEvent.Pre mouseInputEvent) { + GuiScreen screen = Minecraft.getMinecraft().currentScreen; + if (!isEnabled()) return; + if (!DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnDungeon()) return; + if (Mouse.getEventButton() == -1) return; + + if (screen instanceof GuiChest){ + ContainerChest ch = (ContainerChest) ((GuiChest)screen).inventorySlots; + if (!("Large Chest".equals(ch.getLowerChestInventory().getName()) + || "Chest".equals(ch.getLowerChestInventory().getName()))) return; + IInventory actualChest = ch.getLowerChestInventory(); + + int priceSum = 0; + for (int i = 0; i < actualChest.getSizeInventory(); i++) { + priceSum += FeatureChestPrice.getPrice(actualChest.getStackInSlot(i)); + } + + int threshold = this.<Integer>getParameter("threshold").getValue(); + if (priceSum < threshold) { + Minecraft.getMinecraft().thePlayer.closeScreen(); + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureWarnLowHealth.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureWarnLowHealth.java new file mode 100644 index 00000000..15f02e86 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureWarnLowHealth.java @@ -0,0 +1,106 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.scoreboard.Score; +import net.minecraft.scoreboard.ScoreObjective; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.scoreboard.Scoreboard; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + +public class FeatureWarnLowHealth extends TextHUDFeature { + public FeatureWarnLowHealth() { + super("Dungeon.Teammates", "Low Health Warning", "Warn if someone is on low health", "dungeon.lowhealthwarn", false, 500, 20); + parameters.put("threshold", new FeatureParameter<Integer>("threshold", "Health Threshold", "Health Threshold for this feature to be toggled. default to 500", 500, "integer")); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("number", new AColor(0xFF, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("unit", new AColor(0xFF, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + setEnabled(false); + } + + + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnDungeon(); + } + + @Override + public List<String> getUsedTextStyle() { + return Arrays.asList("title", "separator", "number", "unit"); + } + + private static final java.util.List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("DungeonsGuide","title")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("500","number")); + dummyText.add(new StyledText("hp","unit")); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public List<StyledText> getText() { + String lowestHealthName = ""; + int lowestHealth = 999999999; + Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard(); + ScoreObjective objective = scoreboard.getObjectiveInDisplaySlot(1); + for (Score sc : scoreboard.getSortedScores(objective)) { + ScorePlayerTeam scorePlayerTeam = scoreboard.getPlayersTeam(sc.getPlayerName()); + String line = ScorePlayerTeam.formatPlayerName(scorePlayerTeam, sc.getPlayerName()).trim(); + String stripped = TextUtils.keepScoreboardCharacters(TextUtils.stripColor(line)); + if (line.contains("[") && line.endsWith("❤")) { + String name = stripped.split(" ")[stripped.split(" ").length - 2]; + int health = Integer.parseInt(stripped.split(" ")[stripped.split(" ").length - 1]); + if (health < lowestHealth) { + lowestHealth = health; + lowestHealthName = name; + } + } + } + if (lowestHealth > this.<Integer>getParameter("threshold").getValue()) return new ArrayList<StyledText>(); + + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText(lowestHealthName,"title")); + actualBit.add(new StyledText(": ","separator")); + actualBit.add(new StyledText(lowestHealth+"","number")); + actualBit.add(new StyledText("hp","unit")); + return actualBit; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureWatcherWarning.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureWatcherWarning.java new file mode 100644 index 00000000..bc48d51f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/dungeon/FeatureWatcherWarning.java @@ -0,0 +1,87 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.dungeon; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.ChatListener; +import kr.syeyoung.dungeonsguide.features.listener.DungeonEndListener; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +public class FeatureWatcherWarning extends TextHUDFeature implements ChatListener, DungeonEndListener { + + public FeatureWatcherWarning() { + super("Dungeon.Blood Room","Watcher Spawn Alert", "Alert when watcher says 'That will be enough for now'", "dungen.watcherwarn", true, getFontRenderer().getStringWidth("Watcher finished spawning all mobs!"), getFontRenderer().FONT_HEIGHT); + getStyles().add(new TextStyle("warning", new AColor(0xFF, 0x69,0x17,255), new AColor(0, 0,0,0), false)); + setEnabled(false); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + @Override + public boolean isHUDViewable() { + return warning > System.currentTimeMillis(); + } + + @Override + public List<String> getUsedTextStyle() { + return Collections.singletonList("warning"); + } + + private final UUID lastRoomUID = UUID.randomUUID(); + private long warning = 0; + + private static final List<StyledText> text = new ArrayList<StyledText>(); + static { + text.add(new StyledText("Watcher finished spawning all mobs!", "warning")); + } + + @Override + public List<StyledText> getText() { + return text; + } + + @Override + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + if (clientChatReceivedEvent.message.getFormattedText().equals("§r§c[BOSS] The Watcher§r§f: That will be enough for now.§r")) { + warning = System.currentTimeMillis() + 2500; + DungeonContext context = skyblockStatus.getContext(); + if (context ==null) return; + for (DungeonRoom dungeonRoom : context.getDungeonRoomList()) { + if (dungeonRoom != null && dungeonRoom.getColor() == 18) + dungeonRoom.setCurrentState(DungeonRoom.RoomState.DISCOVERED); + } + } + } + + @Override + public void onDungeonEnd() { + warning = 0; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureAutoAcceptReparty.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureAutoAcceptReparty.java new file mode 100644 index 00000000..7be4b22b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureAutoAcceptReparty.java @@ -0,0 +1,68 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.features.listener.ChatListener; +import kr.syeyoung.dungeonsguide.chat.ChatProcessor; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +public class FeatureAutoAcceptReparty extends SimpleFeature implements ChatListener { + public FeatureAutoAcceptReparty() { + super("Party.Reparty", "Auto accept reparty", "Automatically accept reparty", "qol.autoacceptreparty", true); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + private String lastDisband; + @Override + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + if (clientChatReceivedEvent.message.getFormattedText().endsWith("§ehas disbanded the party!§r")) { + lastDisband = null; + String[] texts = TextUtils.stripColor(clientChatReceivedEvent.message.getFormattedText()).split(" "); + for (String s : texts) { + if (s.isEmpty()) continue; + if (s.startsWith("[")) continue; + if (s.equalsIgnoreCase("has")) break; + lastDisband = s; + break; + } + } else if (clientChatReceivedEvent.message.getFormattedText().contains("§ehas invited you to join their party!")) { + String[] texts = TextUtils.stripColor(clientChatReceivedEvent.message.getFormattedText()).split(" "); + boolean equals = false; + for (String s : texts) { + if (s.isEmpty()) continue; + if (s.startsWith("[")) continue; + if (s.equalsIgnoreCase("has")) continue; + if (s.equalsIgnoreCase(lastDisband)) { + equals = true; + break; + } + } + + if (equals && isEnabled()) { + ChatProcessor.INSTANCE.addToChatQueue("/p accept " + lastDisband, () -> {}, true); + lastDisband = null; + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureCooldownCounter.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureCooldownCounter.java new file mode 100644 index 00000000..5499353a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureCooldownCounter.java @@ -0,0 +1,96 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.DungeonQuitListener; +import kr.syeyoung.dungeonsguide.features.listener.GuiOpenListener; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.inventory.ContainerChest; +import net.minecraftforge.client.event.GuiOpenEvent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureCooldownCounter extends TextHUDFeature implements DungeonQuitListener, GuiOpenListener { + public FeatureCooldownCounter() { + super("Dungeon", "Dungeon Cooldown Counter", "Counts 10 seconds after leaving dungeon", "qol.cooldown", true, getFontRenderer().getStringWidth("Cooldown: 10s "), getFontRenderer().FONT_HEIGHT); + getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("number", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + } + + private long leftDungeonTime = 0L; + + private static final java.util.List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Cooldown","title")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("20s","number")); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public boolean isHUDViewable() { + return System.currentTimeMillis() - leftDungeonTime < 20000; + } + + @Override + public java.util.List<String> getUsedTextStyle() { + return Arrays.asList("title", "separator", "number"); + } + + @Override + public List<StyledText> getText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + actualBit.add(new StyledText("Cooldown","title")); + actualBit.add(new StyledText(": ","separator")); + actualBit.add(new StyledText((20 - (System.currentTimeMillis() - leftDungeonTime) / 1000)+"s","number")); + return actualBit; + } + + @Override + public boolean doesScaleWithHeight() { + return true; + } + + @Override + public void onDungeonQuit() { + leftDungeonTime = System.currentTimeMillis(); + } + + @Override + public void onGuiOpen(GuiOpenEvent rendered) { + if (!(rendered.gui instanceof GuiChest)) return; + ContainerChest chest = (ContainerChest) ((GuiChest) rendered.gui).inventorySlots; + if (chest.getLowerChestInventory().getName().contains("On cooldown!")) { + leftDungeonTime = System.currentTimeMillis(); + } else if (chest.getLowerChestInventory().getName().contains("Error")) { + leftDungeonTime = System.currentTimeMillis(); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureCopyMessages.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureCopyMessages.java new file mode 100644 index 00000000..d2b23e48 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureCopyMessages.java @@ -0,0 +1,42 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc; + +import kr.syeyoung.dungeonsguide.features.listener.ChatListener; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.event.ClickEvent; +import net.minecraft.event.HoverEvent; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatStyle; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +public class FeatureCopyMessages extends SimpleFeature implements ChatListener { + public FeatureCopyMessages() { + super("Misc.Chat", "Copy Chat Messages", "Click on copy to copy", "etc.copymsg"); + setEnabled(false); + } + @Override + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + if (!isEnabled()) return; + if (clientChatReceivedEvent.type == 2) return; + + clientChatReceivedEvent.message.appendSibling(new ChatComponentText(" §7[Copy]").setChatStyle(new ChatStyle().setChatClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, TextUtils.stripColor(clientChatReceivedEvent.message.getFormattedText()))).setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText("§eCopy Message"))))); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureDecreaseExplosionSound.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureDecreaseExplosionSound.java new file mode 100644 index 00000000..2786ca53 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureDecreaseExplosionSound.java @@ -0,0 +1,55 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.features.listener.SoundListener; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraftforge.client.event.sound.PlaySoundEvent; + +public class FeatureDecreaseExplosionSound extends SimpleFeature implements SoundListener { + public FeatureDecreaseExplosionSound() { + super("Misc", "Decrease Explosion sound effect", "Decreases volume of explosions while on skyblock", "qol.explosionsound"); + parameters.put("sound", new FeatureParameter<Float>("sound", "Sound Multiplier %", "The volume of explosion effect will be multiplied by this value. 0~100", 10.0f, "float")); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + @Override + public void onSound(PlaySoundEvent soundEvent) { + if (!skyblockStatus.isOnSkyblock()) return; + + if (soundEvent.name.equalsIgnoreCase("random.explode") && soundEvent.result instanceof PositionedSoundRecord) { + PositionedSoundRecord positionedSoundRecord = (PositionedSoundRecord) soundEvent.result; + PositionedSoundRecord neweff = new PositionedSoundRecord( + positionedSoundRecord.getSoundLocation(), + positionedSoundRecord.getVolume() * (this.<Float>getParameter("sound").getValue() / 100), + positionedSoundRecord.getPitch(), + positionedSoundRecord.getXPosF(), + positionedSoundRecord.getYPosF(), + positionedSoundRecord.getZPosF() + ); + + soundEvent.result = neweff; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureDisableMessage.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureDisableMessage.java new file mode 100644 index 00000000..0e65f849 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureDisableMessage.java @@ -0,0 +1,79 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.features.listener.ChatListener; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.regex.Pattern; + +public class FeatureDisableMessage extends SimpleFeature implements ChatListener { + @Data + @AllArgsConstructor + public static class MessageData { + private Pattern pattern; + private String name; + private String description; + private String key; + } + + private static final MessageData[] PRE_DEFINED = new MessageData[] { + new MessageData(Pattern.compile("§r§cThere are blocks in the way!§r"), "Aote block message", "\"There are blocks in the way!\"", "aote"), + new MessageData(Pattern.compile("§r§cThis ability is currently on cooldown for .+ more seconds?\\.§r"), "Ability cooldown message", "\"This ability is currently on cooldown for 3 more seconds.\"", "cooldown"), + new MessageData(Pattern.compile("§r§cThis ability is on cooldown for .+s\\.§r"), "Ability cooldown message2", "\"This ability is on cooldown for 3s.\"", "cooldown2"), + new MessageData(Pattern.compile("§r§cWhow! Slow down there!§r"), "Grappling hook cooldown", "\"Whow! Slow down there!\"", "grappling"), + new MessageData(Pattern.compile("§r§cNo more charges, next one in §r§e.+§r§cs!§r"), "Zombie Sword Charging", "\"No more charges, next one in 3s!\"", "zombie"), + new MessageData(Pattern.compile("§r§7Your .+ hit §r§c.+ §r§7enem(?:y|ies) for §r§c.+ §r§7damage\\.§r"), "Ability Damage", "\"Your blahblah hit 42 enemy for a lots of damage\"", "ability"), + new MessageData(Pattern.compile("§r§cYou do not have enough mana to do this!§r"), "Not enough mana", "\"You do not have enough mana to do this!\"", "mana"), + new MessageData(Pattern.compile("§r§aUsed §r.+§r§a!§r"), "Dungeon Ability Usage", "\"Used Guided Sheep!\" and such", "dungeonability"), + new MessageData(Pattern.compile("§r.+§r§a is ready to use! Press §r.+§r§a to activate it!§r"), "Ready to use message", "\"Blah is ready to use! Press F to activate it!", "readytouse"), + new MessageData(Pattern.compile("§r.+ §r§ais now available!§r"), "Ability Available","\"blah is now available!\"", "available"), + new MessageData(Pattern.compile("§r§cThe Stone doesn't seem to do anything here\\.§r"), "Stone Message", "\"The Stone doesn't seem to do anything here\"", "stone"), + new MessageData(Pattern.compile("§r§cNo target found!§r"), "Voodoo Doll No Target", "\"No target found!\"", "voodotarget") + }; + + public FeatureDisableMessage() { + super("Misc.Chat", "Disable ability messages", "Do not let ability messages show up in chatbox\nclick on Edit for more precise settings", "fixes.messagedisable", true); + for (MessageData messageData : PRE_DEFINED) { + this.parameters.put(messageData.key, new FeatureParameter<Boolean>(messageData.key, messageData.name, messageData.description, true, "boolean")); + } + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + @Override + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + if (clientChatReceivedEvent.type == 2) return; + if (!isEnabled()) return; + if (!skyblockStatus.isOnSkyblock()) return; + String msg = clientChatReceivedEvent.message.getFormattedText(); + for (MessageData md:PRE_DEFINED) { + if (this.<Boolean>getParameter(md.key).getValue() && md.pattern.matcher(msg).matches()) { + clientChatReceivedEvent.setCanceled(true); + return; + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeaturePenguins.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeaturePenguins.java new file mode 100644 index 00000000..ce65a273 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeaturePenguins.java @@ -0,0 +1,168 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc; + +import com.google.common.collect.ImmutableMap; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.features.listener.PlayerRenderListener; +import kr.syeyoung.dungeonsguide.features.listener.TextureStichListener; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.resources.model.IBakedModel; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.item.*; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.RenderPlayerEvent; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.client.model.obj.OBJLoader; +import net.minecraftforge.client.model.obj.OBJModel; + +import java.io.IOException; + + +public class FeaturePenguins extends SimpleFeature implements PlayerRenderListener, TextureStichListener { + public FeaturePenguins() { + super("Misc", "Penguins", "Awwww", "etc.penguin", false); + OBJLoader.instance.addDomain("dungeonsguide"); + + } + @Override + public void onTextureStitch(TextureStitchEvent event) { + if (event instanceof TextureStitchEvent.Pre) { + objModel = null; + ResourceLocation modelResourceLocation = new ResourceLocation("dungeonsguide:models/penguin.obj"); + try { + objModel = (OBJModel) OBJLoader.instance.loadModel(modelResourceLocation); + objModel = (OBJModel) objModel.process(new ImmutableMap.Builder<String, String>().put("flip-v", "true").build()); + for (String obj : objModel.getMatLib().getMaterialNames()) { + ResourceLocation resourceLocation = objModel.getMatLib().getMaterial(obj).getTexture().getTextureLocation(); + event.map.registerSprite(resourceLocation); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + if (objModel != null && event instanceof TextureStitchEvent.Post) { + model = objModel.bake(objModel.getDefaultState(), DefaultVertexFormats.ITEM, ModelLoader.defaultTextureGetter()); + } + } + + + private OBJModel objModel; + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + private IBakedModel model; + + @Override + public void onEntityRenderPre(RenderPlayerEvent.Pre renderPlayerEvent) { + + if (!isEnabled()) return; + if (renderPlayerEvent.entityPlayer.isInvisible()) return; + renderPlayerEvent.setCanceled(true); + GlStateManager.pushMatrix(); + GlStateManager.color(1,1,1,1); + GlStateManager.translate(renderPlayerEvent.x, renderPlayerEvent.y, renderPlayerEvent.z); + if (renderPlayerEvent.entityPlayer.isSneaking()) + { + GlStateManager.translate(0.0F, -0.203125F, 0.0F); + } + float f1 = renderPlayerEvent.entityPlayer.prevRotationYawHead + (renderPlayerEvent.entityPlayer.rotationYawHead - renderPlayerEvent.entityPlayer.prevRotationYawHead) * renderPlayerEvent.partialRenderTick; + GlStateManager.rotate(f1+180,0,-1,0); + Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture); + + Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelRenderer().renderModelBrightnessColor( + model, 1,1,1,1 + ); + GlStateManager.popMatrix(); + + + EntityPlayer entitylivingbaseIn = renderPlayerEvent.entityPlayer; + { + ItemStack itemstack = entitylivingbaseIn.getHeldItem(); + + if (itemstack != null) + { + GlStateManager.pushMatrix(); + GlStateManager.translate(renderPlayerEvent.x, renderPlayerEvent.y, renderPlayerEvent.z); + if (renderPlayerEvent.entityPlayer.isSneaking()) + { + GlStateManager.translate(0.0F, -0.203125F, 0.0F); + } + GlStateManager.rotate(f1+180, 0.0f, -1.0f, 0.0f); + GlStateManager.translate(0,1.30 ,-0.5); + + + + if (entitylivingbaseIn.fishEntity != null) + { + itemstack = new ItemStack(Items.fishing_rod, 0); + } + + Item item = itemstack.getItem(); + Minecraft minecraft = Minecraft.getMinecraft(); + + GlStateManager.rotate(180, 0.0f, 0.0f, 1.0f); + if (item.isFull3D()) { + GlStateManager.translate(0.05,0,0); + GlStateManager.rotate(90, 0.0f, 0.0f, 1.0f); + GlStateManager.rotate(-45, 1.0f, 0.0f, 0.0f); + } else if (item instanceof ItemBow) { + GlStateManager.translate(0,0.1, -0); + GlStateManager.rotate(90, 0.0f, 1.0f, 0.0f); + GlStateManager.rotate(-90, 0.0f, 0.0f, 1.0f); + } else if (item instanceof ItemBlock && Block.getBlockFromItem(item).getRenderType() == 2) { + GlStateManager.translate(0,-0.20,0.1); + GlStateManager.translate(0.0F, 0.1875F, -0.3125F); + GlStateManager.rotate(-25.0F, 1.0F, 0.0F, 0.0F); + GlStateManager.rotate(45.0F, 0.0F, 1.0F, 0.0F); + f1 = 0.375F; + GlStateManager.scale(-f1, -f1, f1); + } else if (item instanceof ItemBlock) { + GlStateManager.translate(0.0F, 0.05, 0.1); + GlStateManager.rotate(-25.0F, 1.0F, 0.0F, 0.0F); + } else { + GlStateManager.translate(0,-0.1, 0.1); + } + + GlStateManager.scale(0.8,0.8,0.8); + + minecraft.getItemRenderer().renderItem(entitylivingbaseIn, itemstack, ItemCameraTransforms.TransformType.THIRD_PERSON); + GlStateManager.popMatrix(); + } + } + + + renderPlayerEvent.renderer.renderName((AbstractClientPlayer) renderPlayerEvent.entityPlayer, renderPlayerEvent.x, renderPlayerEvent.y, renderPlayerEvent.z); + + + } + + @Override + public void onEntityRenderPost(RenderPlayerEvent.Post renderPlayerEvent) { + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureRepartyCommand.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureRepartyCommand.java new file mode 100644 index 00000000..e4eb8a22 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureRepartyCommand.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc; + +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +public class FeatureRepartyCommand extends SimpleFeature { + public FeatureRepartyCommand() { + super("Party.Reparty", "Enable Reparty Command From DG", "if you disable, /dg reparty will still work, Auto reparty will still work\nRequires Restart to get applied", "qol.reparty"); + parameters.put("command", new FeatureParameter<String>("command", "The Command", "Command that the reparty will be bound to", "reparty", "string")); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureTooltipDungeonStat.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureTooltipDungeonStat.java new file mode 100644 index 00000000..533400aa --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureTooltipDungeonStat.java @@ -0,0 +1,52 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc; + +import kr.syeyoung.dungeonsguide.features.listener.TooltipListener; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; + +public class FeatureTooltipDungeonStat extends SimpleFeature implements TooltipListener { + public FeatureTooltipDungeonStat() { + super("Misc", "Dungeon Item Stats", "Shows quality of dungeon items (floor, percentage)", "tooltip.dungeonitem"); + } + + @Override + public void onTooltip(ItemTooltipEvent event) { + if (!isEnabled()) return; + + ItemStack hoveredItem = event.itemStack; + NBTTagCompound compound = hoveredItem.getTagCompound(); + if (compound == null) + return; + if (!compound.hasKey("ExtraAttributes")) + return; + NBTTagCompound nbtTagCompound = compound.getCompoundTag("ExtraAttributes"); + + int floor = nbtTagCompound.getInteger("item_tier"); + int percentage = nbtTagCompound.getInteger("baseStatBoostPercentage"); + + if (nbtTagCompound.hasKey("item_tier")) + event.toolTip.add("§7Obtained in: §c"+(floor == 0 ? "Entrance" : "Floor "+floor)); + if (nbtTagCompound.hasKey("baseStatBoostPercentage")) + event.toolTip.add("§7Stat Percentage: §"+(percentage == 50 ? "6§l":"c")+(percentage * 2)+"%"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureTooltipPrice.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureTooltipPrice.java new file mode 100644 index 00000000..aaf4c01b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureTooltipPrice.java @@ -0,0 +1,111 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc; + +import kr.syeyoung.dungeonsguide.features.listener.TooltipListener; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.utils.AhUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import org.lwjgl.input.Keyboard; + +import java.util.Comparator; +import java.util.Set; +import java.util.TreeSet; + +public class FeatureTooltipPrice extends SimpleFeature implements TooltipListener { + public FeatureTooltipPrice() { + super("Misc.API Features", "Item Price", "Shows price of items", "tooltip.price"); + parameters.put("reqShift", new FeatureParameter<Boolean>("reqShift", "Require Shift", "If shift needs to be pressed in order for this feature to be activated", false, "boolean")); + setEnabled(false); + } + + @Override + public void onTooltip(ItemTooltipEvent event) { + if (!isEnabled()) return; + + boolean activated = !this.<Boolean>getParameter("reqShift").getValue() || Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + + ItemStack hoveredItem = event.itemStack; + NBTTagCompound compound = hoveredItem.getTagCompound(); + if (compound == null) + return; + if (!compound.hasKey("ExtraAttributes")) + return; + if (!activated) { + event.toolTip.add("§7Shift to view price"); + return; + } + + final String id = compound.getCompoundTag("ExtraAttributes").getString("id"); + if (id.equals("ENCHANTED_BOOK")) { + final NBTTagCompound enchants = compound.getCompoundTag("ExtraAttributes").getCompoundTag("enchantments"); + Set<String> keys = enchants.getKeySet(); + Set<String> actualKeys = new TreeSet<String>(new Comparator<String>() { + public int compare(String o1, String o2) { + String id2 = id + "::" + o1 + "-" + enchants.getInteger(o1); + AhUtils.AuctionData auctionData = AhUtils.auctions.get(id2); + long price1 = (auctionData == null) ? 0 : auctionData.lowestBin; + String id3 = id + "::" + o2 + "-" + enchants.getInteger(o2); + AhUtils.AuctionData auctionData2 = AhUtils.auctions.get(id3); + long price2 = (auctionData2 == null) ? 0 : auctionData2.lowestBin; + return (compare2(price1, price2) == 0) ? o1.compareTo(o2) : compare2(price1, price2); + } + + public int compare2(long y, long x) { + return (x < y) ? -1 : ((x == y) ? 0 : 1); + } + }); + actualKeys.addAll(keys); + int totalLowestPrice = 0; + int iterations = 0; + for (String key : actualKeys) { + iterations++; + String id2 = id + "::" + key + "-" + enchants.getInteger(key); + AhUtils.AuctionData auctionData = AhUtils.auctions.get(id2); + if (auctionData == null) { + if (iterations < 10) + event.toolTip.add("§f"+ key + " " + enchants.getInteger(key) + "§7: §cn/a"); + continue; + } + if (iterations < 10) + event.toolTip.add("§f"+ key + " " + enchants.getInteger(key) + "§7: §e"+ TextUtils.format( auctionData.lowestBin)); + totalLowestPrice += auctionData.lowestBin; + } + if (iterations >= 10) + event.toolTip.add("§7"+ (iterations - 10) + " more enchants... "); + event.toolTip.add("§fTotal Lowest§7: §e"+ TextUtils.format(totalLowestPrice)); + } else { + AhUtils.AuctionData auctionData = AhUtils.auctions.get(id); + event.toolTip.add(""); + if (auctionData == null) { + event.toolTip.add("§fLowest ah §7: §cn/a"); + event.toolTip.add("§fBazaar sell price §7: §cn/a"); + event.toolTip.add("§fBazaar buy price §7: §cn/a"); + } else { + event.toolTip.add("§fLowest ah §7: " + ((auctionData.lowestBin != -1) ? ("§e"+ TextUtils.format(auctionData.lowestBin)) : "§cn/a")); + event.toolTip.add("§fBazaar sell price §7: " + ((auctionData.sellPrice == -1) ? "§cn/a": ("§e"+ TextUtils.format(auctionData.sellPrice)))); + event.toolTip.add("§fBazaar buy price §7: " + ((auctionData.buyPrice == -1) ? "§cn/a": ("§e"+ TextUtils.format(auctionData.buyPrice)))); + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureUpdateAlarm.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureUpdateAlarm.java new file mode 100644 index 00000000..eec4b40b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/FeatureUpdateAlarm.java @@ -0,0 +1,63 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc; + +import kr.syeyoung.dungeonsguide.features.listener.StompConnectedListener; +import kr.syeyoung.dungeonsguide.features.listener.TickListener; +import kr.syeyoung.dungeonsguide.events.StompConnectedEvent; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.stomp.StompInterface; +import kr.syeyoung.dungeonsguide.stomp.StompMessageHandler; +import kr.syeyoung.dungeonsguide.stomp.StompPayload; +import kr.syeyoung.dungeonsguide.stomp.StompSubscription; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ChatComponentText; + +public class FeatureUpdateAlarm extends SimpleFeature implements StompConnectedListener, StompMessageHandler, TickListener { + public FeatureUpdateAlarm() { + super("Misc", "Update Alarm","Show a warning in chat when a version has been released.", "etc.updatealarm", true); + } + + private StompPayload stompPayload; + @Override + public void handle(StompInterface stompInterface, StompPayload stompPayload) { + this.stompPayload = stompPayload; + } + + @Override + public void onTick() { + if (stompPayload != null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(stompPayload.payload())); + stompPayload = null; + Minecraft.getMinecraft().thePlayer.playSound("random.successful_hit", 1f,1f); + } + } + + @Override + public void onStompConnected(StompConnectedEvent event) { + event.getStompInterface().subscribe(StompSubscription.builder() + .destination("/topic/updates") + .ackMode(StompSubscription.AckMode.AUTO) + .stompMessageHandler(this).build()); + event.getStompInterface().subscribe(StompSubscription.builder() + .destination("/user/queue/messages") + .ackMode(StompSubscription.AckMode.AUTO) + .stompMessageHandler(this).build()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/ability/FeatureAbilityCooldown.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/ability/FeatureAbilityCooldown.java new file mode 100644 index 00000000..667b1cd4 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/ability/FeatureAbilityCooldown.java @@ -0,0 +1,402 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc.ability; + +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.features.listener.TickListener; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.listener.ChatListener; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FeatureAbilityCooldown extends TextHUDFeature implements ChatListener, TickListener { + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + public FeatureAbilityCooldown() { + super("Misc", "View Ability Cooldowns", "A handy hud for viewing cooldown abilities", "etc.abilitycd2", false, 100, getFontRenderer().FONT_HEIGHT * 5); + getStyles().add(new TextStyle("abilityname", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("number", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("unit",new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("ready",new AColor(0xDF, 0x00,0x67,255), new AColor(0, 0,0,0), false)); + this.parameters.put("disable", new FeatureParameter<Boolean>("disable", "Disable outside of dungeon", "Disable the feature when out of dungeon", false, "boolean")); + this.parameters.put("decimal", new FeatureParameter<Integer>("decimal", "Decimal places", "ex) 2 -> Cooldown: 3.21 3-> Cooldown: 3.210", 0, "integer")); + } + + @Override + public boolean isHUDViewable() { + return skyblockStatus.isOnSkyblock() && (!this.<Boolean>getParameter("disable").getValue() || (this.<Boolean>getParameter("disable").getValue() && skyblockStatus.isOnDungeon())); + } + + @Override + public boolean doesScaleWithHeight() { + return false; + } + + @Override + public List<String> getUsedTextStyle() { + return Arrays.asList("abilityname", "separator", "number", "unit", "ready"); + } + + private static final List<StyledText> dummy = new ArrayList<>(); + + static { + dummy.add(new StyledText("Random Ability", "abilityname")); + dummy.add(new StyledText(": ", "separator")); + dummy.add(new StyledText("10", "number")); + dummy.add(new StyledText("s\n", "unit")); + dummy.add(new StyledText("Random Ability2", "abilityname")); + dummy.add(new StyledText(": ", "separator")); + dummy.add(new StyledText("10", "number")); + dummy.add(new StyledText("m ", "unit")); + dummy.add(new StyledText("9", "number")); + dummy.add(new StyledText("s\n", "unit")); + dummy.add(new StyledText("Random Ability", "abilityname")); + dummy.add(new StyledText(": ", "separator")); + dummy.add(new StyledText("READY", "ready")); + } + + @Override + public List<StyledText> getDummyText() { + return dummy; + } + + private static final Map<String, SkyblockAbility> skyblockAbilities = new HashMap<>(); + private static final Map<String, List<SkyblockAbility>> skyblockAbilitiesByItemID = new HashMap<>(); + + static { + register(new SkyblockAbility("Disgusting Healing", -1, -1, "REAPER_MASK")); + register(new SkyblockAbility("Spirit Leap", -1, 5, "SPIRIT_LEAP")); + register(new SkyblockAbility("Farmer's Grace", -1, -1, "RANCHERS_BOOTS")); + register(new SkyblockAbility("Raise Souls", -1, 1, "SUMMONING_RING")); + register(new SkyblockAbility("Instant Heal", 70, -1, "FLORID_ZOMBIE_SWORD")); + register(new SkyblockAbility("Phantom Impel", -1, -1, "PHANTOM_ROD")); + register(new SkyblockAbility("Implosion", 300, 10, "IMPLOSION_SCROLL")); + register(new SkyblockAbility("Parley", -1, 5, "ASPECT_OF_THE_JERRY")); + register(new SkyblockAbility("Guided Bat", 250, -1, "BAT_WAND")); + register(new SkyblockAbility("Bat Swarm", -1, -1, "WITCH_MASK")); + register(new SkyblockAbility("Flay", -1, -1, "SOUL_WHIP")); + register(new SkyblockAbility("Instant Heal", 70, -1, "ZOMBIE_SWORD")); + register(new SkyblockAbility("Mithril's Protection", -1, -1, "MITHRIL_COAT")); + register(new SkyblockAbility("Second Wind", -1, 30, "SPIRIT_MASK")); + register(new SkyblockAbility("Love Tap", -1, -1, "ZOMBIE_SOLDIER_CUTLASS")); + register(new SkyblockAbility("Spiky", -1, -1, "PUFFERFISH_HAT")); + register(new SkyblockAbility("Jingle Bells", -1, 1, "JINGLE_BELLS")); + register(new SkyblockAbility("Wither Shield", 150, 10, "WITHER_SHIELD_SCROLL")); + register(new SkyblockAbility("Wither Impact", 150, 5, "WITHER_SHIELD_SCROLL")); + register(new SkyblockAbility("Brute Force", -1, -1, "WARDEN_HELMET")); + register(new SkyblockAbility("Growth", -1, 4, "GROWTH_LEGGINGS")); + register(new SkyblockAbility("Shadowstep", -1, 60, "SILENT_DEATH")); + register(new SkyblockAbility("Creeper Veil", -1, -1, "WITHER_CLOAK")); + register(new SkyblockAbility("Ice Bolt", 50, -1, "FROZEN_SCYTHE")); + register(new SkyblockAbility("Rapid-fire", 10, -1, "JERRY_STAFF")); + register(new SkyblockAbility("Water Burst", 20, -1, "SALMON_HELMET_NEW")); + register(new SkyblockAbility("Mist Aura", -1, -1, "SORROW_BOOTS")); + register(new SkyblockAbility("Deploy", -1, -1, "RADIANT_POWER_ORB")); + register(new SkyblockAbility("Ice Spray", 50, 5, "ICE_SPRAY_WAND")); + register(new SkyblockAbility("Grand... Zapper?", -1, -1, "BLOCK_ZAPPER")); + register(new SkyblockAbility("Seek the King", -1, 5, "ROYAL_PIGEON")); + register(new SkyblockAbility("Mist Aura", -1, -1, "SORROW_CHESTPLATE")); + register(new SkyblockAbility("Healing Boost", -1, -1, "REVIVED_HEART")); + register(new SkyblockAbility("Deploy", -1, -1, "OVERFLUX_POWER_ORB")); + register(new SkyblockAbility("Swing", -1, -1, "BONE_BOOMERANG")); + register(new SkyblockAbility("Growth", -1, 4, "GROWTH_CHESTPLATE")); + register(new SkyblockAbility("Squash 'em", -1, -1, "RECLUSE_FANG")); + register(new SkyblockAbility("Roll em'", -1, -1, "PUMPKIN_DICER")); + register(new SkyblockAbility("Cleave", -1, -1, "SUPER_CLEAVER")); + register(new SkyblockAbility("Water Burst", 20, -1, "SALMON_BOOTS_NEW")); + register(new SkyblockAbility("Farmer's Delight", -1, -1, "BASKET_OF_SEEDS")); + register(new SkyblockAbility("Block Damage", -1, 60, "GUARDIAN_CHESTPLATE")); + register(new SkyblockAbility("Water Burst", 20, -1, "SALMON_LEGGINGS")); + register(new SkyblockAbility("Bone Shield", -1, -1, "SKELETON_HELMET")); + register(new SkyblockAbility("Iron Punch", 70, 3, "GOLEM_SWORD")); + register(new SkyblockAbility("Built-in Storage", -1, -1, "BUILDERS_WAND")); + register(new SkyblockAbility("Nasty Bite", -1, -1, "MOSQUITO_BOW")); + register(new SkyblockAbility("Ender Warp", 50, 45, "ENDER_BOW")); + register(new SkyblockAbility("Cleave", -1, -1, "CLEAVER")); + register(new SkyblockAbility("Party Time!", -1, -1, "PARTY_HAT_CRAB")); + register(new SkyblockAbility("Giant's Slam", 100, 30, "GIANTS_SWORD")); + register(new SkyblockAbility("Snow Placer", -1, -1, "SNOW_SHOVEL")); + register(new SkyblockAbility("Greed", -1, -1, "MIDAS_SWORD")); + register(new SkyblockAbility("Clownin' Around", -1, 316, "STARRED_BONZO_MASK")); + register(new SkyblockAbility("Weather", -1, 5, "WEATHER_STICK")); + register(new SkyblockAbility("ME SMASH HEAD", 100, -1, "EDIBLE_MACE")); + register(new SkyblockAbility("Splash", 10, 1, "FISH_HAT")); + register(new SkyblockAbility("Deploy", -1, -1, "PLASMAFLUX_POWER_ORB")); + register(new SkyblockAbility("Dragon Rage", 100, -1, "ASPECT_OF_THE_DRAGON")); + register(new SkyblockAbility("Burning Souls", 400, -1, "PIGMAN_SWORD")); + register(new SkyblockAbility("Water Burst", 20, -1, "SALMON_CHESTPLATE_NEW")); + register(new SkyblockAbility("Fire Blast", 150, 30, "EMBER_ROD")); + register(new SkyblockAbility("Commander Whip", -1, -1, "ZOMBIE_COMMANDER_WHIP")); + register(new SkyblockAbility("Spooktacular", -1, -1, "GHOUL_BUSTER")); + register(new SkyblockAbility("Cleave", -1, -1, "HYPER_CLEAVER")); + register(new SkyblockAbility("Leap", 50, 1, "SILK_EDGE_SWORD")); + register(new SkyblockAbility("Throw", 150, 5, "LIVID_DAGGER")); + register(new SkyblockAbility("Raise Souls", -1, 1, "NECROMANCER_SWORD")); + register(new SkyblockAbility("Double Jump", 50, -1, "SPIDER_BOOTS")); + register(new SkyblockAbility("Speed Boost", 50, -1, "ROGUE_SWORD")); + register(new SkyblockAbility("Spirit Glide", 250, 60, "THORNS_BOOTS")); + register(new SkyblockAbility("Sting", 100, -1, "STINGER_BOW")); + register(new SkyblockAbility("Roll em'", -1, -1, "MELON_DICER")); + register(new SkyblockAbility("Explosive Shot", -1, -1, "EXPLOSIVE_BOW")); + register(new SkyblockAbility("Heat-Seeking Rose", 35, 1, "FLOWER_OF_TRUTH")); + register(new SkyblockAbility("Small Heal", 60, 1, "WAND_OF_HEALING")); + register(new SkyblockAbility("Dreadlord", 40, -1, "CRYPT_DREADLORD_SWORD")); + register(new SkyblockAbility("Shadow Fury", -1, 15, "STARRED_SHADOW_FURY")); + register(new SkyblockAbility("Double Jump", 40, -1, "TARANTULA_BOOTS")); + register(new SkyblockAbility("Acupuncture", 200, 5, "VOODOO_DOLL")); + register(new SkyblockAbility("Showtime", 100, -1, "STARRED_BONZO_STAFF")); + register(new SkyblockAbility("Heartstopper", -1, -1, "SCORPION_FOIL")); + register(new SkyblockAbility("Rapid Fire", -1, 100, "MACHINE_GUN_BOW")); + register(new SkyblockAbility("Water Burst", 20, -1, "SALMON_HELMET")); + register(new SkyblockAbility("Alchemist's Bliss", -1, -1, "NETHER_WART_POUCH")); + register(new SkyblockAbility("Water Burst", 20, -1, "SALMON_CHESTPLATE")); + register(new SkyblockAbility("Instant Heal", 70, -1, "ORNATE_ZOMBIE_SWORD")); + register(new SkyblockAbility("Shadow Fury", -1, 15, "SHADOW_FURY")); + register(new SkyblockAbility("Healing Boost", -1, -1, "ZOMBIE_HEART")); + register(new SkyblockAbility("Witherlord", 40, 3, "CRYPT_WITHERLORD_SWORD")); + register(new SkyblockAbility("Revive", -1, -1, "REVIVE_STONE")); + register(new SkyblockAbility("Raise Souls", -1, 1, "REAPER_SCYTHE")); + register(new SkyblockAbility("Rejuvenate", -1, -1, "VAMPIRE_MASK")); + register(new SkyblockAbility("Mist Aura", -1, -1, "SORROW_HELMET")); + register(new SkyblockAbility("Place Dirt", -1, -1, "INFINIDIRT_WAND")); + register(new SkyblockAbility("Clownin' Around", -1, 360, "BONZO_MASK")); + register(new SkyblockAbility("Shadow Warp", 300, 10, "SHADOW_WARP_SCROLL")); + register(new SkyblockAbility("Molten Wave", 500, 1, "MIDAS_STAFF")); + register(new SkyblockAbility("Growth", -1, 4, "GROWTH_HELMET")); + register(new SkyblockAbility("Howl", 150, 20, "WEIRD_TUBA")); + register(new SkyblockAbility("Medium Heal", 80, 1, "WAND_OF_MENDING")); + register(new SkyblockAbility("Throw", 20, -1, "AXE_OF_THE_SHREDDED")); + register(new SkyblockAbility("Ink Bomb", 60, 30, "INK_WAND")); + register(new SkyblockAbility("Whassup?", -1, -1, "AATROX_BATPHONE")); + register(new SkyblockAbility("Deploy", -1, -1, "MANA_FLUX_POWER_ORB")); + register(new SkyblockAbility("Extreme Focus", -1, -1, "END_STONE_BOW")); + register(new SkyblockAbility("Healing Boost", -1, -1, "CRYSTALLIZED_HEART")); + register(new SkyblockAbility("Mist Aura", -1, -1, "SORROW_LEGGINGS")); + register(new SkyblockAbility("Showtime", 100, -1, "BONZO_STAFF")); + register(new SkyblockAbility("Triple Shot", -1, -1, "RUNAANS_BOW")); + register(new SkyblockAbility("Water Burst", 20, -1, "SALMON_LEGGINGS_NEW")); + register(new SkyblockAbility("Rejuvenate", -1, -1, "VAMPIRE_WITCH_MASK")); + register(new SkyblockAbility("Terrain Toss", 250, 1, "YETI_SWORD")); + register(new SkyblockAbility("Instant Transmission", 50, -1, "ASPECT_OF_THE_END")); + register(new SkyblockAbility("Detonate", -1, 60, "CREEPER_LEGGINGS")); + register(new SkyblockAbility("Extreme Focus", -1, -1, "END_STONE_SWORD")); + register(new SkyblockAbility("Leap", 50, 1, "LEAPING_SWORD")); + register(new SkyblockAbility("Fun Guy Bonus", -1, -1, "FUNGI_CUTTER")); + register(new SkyblockAbility("Cleave", -1, -1, "GIANT_CLEAVER")); + register(new SkyblockAbility("Tempest", -1, -1, "HURRICANE_BOW")); + register(new SkyblockAbility("Big Heal", 100, 1, "WAND_OF_RESTORATION")); + register(new SkyblockAbility("Growth", -1, 4, "GROWTH_BOOTS")); + register(new SkyblockAbility("Stinger", 150, -1, "SCORPION_BOW")); + register(new SkyblockAbility("Eye Beam", -1, -1, "PRECURSOR_EYE")); + register(new SkyblockAbility("Water Burst", 20, -1, "SALMON_BOOTS")); + register(new SkyblockAbility("Mining Speed Boost", -1, 120, null)); + register(new SkyblockAbility("Pikobulus", -1, 110, null)); + // abilities + + register(new SkyblockAbility("Healing Circle", -1, 2, "DUNGEON_STONE")); + register(new SkyblockAbility("Wish", -1, 120, "DUNGEON_STONE")); + register(new SkyblockAbility("Guided Sheep", -1, 30, "DUNGEON_STONE")); + register(new SkyblockAbility("Thunderstorm", -1, 500, "DUNGEON_STONE")); + register(new SkyblockAbility("Throwing Axe", -1, 10, "DUNGEON_STONE")); + register(new SkyblockAbility("Ragnarok", -1, 60, "DUNGEON_STONE")); + register(new SkyblockAbility("Explosive Shot", -1, 40, "DUNGEON_STONE")); + register(new SkyblockAbility("Rapid Fire", -1, 100, "DUNGEON_STONE")); + register(new SkyblockAbility("Seismic Wave", -1, 15, "DUNGEON_STONE")); + register(new SkyblockAbility("Castle of Stone", -1, 150, "DUNGEON_STONE")); + } + + static void register(SkyblockAbility skyblockAbility) { + if (!skyblockAbilities.containsKey(skyblockAbility.getName())) + skyblockAbilities.put(skyblockAbility.getName(), skyblockAbility); + if (skyblockAbility.getItemId() != null && skyblockAbility.getCooldown() != -1) { + List<SkyblockAbility> skyblockAbility1 = skyblockAbilitiesByItemID.computeIfAbsent(skyblockAbility.getItemId(), (a) -> new ArrayList<>()); + skyblockAbility1.add(skyblockAbilities.get(skyblockAbility.getName())); + skyblockAbilitiesByItemID.put(skyblockAbility.getItemId(), skyblockAbility1); + } + } + + private final TreeSet<UsedAbility> usedAbilities = new TreeSet<UsedAbility>((c1, c2) -> { + int a = Comparator.comparingLong(UsedAbility::getCooldownEnd).compare(c1,c2); + return c1.getAbility().getName().equals(c2.getAbility().getName()) ? 0 : a; + }); + + @Override + public List<StyledText> getText() { + List<StyledText> cooldowns = new ArrayList<>(); + + for (UsedAbility usedAbility : usedAbilities) { + long end = usedAbility.getCooldownEnd(); + if (System.currentTimeMillis() >= end) { + if (System.currentTimeMillis() <= end + 20000) { + cooldowns.add(new StyledText(usedAbility.getAbility().getName(), "abilityname")); + cooldowns.add(new StyledText(": ", "separator")); + cooldowns.add(new StyledText("READY\n", "ready")); + } + } else { + cooldowns.add(new StyledText(usedAbility.getAbility().getName(), "abilityname")); + cooldowns.add(new StyledText(": ", "separator")); + long millies = end-System.currentTimeMillis(); + double decimalPlaces = (double ) Math.pow(10, 3- this.<Integer>getParameter("decimal").getValue()); + if (decimalPlaces == 0) { + cooldowns.add(new StyledText( this.<Integer>getParameter("decimal").getValue()+" decimal places? You'd be joking\n", "unit")); + continue; + } + millies = (long) (((millies-1) / decimalPlaces + 1) * decimalPlaces); + long hr = (long) (millies / (1000 * 60 * 60)); + long min = (long) (( millies / (1000*60)) % 60); + double seconds = (millies/1000.0 ) % 60; + String secondStr = String.format("%."+(this.<Integer>getParameter("decimal").getValue())+"f", seconds); + + if (hr > 0) { + cooldowns.add(new StyledText(String.valueOf(hr), "number")); + cooldowns.add(new StyledText("h ", "unit")); + } + if (hr > 0 || min > 0) { + cooldowns.add(new StyledText(String.valueOf(min), "number")); + cooldowns.add(new StyledText("m ", "unit")); + } + if (hr > 0 || min > 0 || seconds > 0) { + cooldowns.add(new StyledText(secondStr, "number")); + cooldowns.add(new StyledText("s ", "unit")); + } + cooldowns.add(new StyledText("\n", "unit")); + } + } + return cooldowns; + } + + Pattern thePattern = Pattern.compile("§b-(\\d+) Mana \\(§6(.+)§b\\)"); + Pattern thePattern2 = Pattern.compile("§r§aUsed (.+)§r§a! §r§b\\((1194) Mana\\)§r"); + Pattern thePattern3 = Pattern.compile("§r§aUsed (.+)§r§a!§r"); + + private String lastActionbarAbility; + @Override + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + if (clientChatReceivedEvent.type == 2) { + Matcher m = thePattern.matcher(clientChatReceivedEvent.message.getFormattedText()); + if (m.find()) { + String name = m.group(2); + if (!name.equalsIgnoreCase(lastActionbarAbility)) { + used(name); + } + lastActionbarAbility = name; + } else { + lastActionbarAbility = null; + } + } else { + String message = clientChatReceivedEvent.message.getFormattedText(); + if (message.equals("§r§aYour §r§9Bonzo's Mask §r§asaved your life!§r")) { + used("Clownin' Around"); + } else { + Matcher m = thePattern2.matcher(message); + if (m.matches()) { + String abilityName = TextUtils.stripColor(m.group(1)); + used(abilityName); + } else { + Matcher m2 = thePattern3.matcher(message); + if (m2.matches()) { + String abilityName = TextUtils.stripColor(m2.group(1)); + used(abilityName); + } else if (message.startsWith("§r§aYou used your ") || message.endsWith("§r§aPickaxe Ability!§r")) { + String nocolor = TextUtils.stripColor(message); + String abilityName = nocolor.substring(nocolor.indexOf("your") + 5, nocolor.indexOf("Pickaxe") - 1); + used(abilityName); + } + } + } + } + } + + private void used(String ability) { + if (skyblockAbilities.containsKey(ability)) { + SkyblockAbility skyblockAbility = skyblockAbilities.get(ability); + if (skyblockAbility.getCooldown() > 0) { + UsedAbility usedAbility = new UsedAbility(skyblockAbility, System.currentTimeMillis() + skyblockAbility.getCooldown() * 1000); + for (int i = 0; i < 3; i++) usedAbilities.remove(usedAbility); + usedAbilities.add(usedAbility); + } + } else { + System.out.println("Unknown ability: "+ability); + } + } + + public void checkForCooldown(ItemStack itemStack) { + if (itemStack == null) return; + NBTTagCompound nbt = itemStack.getTagCompound(); + if (nbt == null) return; + NBTTagCompound extra = nbt.getCompoundTag("ExtraAttributes"); + if (extra == null) return; + String id = extra.getString("id"); + if (!skyblockAbilitiesByItemID.containsKey(id)) return; + List<SkyblockAbility> skyblockAbility = skyblockAbilitiesByItemID.get(id); + + NBTTagCompound display = nbt.getCompoundTag("display"); + if (display == null) return; + NBTTagList lore = display.getTagList("Lore", 8); + int thecd = -1; + SkyblockAbility currentAbility = null; + for (int i = 0; i < lore.tagCount(); i++) { + String specific = lore.getStringTagAt(i); + if (specific.startsWith("§8Cooldown: §a") && currentAbility != null) { + String thecdstr = TextUtils.stripColor(specific).substring(10).trim(); + thecdstr = thecdstr.substring(0, thecdstr.length() - 1); + thecd = Integer.parseInt(thecdstr); + currentAbility.setCooldown(thecd); + currentAbility = null; + } else if (specific.startsWith("§6Item Ability: ")) { + String ability = TextUtils.stripColor(specific).substring(14).trim(); + + for (SkyblockAbility skyblockAbility1 : skyblockAbility) { + if (skyblockAbility1.getName().equals(ability)) { + currentAbility = skyblockAbility1; + break; + } + } + } + } + } + + @Override + public void onTick() { + EntityPlayerSP sp = Minecraft.getMinecraft().thePlayer; + if (sp == null) return; + if (sp.inventory == null || sp.inventory.armorInventory == null) return; + for (ItemStack itemStack : sp.inventory.armorInventory) { + checkForCooldown(itemStack); + } + for (ItemStack itemStack : sp.inventory.mainInventory) { + checkForCooldown(itemStack); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/ability/SkyblockAbility.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/ability/SkyblockAbility.java new file mode 100644 index 00000000..6869e8f7 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/ability/SkyblockAbility.java @@ -0,0 +1,32 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc.ability; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class SkyblockAbility { + private String name; + private int manaCost; + private int cooldown; + + private String itemId; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/ability/UsedAbility.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/ability/UsedAbility.java new file mode 100644 index 00000000..9bd998d8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/etc/ability/UsedAbility.java @@ -0,0 +1,31 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.etc.ability; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@AllArgsConstructor +public class UsedAbility { + private SkyblockAbility ability; + @EqualsAndHashCode.Exclude + private long cooldownEnd; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/APIKey.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/APIKey.java new file mode 100644 index 00000000..829010dc --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/APIKey.java @@ -0,0 +1,56 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party; + +import kr.syeyoung.dungeonsguide.features.listener.ChatListenerGlobal; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ChatComponentText; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +public class APIKey extends SimpleFeature implements ChatListenerGlobal { + + public APIKey() { + super("Misc.API Features", "API KEY", "Sets api key","partykicker.apikey"); + parameters.put("apikey", new FeatureParameter<String>("apikey", "API Key", "API key", "","string")); + } + + public String getAPIKey() { + return this.<String>getParameter("apikey").getValue(); + } + + + @Override + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + if (clientChatReceivedEvent.type == 2) return; + String str = clientChatReceivedEvent.message.getFormattedText(); + if (str.startsWith("§aYour new API key is §r§b")) { + String apiKeys = TextUtils.stripColor(str.split(" ")[5]); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fAutomatically Configured Hypixel API Key")); + this.<String>getParameter("apikey").setValue(apiKeys); + } + } + + @Override + public boolean isDisyllable() { + return false; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeatureGoodParties.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeatureGoodParties.java new file mode 100644 index 00000000..dbdcdd3f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeatureGoodParties.java @@ -0,0 +1,121 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party; + +import kr.syeyoung.dungeonsguide.features.listener.GuiPostRenderListener; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Items; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.Slot; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.client.event.GuiScreenEvent; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +public class FeatureGoodParties extends SimpleFeature implements GuiPostRenderListener { + public FeatureGoodParties() { + super("Party Kicker", "Highlight parties in party viewer", "Highlight parties you can't join with red", "partykicker.goodparty",true); + } + + @Override + public void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered) { + if (!isEnabled()) return; + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChest)) return; + GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest cont = (ContainerChest) chest.inventorySlots; + String name = cont.getLowerChestInventory().getName(); + if (!"Party Finder".equals(name)) return; + + + int i = 222; + int j = i - 108; + int ySize = j + (((ContainerChest)(((GuiChest) Minecraft.getMinecraft().currentScreen).inventorySlots)).getLowerChestInventory().getSizeInventory() / 9) * 18; + int left = (rendered.gui.width - 176) / 2; + int top = (rendered.gui.height - ySize ) / 2; + GlStateManager.pushMatrix(); + GlStateManager.disableDepth(); + GlStateManager.disableLighting(); + GlStateManager.colorMask(true, true, true, false); + GlStateManager.translate(left, top, 0); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + try { + + for (int i1 = 0; i1 < Integer.min(54, cont.inventorySlots.size()); i1++) { + Slot s = cont.inventorySlots.get(i1); + if (s.getStack() == null) continue; + if (s.getStack().getItem() != Items.skull) continue; + NBTTagCompound nbt = s.getStack().getTagCompound(); + if (nbt == null || nbt.hasNoTags()) continue; + NBTTagCompound display = nbt.getCompoundTag("display"); + if (display.hasNoTags()) return; + NBTTagList lore = display.getTagList("Lore", 8); + int classLvReq = 0; + int cataLvReq = 0; + boolean Req = false; + String note = ""; + for (int n = 0; n < lore.tagCount(); n++) { + String str = lore.getStringTagAt(n); + if (str.startsWith("§7Dungeon Level Required: §b")) cataLvReq = Integer.parseInt(str.substring(28)); + if (str.startsWith("§7Class Level Required: §b")) classLvReq = Integer.parseInt(str.substring(26)); + if (str.startsWith("§7§7Note:")) note = TextUtils.stripColor(str.substring(10)); + if (str.startsWith("§cRequires")) Req = true; + } + + int x = s.xDisplayPosition; + int y = s.yDisplayPosition; + if (Req) { + Gui.drawRect(x, y, x + 16, y + 16, 0x77AA0000); + } else { + + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + if (note.toLowerCase().contains("car")) { + fr.drawStringWithShadow("C", x + 1, y + 1, 0xFFFF0000); + } else if (note.toLowerCase().replace(" ", "").contains("s/s+")) { + fr.drawStringWithShadow("S+", x + 1, y + 1, 0xFFFFFF00); + } else if (note.toLowerCase().contains("s+")) { + fr.drawStringWithShadow("S+", x + 1, y + 1, 0xFF00FF00); + } else if (note.toLowerCase().contains(" s") || note.toLowerCase().contains(" s ")) { + fr.drawStringWithShadow("S", x + 1, y + 1, 0xFFFFFF00); + } else if (note.toLowerCase().contains("rush")) { + fr.drawStringWithShadow("R", x + 1, y + 1, 0xFFFF0000); + } + fr.drawStringWithShadow("§e"+Integer.max(classLvReq, cataLvReq), x + 1, y + fr.FONT_HEIGHT, 0xFFFFFFFF); + } + + + } + } catch (Throwable e) { + e.printStackTrace(); + } + GlStateManager.colorMask(true, true, true, true); + GlStateManager.popMatrix(); + GlStateManager.enableBlend(); + GlStateManager.enableLighting(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeaturePartyList.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeaturePartyList.java new file mode 100644 index 00000000..55ea699c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeaturePartyList.java @@ -0,0 +1,97 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.chat.PartyContext; +import kr.syeyoung.dungeonsguide.chat.PartyManager; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeaturePartyList extends TextHUDFeature { + public FeaturePartyList() { + super("Party","Party List", "Party List as GUI", "party.list", false, getFontRenderer().getStringWidth("Watcher finished spawning all mobs!"), getFontRenderer().FONT_HEIGHT*4); + getStyles().add(new TextStyle("name", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("player", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("allinvite", new AColor(0xAA,0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + setEnabled(false); + } + + @Override + public boolean isHUDViewable() { + return PartyManager.INSTANCE.getPartyContext() != null; + } + + @Override + public java.util.List<String> getUsedTextStyle() { + return Arrays.asList("name" ,"separator", "player", "allinvite"); + } + + private static final List<StyledText> dummyText = new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Leader","name")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("syeyoung","player")); + dummyText.add(new StyledText("\nModerator","name")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("rioho, RaidShadowLegends, Tricked","player")); + dummyText.add(new StyledText("\nMember","name")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("Everyone","player")); + dummyText.add(new StyledText("\nAll invite Off","allinvite")); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public boolean doesScaleWithHeight() { + return false; + } + + @Override + public List<StyledText> getText() { + PartyContext pc = PartyManager.INSTANCE.getPartyContext(); + List<StyledText> text= new ArrayList<>(); + text.add(new StyledText("Leader","name")); + text.add(new StyledText(": ","separator")); + text.add(new StyledText(pc.getPartyOwner()+"","player")); + text.add(new StyledText("\nModerator","name")); + text.add(new StyledText(": ","separator")); + text.add(new StyledText(pc.getPartyModerator() == null ? "????" : String.join(", ", pc.getPartyModerator()) + (pc.isModeratorComplete() ? "" : " ?"),"player")); + text.add(new StyledText("\nMember","name")); + text.add(new StyledText(": ","separator")); + text.add(new StyledText(pc.getPartyMember() == null ? "????" : String.join(", ", pc.getPartyMember()) + (pc.isMemberComplete() ? "" : " ?"),"player")); + if (pc.getAllInvite() != null && !pc.getAllInvite()) + text.add(new StyledText("\nAll invite Off","allinvite")); + else if (pc.getAllInvite() != null) + text.add(new StyledText("\nAll invite On","allinvite")); + else + text.add(new StyledText("\nAll invite Unknown","allinvite")); + return text; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeaturePartyReady.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeaturePartyReady.java new file mode 100644 index 00000000..f7d16167 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeaturePartyReady.java @@ -0,0 +1,180 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.listener.ChatListener; +import kr.syeyoung.dungeonsguide.features.listener.DungeonStartListener; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.chat.PartyContext; +import kr.syeyoung.dungeonsguide.chat.PartyManager; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +import java.util.*; + +public class FeaturePartyReady extends TextHUDFeature implements ChatListener, DungeonStartListener { + public FeaturePartyReady() { + super("Party","Party Ready List", "Check if your party member have said r or not", "party.readylist", false, getFontRenderer().getStringWidth("Watcher finished spawning all mobs!"), getFontRenderer().FONT_HEIGHT*4); + getStyles().add(new TextStyle("player", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("ready", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("notready", new AColor(0xFF, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("terminal", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + setEnabled(true); + } + + @Override + public boolean isHUDViewable() { + return PartyManager.INSTANCE.getPartyContext() != null && PartyManager.INSTANCE.getPartyContext().isPartyExistHypixel() && "Dungeon Hub".equals(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()); + } + + @Override + public List<String> getUsedTextStyle() { + return Arrays.asList("separator", "player", "ready", "notready", "terminal"); + } + + private static final List<StyledText> dummyText = new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("syeyoung","player")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("Ready","ready")); + dummyText.add(new StyledText(" 4","terminal")); + dummyText.add(new StyledText("\nrioho","player")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("Ready","ready")); + dummyText.add(new StyledText(" 3","terminal")); + dummyText.add(new StyledText("\nRaidShadowLegends","player")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("Not Ready","notready")); + dummyText.add(new StyledText(" 2t","terminal")); + dummyText.add(new StyledText("\nTricked","player")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("Ready","ready")); + dummyText.add(new StyledText(" ss","terminal")); + dummyText.add(new StyledText("\nMr. Penguin","player")); + dummyText.add(new StyledText(": ","separator")); + dummyText.add(new StyledText("Not Ready","notready")); + dummyText.add(new StyledText(" 2b","terminal")); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + @Override + public boolean doesScaleWithHeight() { + return false; + } + + private Set<String> ready = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + private Map<String, String> terminal = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + @Override + public List<StyledText> getText() { + PartyContext pc = PartyManager.INSTANCE.getPartyContext(); + List<StyledText> text= new ArrayList<>(); + boolean first = true; + for (String partyRawMember : pc.getPartyRawMembers()) { + text.add(new StyledText((first ? "":"\n") + partyRawMember, "player")); + text.add(new StyledText(": ","separator")); + if (ready.contains(partyRawMember)) + text.add(new StyledText("Ready","ready")); + else + text.add(new StyledText("Not Ready","notready")); + if (terminal.get(partyRawMember) != null) { + text.add(new StyledText(" "+ terminal.get(partyRawMember), "terminal")); + } + first =false; + } + return text; + } + + private static final List<String> readyPhrase = Arrays.asList("r", "rdy", "ready"); + private static final List<String> negator = Arrays.asList("not ", "not", "n", "n "); + private static final List<String> terminalPhrase = Arrays.asList("ss", "s1", "1", "2b", "2t", "3", "4", "s3", "s4", "s2", "2"); + private static final Map<String, Boolean> readynessIndicator = new HashMap<>(); + static { + readyPhrase.forEach(val -> readynessIndicator.put(val, true)); + for (String s : negator) { + readyPhrase.forEach(val -> readynessIndicator.put(s+val, false)); + } + readynessIndicator.put("dont start", false); + readynessIndicator.put("don't start", false); + readynessIndicator.put("dont go", false); + readynessIndicator.put("don't go", false); + readynessIndicator.put("start", true); + readynessIndicator.put("go", true); + } + + + @Override + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + String txt = clientChatReceivedEvent.message.getFormattedText(); + if (!txt.startsWith("§r§9Party §8>")) return; + + String chat = TextUtils.stripColor(txt.substring(txt.indexOf(":")+1)).trim().toLowerCase(); + + + + String usernamearea = TextUtils.stripColor(txt.substring(13, txt.indexOf(":"))); + String username = null; + for (String s : usernamearea.split(" ")) { + if (s.isEmpty()) continue; + if (s.startsWith("[")) continue; + username = s; + break; + } + + + Boolean status = null; + String longestMatch = ""; + for (Map.Entry<String, Boolean> stringBooleanEntry : readynessIndicator.entrySet()) { + if (chat.startsWith(stringBooleanEntry.getKey()) || chat.endsWith(stringBooleanEntry.getKey()) || (stringBooleanEntry.getKey().length()>=3 && chat.contains(stringBooleanEntry.getKey()))) { + if (stringBooleanEntry.getKey().length() > longestMatch.length()) { + longestMatch = stringBooleanEntry.getKey(); + status = stringBooleanEntry.getValue(); + } + } + } + if (status == null); + else if (status) ready.add(username); + else ready.remove(username); + + + String term = ""; + for (String s : terminalPhrase) { + if (chat.equals(s) || chat.startsWith(s+" ") || chat.endsWith(" "+s) || chat.contains(" "+s+" ")) { + term += s+" "; + } + } + if (!term.isEmpty()) + terminal.put(username, term); + } + + @Override + public void onDungeonStart() { + ready.clear(); + terminal.clear(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java new file mode 100644 index 00000000..3e991c59 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java @@ -0,0 +1,694 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import com.google.gson.*; +import com.mojang.authlib.GameProfile; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import kr.syeyoung.dungeonsguide.utils.XPUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.*; +import java.util.concurrent.*; +import java.util.function.BiFunction; +import java.util.stream.Collectors; + +public class ApiFetchur { + private static final Gson gson = new Gson(); + + private static final Map<String, CachedData<PlayerProfile>> playerProfileCache = new ConcurrentHashMap<>(); + private static final Map<String, CachedData<String>> nicknameToUID = new ConcurrentHashMap<>(); + private static final Map<String, CachedData<String>> UIDtoNickname = new ConcurrentHashMap<>(); + private static final Map<String, CachedData<GameProfile>> UIDtoGameProfile = new ConcurrentHashMap<>(); + + private static final ExecutorService ex = Executors.newFixedThreadPool(4); + + private static final Set<String> invalidKeys = new HashSet<>(); + public static void purgeCache() { + playerProfileCache.clear(); + nicknameToUID.clear(); + UIDtoNickname.clear(); + UIDtoGameProfile.clear(); + + completableFutureMap.clear(); + completableFutureMap2.clear(); + completableFutureMap3.clear(); + completableFutureMap4.clear(); + invalidKeys.clear(); + constants = null; + + ex.submit(ApiFetchur::getLilyWeightConstants); + } + static { + ex.submit(ApiFetchur::getLilyWeightConstants); + } + + public static JsonObject getJson(String url) throws IOException { + URLConnection connection = new URL(url).openConnection(); + connection.setConnectTimeout(10000); + connection.setReadTimeout(10000); + return gson.fromJson(new InputStreamReader(connection.getInputStream()), JsonObject.class); + } + public static JsonArray getJsonArr(String url) throws IOException { + URLConnection connection = new URL(url).openConnection(); + connection.setConnectTimeout(10000); + connection.setReadTimeout(10000); + return gson.fromJson(new InputStreamReader(connection.getInputStream()), JsonArray.class); + } + + private static volatile JsonObject constants; + public static JsonObject getLilyWeightConstants() { + if (constants != null) return constants; + try { + JsonObject jsonObject = getJson("https://raw.githubusercontent.com/Antonio32A/lilyweight/master/lib/constants.json"); + constants = jsonObject; + } catch (Exception e) { + throw new RuntimeException(e); + } + return constants; + } + + private static final Map<String, CompletableFuture<Optional<GameProfile>>> completableFutureMap4 = new ConcurrentHashMap<>(); + public static CompletableFuture<Optional<GameProfile>> getSkinGameProfileByUUIDAsync(String uid) { + if (UIDtoGameProfile.containsKey(uid)) { + CachedData<GameProfile> cachedData = UIDtoGameProfile.get(uid); + if (cachedData.getExpire() > System.currentTimeMillis()) { + return CompletableFuture.completedFuture(Optional.ofNullable(cachedData.getData())); + } + UIDtoGameProfile.remove(uid); + } + if (completableFutureMap4.containsKey(uid)) return completableFutureMap4.get(uid); + + CompletableFuture<Optional<GameProfile>> completableFuture = new CompletableFuture<>(); + fetchNicknameAsync(uid).thenAccept(nick -> { + if (!nick.isPresent()) { + completableFuture.complete(Optional.empty()); + return; + } + ex.submit(() -> { + try { + Optional<GameProfile> playerProfile = getSkinGameProfileByUUID(uid,nick.get()); + UIDtoGameProfile.put(uid, new CachedData<GameProfile>(System.currentTimeMillis()+1000*60*30, playerProfile.orElse(null))); + completableFuture.complete(playerProfile); + completableFutureMap4.remove(uid); + return; + } catch (IOException e) { + e.printStackTrace(); + } + completableFuture.complete(Optional.empty()); + completableFutureMap4.remove(uid); + }); + }); + completableFutureMap4.put(uid, completableFuture); + return completableFuture; + } + + public static Optional<GameProfile> getSkinGameProfileByUUID(String uid, String nickname) throws IOException { + GameProfile gameProfile = new GameProfile(UUID.fromString(uid), nickname); + GameProfile newProf = Minecraft.getMinecraft().getSessionService().fillProfileProperties(gameProfile, true); + return newProf == gameProfile ? Optional.empty() : Optional.of(newProf); + } + + + private static final Map<String, CompletableFuture<Optional<PlayerProfile>>> completableFutureMap = new ConcurrentHashMap<>(); + public static CompletableFuture<Optional<PlayerProfile>> fetchMostRecentProfileAsync(String uid, String apiKey) { + if (playerProfileCache.containsKey(uid)) { + CachedData<PlayerProfile> cachedData = playerProfileCache.get(uid); + if (cachedData.getExpire() > System.currentTimeMillis()) { + return CompletableFuture.completedFuture(Optional.ofNullable(cachedData.getData())); + } + playerProfileCache.remove(uid); + } + if (completableFutureMap.containsKey(uid)) return completableFutureMap.get(uid); + if (invalidKeys.contains(apiKey)) { + CompletableFuture cf = new CompletableFuture(); + cf.completeExceptionally(new IOException("403 for url")); + return cf; + } + + CompletableFuture<Optional<PlayerProfile>> completableFuture = new CompletableFuture<>(); + ex.submit(() -> { + try { + Optional<PlayerProfile> playerProfile = fetchMostRecentProfile(uid, apiKey); + playerProfileCache.put(uid, new CachedData<PlayerProfile>(System.currentTimeMillis()+1000*60*30, playerProfile.orElse(null))); + completableFuture.complete(playerProfile); + completableFutureMap.remove(uid); + return; + } catch (IOException e) { + if (e.getMessage().contains("403 for URL")) { + completableFuture.completeExceptionally(e); + completableFutureMap.remove(uid); + invalidKeys.add(apiKey); + } else { + completableFuture.completeExceptionally(e); + completableFutureMap.remove(uid); + } + e.printStackTrace(); + } + }); + completableFutureMap.put(uid, completableFuture); + return completableFuture; + } + + private static final Map<String, CompletableFuture<Optional<String>>> completableFutureMap3 = new ConcurrentHashMap<>(); + public static CompletableFuture<Optional<String>> fetchNicknameAsync(String uid) { + if (UIDtoNickname.containsKey(uid)) { + CachedData<String> cachedData = UIDtoNickname.get(uid); + if (cachedData.getExpire() > System.currentTimeMillis()) { + return CompletableFuture.completedFuture(Optional.ofNullable(cachedData.getData())); + } + UIDtoNickname.remove(uid); + } + if (completableFutureMap3.containsKey(uid)) return completableFutureMap3.get(uid); + + + CompletableFuture<Optional<String>> completableFuture = new CompletableFuture<>(); + + ex.submit(() -> { + try { + Optional<String> playerProfile = fetchNickname(uid); + UIDtoNickname.put(uid, new CachedData<String>(System.currentTimeMillis()+1000*60*60*12,playerProfile.orElse(null))); + if (playerProfile.isPresent()) + nicknameToUID.put(playerProfile.orElse(null), new CachedData<>(System.currentTimeMillis()+1000*60*60*12, uid)); + completableFuture.complete(playerProfile); + completableFutureMap3.remove(uid); + return; + } catch (IOException e) { + e.printStackTrace(); + } + completableFuture.complete(Optional.empty()); + completableFutureMap3.remove(uid); + }); + completableFutureMap3.put(uid, completableFuture); + + return completableFuture; + } + + private static final Map<String, CompletableFuture<Optional<String>>> completableFutureMap2 = new ConcurrentHashMap<>(); + public static CompletableFuture<Optional<String>> fetchUUIDAsync(String nickname) { + if (nicknameToUID.containsKey(nickname)) { + CachedData<String> cachedData = nicknameToUID.get(nickname); + if (cachedData.getExpire() > System.currentTimeMillis()) { + return CompletableFuture.completedFuture(Optional.ofNullable(cachedData.getData())); + } + nicknameToUID.remove(nickname); + } + if (completableFutureMap2.containsKey(nickname)) return completableFutureMap2.get(nickname); + + + CompletableFuture<Optional<String>> completableFuture = new CompletableFuture<>(); + + ex.submit(() -> { + try { + Optional<String> playerProfile = fetchUUID(nickname); + nicknameToUID.put(nickname, new CachedData<String>(System.currentTimeMillis()+1000*60*60*12,playerProfile.orElse(null))); + if (playerProfile.isPresent()) + UIDtoNickname.put(playerProfile.orElse(null), new CachedData<>(System.currentTimeMillis()+1000*60*60*12, nickname)); + + completableFuture.complete(playerProfile); + completableFutureMap2.remove(nickname); + return; + } catch (IOException e) { + e.printStackTrace(); + } + completableFuture.complete(Optional.empty()); + completableFutureMap2.remove(nickname); + }); + completableFutureMap2.put(nickname, completableFuture); + + return completableFuture; + } + + public static Optional<String> fetchUUID(String nickname) throws IOException { + JsonObject json = getJson("https://api.mojang.com/users/profiles/minecraft/"+nickname); + if (json.has("error")) return Optional.empty(); + return Optional.of(TextUtils.insertDashUUID(json.get("id").getAsString())); + } + public static Optional<String> fetchNickname(String uuid) throws IOException { + try { + JsonArray json = getJsonArr("https://api.mojang.com/user/profiles/" + uuid.replace("-", "") + "/names"); + return Optional.of(json.get(json.size()-1).getAsJsonObject().get("name").getAsString()); + } catch (Exception e) {return Optional.empty();} + } + + public static List<PlayerProfile> fetchPlayerProfiles(String uid, String apiKey) throws IOException { + JsonObject json = getJson("https://api.hypixel.net/skyblock/profiles?uuid="+uid+"&key="+apiKey); + if (!json.get("success").getAsBoolean()) return new ArrayList<>(); + JsonArray profiles = json.getAsJsonArray("profiles"); + String dashTrimmed = uid.replace("-", ""); + + ArrayList<PlayerProfile> playerProfiles = new ArrayList<>(); + for (JsonElement jsonElement : profiles) { + JsonObject semiProfile = jsonElement.getAsJsonObject(); + if (!semiProfile.has(dashTrimmed)) continue; + playerProfiles.add(parseProfile(semiProfile, dashTrimmed)); + } + return playerProfiles; + } + + public static Optional<PlayerProfile> fetchMostRecentProfile(String uid, String apiKey) throws IOException { + JsonObject json = getJson("https://api.hypixel.net/skyblock/profiles?uuid="+uid+"&key="+apiKey); + if (!json.get("success").getAsBoolean()) return Optional.empty(); + JsonArray profiles = json.getAsJsonArray("profiles"); + String dashTrimmed = uid.replace("-", ""); + + JsonObject profile = null; + long lastSave = Long.MIN_VALUE; + for (JsonElement jsonElement : profiles) { + JsonObject semiProfile = jsonElement.getAsJsonObject(); + if (!semiProfile.getAsJsonObject("members").has(dashTrimmed)) continue; + long lastSave2 = semiProfile.getAsJsonObject("members").getAsJsonObject(dashTrimmed).get("last_save").getAsLong(); + if (lastSave2 > lastSave) { + profile = semiProfile; + lastSave = lastSave2; + } + } + + if (profile == null) return Optional.empty(); + PlayerProfile pp = parseProfile(profile, dashTrimmed); + json = getJson("https://api.hypixel.net/player?uuid="+uid+"&key="+apiKey); + if (json.has("player")) { + JsonObject treasures = json.getAsJsonObject("player"); + if (treasures.has("achievements")) { + treasures = treasures.getAsJsonObject("achievements"); + if (treasures.has("skyblock_treasure_hunter")) { + pp.setTotalSecrets(treasures.get("skyblock_treasure_hunter").getAsInt()); + } + } + } + + return Optional.of(pp); + } + + public static int getOrDefault(JsonObject jsonObject, String key, int value) { + if (jsonObject == null || !jsonObject.has(key) || jsonObject.get(key) instanceof JsonNull) return value; + return jsonObject.get(key).getAsInt(); + } + public static long getOrDefault(JsonObject jsonObject, String key, long value) { + if (jsonObject == null || !jsonObject.has(key) || jsonObject.get(key) instanceof JsonNull) return value; + return jsonObject.get(key).getAsLong(); + } + public static double getOrDefault(JsonObject jsonObject, String key, double value) { + if (jsonObject == null || !jsonObject.has(key) || jsonObject.get(key) instanceof JsonNull) return value; + return jsonObject.get(key).getAsDouble(); + } + public static String getOrDefault(JsonObject jsonObject, String key, String value) { + if (jsonObject == null || !jsonObject.has(key) || jsonObject.get(key) instanceof JsonNull) return value; + return jsonObject.get(key).getAsString(); + } + public static Double getOrDefaultNullable(JsonObject jsonObject, String key, Double value) { + if (jsonObject == null || !jsonObject.has(key) || jsonObject.get(key) instanceof JsonNull) return value; + return jsonObject.get(key).getAsDouble(); + } + public static NBTTagCompound parseBase64NBT(String nbt) throws IOException { + return CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(nbt))); + } + + public static ItemStack deserializeNBT(NBTTagCompound nbtTagCompound) { + if (nbtTagCompound.hasNoTags()) return null; + ItemStack itemStack = new ItemStack(Blocks.stone); + itemStack.deserializeNBT(nbtTagCompound); + return itemStack; + } + + public static PlayerProfile parseProfile(JsonObject profile, String dashTrimmed) throws IOException { + PlayerProfile playerProfile = new PlayerProfile(); + playerProfile.setProfileUID(getOrDefault(profile, "profile_id", "")); + playerProfile.setMemberUID(dashTrimmed); + playerProfile.setProfileName(getOrDefault(profile, "cute_name", "")); + + JsonObject playerData = profile.getAsJsonObject("members").getAsJsonObject(dashTrimmed); + playerProfile.setLastSave(getOrDefault(playerData, "last_save", 0L)); + playerProfile.setFairySouls(getOrDefault(playerData, "fairy_souls_collected", 0)); + playerProfile.setFairyExchanges(getOrDefault(playerData, "fairy_exchanges", 0)); + + if (playerData.has("inv_armor")) { + playerProfile.setCurrentArmor(new PlayerProfile.Armor()); + NBTTagCompound armor = parseBase64NBT(playerData.getAsJsonObject("inv_armor") + .get("data") + .getAsString()); + NBTTagList array = armor.getTagList("i", 10); + for (int i = 0; i < 4; i++) { + NBTTagCompound item = array.getCompoundTagAt(i); + playerProfile.getCurrentArmor().getArmorSlots()[i] = deserializeNBT(item); + } + } + + if (playerData.has("wardrobe_contents")) { + NBTTagCompound armor = parseBase64NBT(playerData.getAsJsonObject("wardrobe_contents").get("data").getAsString()); + NBTTagList array = armor.getTagList("i", 10); + for (int i = 0; i < array.tagCount(); i++) { + if (i % 4 == 0) playerProfile.getWardrobe().add(new PlayerProfile.Armor()); + NBTTagCompound item = array.getCompoundTagAt(i); + playerProfile.getWardrobe().get(i/4).getArmorSlots()[i%4] = deserializeNBT(item); + } + + } + playerProfile.setSelectedWardrobe(getOrDefault(playerData, "wardrobe_equipped_slot", -1)); + + if (playerData.has("inv_contents")) { + NBTTagCompound armor = parseBase64NBT(playerData.getAsJsonObject("inv_contents").get("data").getAsString()); + NBTTagList array = armor.getTagList("i", 10); + playerProfile.setInventory(new ItemStack[array.tagCount()]); + for (int i = 0; i < array.tagCount(); i++) { + NBTTagCompound item = array.getCompoundTagAt(i); + playerProfile.getInventory()[i] = deserializeNBT(item); + } + } + if (playerData.has("ender_chest_contents")) { + NBTTagCompound armor = parseBase64NBT(playerData.getAsJsonObject("ender_chest_contents").get("data").getAsString()); + NBTTagList array = armor.getTagList("i", 10); + playerProfile.setEnderchest(new ItemStack[array.tagCount()]); + for (int i = 0; i < array.tagCount(); i++) { + NBTTagCompound item = array.getCompoundTagAt(i); + playerProfile.getEnderchest()[i] = deserializeNBT(item); + } + } + if (playerData.has("talisman_bag")) { + NBTTagCompound armor = parseBase64NBT(playerData.getAsJsonObject("talisman_bag").get("data").getAsString()); + NBTTagList array = armor.getTagList("i", 10); + playerProfile.setTalismans(new ItemStack[array.tagCount()]); + for (int i = 0; i < array.tagCount(); i++) { + NBTTagCompound item = array.getCompoundTagAt(i); + playerProfile.getTalismans()[i] = deserializeNBT(item); + } + } + + playerProfile.setSkillXp(new HashMap<>()); + for (Skill value : Skill.values()) { + playerProfile.getSkillXp().put(value, getOrDefaultNullable(playerData, "experience_skill_"+value.getJsonName(), null)); + } + + if (playerData.has("pets")) { + for (JsonElement pets : playerData.getAsJsonArray("pets")) { + JsonObject pet = pets.getAsJsonObject(); + Pet petObj = new Pet(); + petObj.setActive(pet.get("active").getAsBoolean()); + petObj.setExp(getOrDefault(pet, "exp", 0.0)); + petObj.setHeldItem(getOrDefault(pet, "heldItem", null)); + petObj.setSkin(getOrDefault(pet, "skin", null)); + petObj.setType(getOrDefault(pet, "type", null)); + petObj.setUuid(getOrDefault(pet, "uuid", null)); + + playerProfile.getPets().add(petObj); + } + } + + if (playerData.has("dungeons") && playerData.getAsJsonObject("dungeons").has("dungeon_types")) { + JsonObject types = playerData.getAsJsonObject("dungeons") + .getAsJsonObject("dungeon_types"); + for (DungeonType value : DungeonType.values()) { + DungeonStat dungeonStat = new DungeonStat(); + DungeonSpecificData<DungeonStat> dungeonSpecificData = new DungeonSpecificData<>(value, dungeonStat); + playerProfile.getDungeonStats().put(value, dungeonSpecificData); + + if (!types.has(value.getJsonName())) continue; + + JsonObject dungeonObj = types.getAsJsonObject(value.getJsonName()); + + dungeonStat.setHighestCompleted(getOrDefault(dungeonObj, "highest_tier_completed", -1)); + + for (Integer validFloor : value.getValidFloors()) { + DungeonStat.PlayedFloor playedFloor = new DungeonStat.PlayedFloor(); + playedFloor.setBestScore(getOrDefault(dungeonObj.getAsJsonObject("best_score"), ""+validFloor, 0)); + playedFloor.setCompletions(getOrDefault(dungeonObj.getAsJsonObject("tier_completions"), ""+validFloor, 0)); + playedFloor.setFastestTime(getOrDefault(dungeonObj.getAsJsonObject("fastest_time"), ""+validFloor, -1)); + playedFloor.setFastestTimeS(getOrDefault(dungeonObj.getAsJsonObject("fastest_time_s"), ""+validFloor, -1)); + playedFloor.setFastestTimeSPlus(getOrDefault(dungeonObj.getAsJsonObject("fastest_time_s_plus"), ""+validFloor, -1)); + playedFloor.setMobsKilled(getOrDefault(dungeonObj.getAsJsonObject("mobs_killed"), ""+validFloor, 0)); + playedFloor.setMostMobsKilled(getOrDefault(dungeonObj.getAsJsonObject("most_mobs_killed"), ""+validFloor, 0)); + playedFloor.setMostHealing(getOrDefault(dungeonObj.getAsJsonObject("most_healing"), ""+validFloor, 0)); + playedFloor.setTimes_played(getOrDefault(dungeonObj.getAsJsonObject("times_played"), ""+validFloor, 0)); + playedFloor.setWatcherKills(getOrDefault(dungeonObj.getAsJsonObject("watcher_kills"), ""+validFloor, 0)); + + for (DungeonClass dungeonClass : DungeonClass.values()) { + DungeonStat.PlayedFloor.ClassStatistics classStatistics = new DungeonStat.PlayedFloor.ClassStatistics(); + classStatistics.setMostDamage(getOrDefault(dungeonObj.getAsJsonObject("most_damage_"+dungeonClass.getJsonName()), ""+validFloor, 0)); + ClassSpecificData<DungeonStat.PlayedFloor.ClassStatistics> classStatisticsClassSpecificData = new ClassSpecificData<>(dungeonClass, classStatistics); + + playedFloor.getClassStatistics().put(dungeonClass, classStatisticsClassSpecificData); + } + + FloorSpecificData<DungeonStat.PlayedFloor> playedFloorFloorSpecificData = new FloorSpecificData<>(validFloor, playedFloor); + dungeonStat.getPlays().put(validFloor, playedFloorFloorSpecificData); + } + + dungeonStat.setExperience(getOrDefault(dungeonObj, "experience", 0)); + + + } + } + if (playerData.has("dungeons") && playerData.getAsJsonObject("dungeons").has("player_classes")) { + JsonObject classes = playerData.getAsJsonObject("dungeons") + .getAsJsonObject("player_classes"); + for (DungeonClass dungeonClass : DungeonClass.values()) { + PlayerProfile.PlayerClassData classStatistics = new PlayerProfile.PlayerClassData(); + classStatistics.setExperience(getOrDefault(classes.getAsJsonObject(dungeonClass.getJsonName()), "experience", 0)); + ClassSpecificData<PlayerProfile.PlayerClassData> classStatisticsClassSpecificData = new ClassSpecificData<>(dungeonClass, classStatistics); + + playerProfile.getPlayerClassData().put(dungeonClass, classStatisticsClassSpecificData); + } + } + if (playerData.has("dungeons")) { + String id = getOrDefault(playerData.getAsJsonObject("dungeons"), "selected_dungeon_class", null); + DungeonClass dungeonClass = DungeonClass.getClassByJsonName(id); + playerProfile.setSelectedClass(dungeonClass); + } + try { + calculateLilyWeight(playerProfile, playerData); + } catch (Exception e) { + e.printStackTrace(); + } + return playerProfile; + } + + private static void calculateLilyWeight(PlayerProfile playerProfile, JsonObject playerData) throws ExecutionException, InterruptedException { + JsonObject constants = getLilyWeightConstants(); + double[] slayerXP = new double[4]; + if (playerData.has("slayer_bosses")) { + slayerXP[0] = getOrDefault(playerData.getAsJsonObject("slayer_bosses").getAsJsonObject("zombie"), "xp", 0); + slayerXP[1] = getOrDefault(playerData.getAsJsonObject("slayer_bosses").getAsJsonObject("spider"), "xp", 0); + slayerXP[2] = getOrDefault(playerData.getAsJsonObject("slayer_bosses").getAsJsonObject("wolf"), "xp", 0); + slayerXP[3] = getOrDefault(playerData.getAsJsonObject("slayer_bosses").getAsJsonObject("enderman"), "xp", 0); + } + double skillWeight = 0; + double overflowWeight = 0; + { + JsonObject srw = constants.getAsJsonObject("skillRatioWeight"); + int skillMaxXP = constants.get("skillMaxXP").getAsInt(); + JsonArray overflowMultiplier = constants.getAsJsonArray("skillOverflowMultipliers"); + JsonArray skillFactor = constants.getAsJsonArray("skillFactors"); + + double skillAvg = playerProfile.getSkillXp().entrySet().stream() + .filter(a -> a.getValue() != null) + .filter(a -> srw.has(a.getKey().getJsonName())) + .map(a -> XPUtils.getSkillXp(a.getKey(), a.getValue()).getLevel()).collect(Collectors.averagingInt(a -> a)); + + double n = 12 * (skillAvg/60)*(skillAvg/60); + double r2 = Math.sqrt(2); + + for (Map.Entry<Skill, Double> skillDoubleEntry : playerProfile.getSkillXp().entrySet()) { + String jsonName = skillDoubleEntry.getKey().getJsonName(); + JsonArray temp_srw = srw.getAsJsonArray(jsonName); + if (temp_srw == null) continue; + int lv = XPUtils.getSkillXp(skillDoubleEntry.getKey(), skillDoubleEntry.getValue()).getLevel(); + skillWeight += n * temp_srw.get(lv).getAsDouble() + * temp_srw.get(temp_srw.size() - 1).getAsDouble(); + skillWeight += temp_srw.get(temp_srw.size() - 1).getAsDouble() * Math.pow(lv/60.0, r2); + } + + int cnt = 0; + for (Map.Entry<String, JsonElement> skillNames : constants.getAsJsonObject("skillNames").entrySet()) { + Skill s = getSkillByLilyName(skillNames.getKey()); + double factor = skillFactor.get(cnt).getAsDouble(); + double effectiveOver; + Double xp = playerProfile.getSkillXp().get(s); + if (xp == null) continue; xp -= skillMaxXP; + { + if (xp < skillMaxXP) effectiveOver = xp; + else { + double remainingXP = xp; + double z = 0; + for (int i = 0; i<= xp/skillMaxXP; i++) { + if (remainingXP >= skillMaxXP) { + remainingXP -= skillMaxXP; + z += Math.pow(factor, i); + } + } + effectiveOver = z * skillMaxXP; + } + } + double rating = effectiveOver / skillMaxXP; + double overflowMult = overflowMultiplier.get(cnt).getAsDouble(); + double t = rating * overflowMult; + if (t > 0) overflowWeight += t; + cnt++; + } + } + double cataCompWeight, masterCompWeight; + { + JsonArray completionFactor = constants.getAsJsonArray("dungeonCompletionWorth"); + JsonObject dungeonCompletionBuffs = constants.getAsJsonObject("dungeonCompletionBuffs"); + double max1000 = 0; + double mMax1000 = 0; + for (int i = 0; i < completionFactor.size(); i++) { + if (i < 8) max1000 += completionFactor.get(i).getAsDouble(); + else mMax1000 += completionFactor.get(i).getAsDouble(); + } + + max1000 *= 1000; + mMax1000 *= 1000; + + double upperBound = 1500; double score = 0; + + DungeonStat dStat = playerProfile.getDungeonStats().get(DungeonType.CATACOMBS).getData(); + for (FloorSpecificData<DungeonStat.PlayedFloor> value : dStat.getPlays().values()) { + int runs = value.getData().getCompletions(); + int excess = 0; if (runs > 1000) { + excess = runs - 1000; runs = 1000; + } + + double floorScore = runs * completionFactor.get(value.getFloor()).getAsDouble(); + if (excess > 0) + floorScore *= Math.log10(excess / 1000.0 + 1) / Math.log10(7.5) + 1; + score += floorScore; + } + cataCompWeight = (score / max1000 * upperBound); + + dStat = playerProfile.getDungeonStats().get(DungeonType.MASTER_CATACOMBS).getData(); + for (FloorSpecificData<DungeonStat.PlayedFloor> value : dStat.getPlays().values()) { + if (dungeonCompletionBuffs.has(value.getFloor()+"")) { + double threshold = 20; + if (value.getData().getCompletions() >= threshold) upperBound += dungeonCompletionBuffs.get(value.getFloor()+"").getAsDouble(); + else upperBound += dungeonCompletionBuffs.get(value.getFloor()+"").getAsDouble() * Math.pow(value.getData().getCompletions()/threshold, 1.840896416); + } + } + score = 0; + for (FloorSpecificData<DungeonStat.PlayedFloor> value : dStat.getPlays().values()) { + int runs = value.getData().getCompletions(); + int excess = 0; if (runs > 1000) { + excess = runs - 1000; runs = 1000; + } + + double floorScore = runs * completionFactor.get(value.getFloor()+7).getAsDouble(); + if (excess > 0) + floorScore *= Math.log10(excess / 1000.0 + 1) / Math.log10(5) + 1; + score += floorScore; + } + + masterCompWeight = score / mMax1000 * upperBound; + } + double dungeonXPWeight = 0; + { + double dungeonOverall = constants.get("dungeonOverall").getAsDouble(); + double dungeonMaxXP = constants.get("dungeonMaxXP").getAsDouble(); + + double cataXP = playerProfile.getDungeonStats().get(DungeonType.CATACOMBS).getData().getExperience(); + XPUtils.XPCalcResult xpCalcResult = XPUtils.getCataXp(cataXP); + double level = xpCalcResult.getLevel(); + if (xpCalcResult.getLevel() != 50) { + double progress = Math.floor(xpCalcResult.getRemainingXp() / xpCalcResult.getNextLvXp() * 1000) / 1000.0; + level += progress; + } + + double n; double tempLevel = 0; + if (cataXP < dungeonMaxXP) + n = 0.2 * Math.pow(level / 50.0, 2.967355422); + else { + double part = 142452410; + tempLevel = 50 + (cataXP - dungeonMaxXP) / part; + n = 0.2 * Math.pow(1 + ((tempLevel - 50) / 50), 2.967355422); + } + if (level != 0) { + if (cataXP < 569809640) dungeonXPWeight = dungeonOverall * (Math.pow(1.18340401286164044, (level + 1)) - 1.05994990217254) * (1 + n); + else dungeonXPWeight =4000 * (n / 0.15465244570598540); + } else dungeonXPWeight = 0; + } + double slayerWeight = 0; + { + JsonArray slayerDeprecationScaling = constants.getAsJsonArray("slayerDeprecationScaling"); + BiFunction<Double, Integer, Double> getSlayerWeight = (xp, type) -> { + double score = 0; + { + double d = xp / 100000; + if (xp >= 6416) { + double D = (d - Math.pow(3, (-5 / 2.0))) * (d + Math.pow(3, -5 / 2.0)); + double u = Math.cbrt(3 * (d + Math.sqrt(D))); + double v = Math.cbrt(3 * (d - Math.sqrt(D))); + score = u + v - 1; + } else { + score = Math.sqrt(4 / 3.0) * Math.cos(Math.acos(d * Math.pow(3, 5 / 2.0)) / 3) - 1; + } + } + score = Math.floor(score); + double scaling = slayerDeprecationScaling.get(type).getAsDouble(); + double effectiveXP = 0; + for (int i = 1; i <= score; i++) + effectiveXP += (i * i + i) * Math.pow(scaling, i); + effectiveXP = Math.round((1000000 * effectiveXP * (0.05 / scaling)) * 100) / 100.0; + double actualXP = ((score*score*score / 6) + (score*score / 2) + (score / 3)) * 100000; + double distance = xp - actualXP; + double effectiveDistance = distance * Math.pow(scaling, score); + return effectiveXP + effectiveDistance; + }; + + double zombie = getSlayerWeight.apply(slayerXP[0], 0); + double spider = getSlayerWeight.apply(slayerXP[1], 1); + double wolf = getSlayerWeight.apply(slayerXP[2], 2); + double enderman = getSlayerWeight.apply(slayerXP[3], 3); + double individual = zombie / 7000 + spider / 4800 + wolf / 2200 + enderman / 1000; + double extra = (slayerXP[0] + 1.6 * slayerXP[1] + 3.6 * slayerXP[2] + 10 * slayerXP[3]) / 900000; + slayerWeight = (individual + extra); + } + + PlayerProfile.LilyWeight lilyWeight = new PlayerProfile.LilyWeight(); + lilyWeight.setCatacombs_base(cataCompWeight); + lilyWeight.setCatacombs_master(masterCompWeight); + lilyWeight.setCatacombs_exp(dungeonXPWeight); + lilyWeight.setSkill_base(skillWeight); + lilyWeight.setSkill_overflow(overflowWeight); + lilyWeight.setSlayer(slayerWeight); + + playerProfile.setLilyWeight(lilyWeight); + } + + private static Skill getSkillByLilyName(String lilyName) { + switch(lilyName) { + case "experience_skill_enchanting": return Skill.ENCHANTING; + case "experience_skill_taming": return Skill.TAMING; + case "experience_skill_alchemy": return Skill.ALCHEMY; + case "experience_skill_mining": return Skill.MINING; + case "experience_skill_farming": return Skill.FARMING; + case "experience_skill_foraging": return Skill.FORAGING; + case "experience_skill_combat": return Skill.COMBAT; + case "experience_skill_fishing": return Skill.FISHING; + default: return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/CachedData.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/CachedData.java new file mode 100644 index 00000000..9213e2e5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/CachedData.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class CachedData<T> { + private final long expire; + private final T data; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ClassSpecificData.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ClassSpecificData.java new file mode 100644 index 00000000..d1df192b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ClassSpecificData.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class ClassSpecificData<T> { + private final DungeonClass dungeonClass; + private final T data; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonClass.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonClass.java new file mode 100644 index 00000000..a840d29e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonClass.java @@ -0,0 +1,46 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +@Getter +@AllArgsConstructor +public enum DungeonClass { + MAGE("mage", "Mage"), ARCHER("archer","Archer"), HEALER("healer", "Healer"), TANK("tank", "Tank"), BERSERK("berserk", "Berserk"); + + + private final String jsonName; + private final String familarName; + private static final Map<String, DungeonClass> jsonNameToClazz = new HashMap<>(); + static { + for (DungeonClass value : values()) { + jsonNameToClazz.put(value.getJsonName(), value); + } + } + + public static DungeonClass getClassByJsonName(String name) { + return jsonNameToClazz.get(name); + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonSpecificData.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonSpecificData.java new file mode 100644 index 00000000..56230e1f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonSpecificData.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class DungeonSpecificData<T> { + private final DungeonType type; + private final T data; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonStat.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonStat.java new file mode 100644 index 00000000..7fbe02df --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonStat.java @@ -0,0 +1,54 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class DungeonStat { + private int highestCompleted; + private double experience; + + private Map<Integer, FloorSpecificData<PlayedFloor>> plays = new HashMap<>(); + @Data + public static class PlayedFloor { + private int times_played; + private int completions; + private int watcherKills; + + private int fastestTime; + private int fastestTimeS; + private int fastestTimeSPlus; + private int bestScore; + + private int mostMobsKilled; + private int mobsKilled; + + private Map<DungeonClass, ClassSpecificData<ClassStatistics>> classStatistics = new HashMap<>(); + @Data + public static class ClassStatistics { + private double mostDamage; + } + + private double mostHealing; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonType.java new file mode 100644 index 00000000..f1c443e4 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/DungeonType.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import com.google.common.collect.Sets; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Set; + +@Getter +@AllArgsConstructor +public enum DungeonType { + CATACOMBS("catacombs", "The Catacombs", + Sets.newHashSet(0,1,2,3,4,5,6,7)), + MASTER_CATACOMBS("master_catacombs", "MasterMode Catacombs", Sets.newHashSet( + 1,2,3,4,5,6 + )); + + private final String jsonName; + private final String familiarName; + private final Set<Integer> validFloors ; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/FloorSpecificData.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/FloorSpecificData.java new file mode 100644 index 00000000..18641c79 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/FloorSpecificData.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class FloorSpecificData<T> { + private final int floor; + private final T data; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/Pet.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/Pet.java new file mode 100644 index 00000000..99004cc1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/Pet.java @@ -0,0 +1,31 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import lombok.Data; + +@Data +public class Pet { + private String uuid; + private String type; + private double exp; + private boolean active; + private String heldItem; + private String skin; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/PlayerProfile.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/PlayerProfile.java new file mode 100644 index 00000000..68de8b86 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/PlayerProfile.java @@ -0,0 +1,91 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import lombok.Data; +import net.minecraft.item.ItemStack; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Data +public class PlayerProfile { + private String profileUID; + private String memberUID; + private String profileName; + + private long lastSave; + + private int fairySouls; + private int fairyExchanges; + + private Armor currentArmor; + private List<Armor> wardrobe = new ArrayList<>(); + private int selectedWardrobe = -1; + + private ItemStack[] inventory; + private ItemStack[] enderchest; + private ItemStack[] talismans; + + private int totalSecrets; + + @Data + public static class Armor { + private final ItemStack[] armorSlots = new ItemStack[4]; + + public ItemStack getHelmet() { return armorSlots[3]; } + public ItemStack getChestPlate() { return armorSlots[2]; } + public ItemStack getLeggings() { return armorSlots[1]; } + public ItemStack getBoots() { return armorSlots[0]; } + } + + private Map<DungeonType, DungeonSpecificData<DungeonStat>> dungeonStats = new HashMap<>(); + + private Map<DungeonClass, ClassSpecificData<PlayerClassData>> playerClassData = new HashMap<>(); + private DungeonClass selectedClass; + @Data + public static class PlayerClassData { + private double experience; + } + + private Map<Skill, Double> skillXp; + + private List<Pet> pets = new ArrayList<>(); + + + private Map<String, Object> additionalProperties = new HashMap<>(); + + private LilyWeight lilyWeight; + + @Data + public static class LilyWeight { + private double skill_base; + private double skill_overflow; + private double catacombs_base; + private double catacombs_master; + private double catacombs_exp; + private double slayer; + + public double getTotal() { + return skill_base + skill_overflow + catacombs_base + catacombs_exp + catacombs_master + slayer; + } + } +}
\ No newline at end of file diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/Skill.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/Skill.java new file mode 100644 index 00000000..f0d8e88b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/Skill.java @@ -0,0 +1,31 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum Skill { + RUNECRAFTING("runecrafting", "Runecrafting"), COMBAT("combat", "Combat"), MINING("mining", "Mining"), ALCHEMY("alchemy", "Alchemy"), FARMING("farming", "Farming"), TAMING("taming", "Taming"), ENCHANTING("enchanting", "Enchanting"), FISHING("fishing", "Fishing"), FORAGING("foraging", "Foraging"), CARPENTRY("carpentry", "Carpentry"); + + private final String jsonName; + private final String friendlyName; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/SkinFetchur.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/SkinFetchur.java new file mode 100644 index 00000000..29850132 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/SkinFetchur.java @@ -0,0 +1,88 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.client.resources.SkinManager; +import net.minecraft.util.ResourceLocation; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; + +public class SkinFetchur { + + private static final Map<String, CachedData<SkinSet>> skinSetMap = new ConcurrentHashMap<>(); + + private static final Map<String, CompletableFuture<SkinSet>> currentReq = new HashMap<>(); + + public static CompletableFuture<SkinSet> getSkinSet(GameProfile gameProfile) { + if (gameProfile == null) { + return CompletableFuture.completedFuture(new SkinSet(DefaultPlayerSkin.getDefaultSkinLegacy(), null, "default")); + } + if (skinSetMap.containsKey(gameProfile.getId().toString())) { + CachedData<SkinSet> ss = skinSetMap.get(gameProfile.getId().toString()); + if (ss.getExpire() > System.currentTimeMillis()) + CompletableFuture.completedFuture(skinSetMap.get(gameProfile.getId().toString()).getData()); + skinSetMap.remove(gameProfile.getId().toString()); + } + if (currentReq.containsKey(gameProfile.getId().toString())) + return currentReq.get(gameProfile.getId().toString()); + + SkinSet skinSet = new SkinSet(); + CompletableFuture<SkinSet> skinSet2 = new CompletableFuture<>(); + currentReq.put(gameProfile.getId().toString(), skinSet2); + Minecraft.getMinecraft().getSkinManager().loadProfileTextures(gameProfile, new SkinManager.SkinAvailableCallback() { + public void skinAvailable(MinecraftProfileTexture.Type p_180521_1_, ResourceLocation location, MinecraftProfileTexture profileTexture) { + switch (p_180521_1_) { + case SKIN: + skinSet.setSkinLoc(location); + skinSet.setSkinType(profileTexture.getMetadata("model")); + if (skinSet.getSkinType() == null) { + skinSet.setSkinType("default"); + } + skinSet2.complete(skinSet); + skinSetMap.put(gameProfile.getId().toString(), new CachedData<>(System.currentTimeMillis() + 1000*60*60*3, skinSet)); + currentReq.get(gameProfile.getId().toString()); + break; + case CAPE: + skinSet.setCapeLoc(location); + } + } + }, true); + + return skinSet2; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class SkinSet { + private ResourceLocation skinLoc; + private ResourceLocation capeLoc; + private String skinType; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/FeatureCustomPartyFinder.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/FeatureCustomPartyFinder.java new file mode 100644 index 00000000..98605169 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/FeatureCustomPartyFinder.java @@ -0,0 +1,112 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.customgui; + +import kr.syeyoung.dungeonsguide.events.WindowUpdateEvent; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.features.listener.GuiOpenListener; +import kr.syeyoung.dungeonsguide.features.listener.GuiUpdateListener; +import kr.syeyoung.dungeonsguide.features.listener.*; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.client.event.GuiOpenEvent; + +public class FeatureCustomPartyFinder extends SimpleFeature implements GuiOpenListener, GuiUpdateListener { + public FeatureCustomPartyFinder() { + super("Party","Custom Party Finder","Custom Party Finder", "party.customfinder", true); + } + + @Getter + @Setter + private String whitelist = "", blacklist = "", highlight ="", blacklistClass = ""; + @Getter + @Setter + private int minimumCata; + + @Getter @Setter + private String lastClass = ""; + + GuiCustomPartyFinder guiCustomPartyFinder; + @Override + public void onGuiOpen(GuiOpenEvent event) { + if (event.gui == null) guiCustomPartyFinder = null; + if (!isEnabled()) return; + if (!(event.gui instanceof GuiChest)) return; + GuiChest chest = (GuiChest) event.gui; + if (!(chest.inventorySlots instanceof ContainerChest)) return; + ContainerChest containerChest = (ContainerChest) chest.inventorySlots; + IInventory lower = containerChest.getLowerChestInventory(); + if (lower == null || !lower.getName().equals("Party Finder")) return; + + if (guiCustomPartyFinder == null) { + guiCustomPartyFinder = new GuiCustomPartyFinder(); + } + guiCustomPartyFinder.setGuiChest(chest); + + event.gui = guiCustomPartyFinder; + } + + @Override + public void onGuiUpdate(WindowUpdateEvent windowUpdateEvent) { + if (guiCustomPartyFinder != null) { + guiCustomPartyFinder.onChestUpdate(windowUpdateEvent); + } + + if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; + + if (!(chest.inventorySlots instanceof ContainerChest)) return; + ContainerChest containerChest = (ContainerChest) chest.inventorySlots; + IInventory lower = containerChest.getLowerChestInventory(); + if (lower == null || !lower.getName().equals("Catacombs Gate")) return; + + ItemStack item = null; + if (windowUpdateEvent.getWindowItems() != null) { + item = windowUpdateEvent.getWindowItems().getItemStacks()[47]; + } else if (windowUpdateEvent.getPacketSetSlot() != null) { + if (windowUpdateEvent.getPacketSetSlot().func_149173_d() != 47) return; + item = windowUpdateEvent.getPacketSetSlot().func_149174_e(); + } + if (item == null) return; + + NBTTagCompound stackTagCompound = item.getTagCompound(); + if (stackTagCompound.hasKey("display", 10)) { + NBTTagCompound nbttagcompound = stackTagCompound.getCompoundTag("display"); + + if (nbttagcompound.getTagId("Lore") == 9) { + NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8); + + for (int i = 0; i < nbttaglist1.tagCount(); i++) { + String str = nbttaglist1.getStringTagAt(i); + if (str.startsWith("§aCurrently Selected")) { + lastClass = str.substring(24); + } + } + } + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/GuiCustomPartyFinder.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/GuiCustomPartyFinder.java new file mode 100644 index 00000000..a42b946f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/GuiCustomPartyFinder.java @@ -0,0 +1,75 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.customgui; + +import kr.syeyoung.dungeonsguide.events.WindowUpdateEvent; +import kr.syeyoung.dungeonsguide.gui.MGui; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiChest; + +import java.awt.*; + +public class GuiCustomPartyFinder extends MGui { + @Getter + private GuiChest guiChest; + + public void setGuiChest(GuiChest guiChest) { + if (this.guiChest != null) this.guiChest.onGuiClosed(); + this.guiChest = guiChest; + panelPartyFinder.onChestUpdate(null); + guiChest.setWorldAndResolution(Minecraft.getMinecraft(), Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight); + guiChest.initGui(); + } + + public void onChestUpdate(WindowUpdateEvent windowUpdateEvent) { + panelPartyFinder.onChestUpdate(windowUpdateEvent); + } + + private PanelPartyFinder panelPartyFinder; + public GuiCustomPartyFinder() { + panelPartyFinder = new PanelPartyFinder(this); + getMainPanel().add(panelPartyFinder); + } + + @Override + public void initGui() { + super.initGui(); + int width = 3*Minecraft.getMinecraft().displayWidth/5; + width = Math.max(width, 1000); + int height = 3*Minecraft.getMinecraft().displayHeight/5; + height = Math.max(height, 600); + + panelPartyFinder.setBounds(new Rectangle((Minecraft.getMinecraft().displayWidth-width)/2, (Minecraft.getMinecraft().displayHeight-height)/2, width, height)); + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawDefaultBackground(); + super.drawScreen(mouseX, mouseY, partialTicks); + + } + + @Override + public void onGuiClosed() { + guiChest.onGuiClosed(); + guiChest = null; + super.onGuiClosed(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinder.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinder.java new file mode 100644 index 00000000..7a07ba2e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinder.java @@ -0,0 +1,342 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.customgui; + +import kr.syeyoung.dungeonsguide.chat.PartyManager; +import kr.syeyoung.dungeonsguide.config.guiconfig.GuiConfigV2; +import kr.syeyoung.dungeonsguide.events.WindowUpdateEvent; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.impl.discord.invteTooltip.MTooltipInvite; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + +import java.awt.*; +import java.util.HashMap; +import java.util.Map; + +public class PanelPartyFinder extends MPanel { + @Getter + private GuiCustomPartyFinder guiCustomPartyFinder; + + private PanelPartyFinderSettings panelPartyFinderSettings; + + private MScrollablePanel scrollablePanel; + private MList list; + + private MButton goBack; + + private MPanelScaledGUI navigation; + + private MButton previous; + private MButton next; + private MButton settings, discordInvite; + private int page = 1; + + private Map<Integer, PanelPartyListElement> panelPartyListElementMap = new HashMap<>(); + + public PanelPartyFinder(GuiCustomPartyFinder guiCustomPartyFinder) { + this.guiCustomPartyFinder = guiCustomPartyFinder; + + scrollablePanel = new MScrollablePanel(1); + panelPartyFinderSettings = new PanelPartyFinderSettings(this); + + + list = new MList() { + @Override + public void resize(int parentWidth, int parentHeight) { + setSize(new Dimension(parentWidth, 9999)); + realignChildren(); + } + }; + list.setGap(1); + + scrollablePanel.add(list); + + add(scrollablePanel); + add(panelPartyFinderSettings); + + previous = new MButton(); next = new MButton(); + previous.setText("Prev"); next.setText("Next"); + previous.setEnabled(false); next.setEnabled(false); + next.setOnActionPerformed(() -> { + GuiChest chest = getGuiCustomPartyFinder().getGuiChest(); + Minecraft.getMinecraft().playerController.windowClick(chest.inventorySlots.windowId, 9*2+8, 0, 0, Minecraft.getMinecraft().thePlayer); + }); + previous.setOnActionPerformed(() -> { + GuiChest chest = getGuiCustomPartyFinder().getGuiChest(); + Minecraft.getMinecraft().playerController.windowClick(chest.inventorySlots.windowId, 9*2, 0, 0, Minecraft.getMinecraft().thePlayer); + }); + goBack = new MButton(); + goBack.setBackground(RenderUtils.blendAlpha(0xFF141414, 0.05f)); + goBack.setText("<"); + goBack.setOnActionPerformed(() -> { + GuiChest chest = getGuiCustomPartyFinder().getGuiChest(); + Minecraft.getMinecraft().playerController.windowClick(chest.inventorySlots.windowId, 9*5+3, 0, 0, Minecraft.getMinecraft().thePlayer); + }); + add(goBack); + settings = new MButton(); + settings.setBackground(RenderUtils.blendAlpha(0xFF141414, 0.05f)); + settings.setText("Settings"); + settings.setOnActionPerformed(() -> { + GuiConfigV2 guiConfigV2 = new GuiConfigV2(); + guiConfigV2.getRootConfigPanel().setCurrentPageAndPushHistory("ROOT."+ FeatureRegistry.PARTYKICKER_CUSTOM.getCategory()); + Minecraft.getMinecraft().displayGuiScreen(guiConfigV2); + }); + discordInvite = new MButton(); + discordInvite.setText("Invite Discord Friends"); + discordInvite.setOnActionPerformed(() -> { + if (RichPresenceManager.INSTANCE.getLastSetupCode() == -9999) { + MModalMessage mTooltipInvite = new MModalMessage("Error", "Discord GameSDK has been disabled, or it failed to load", () -> {}); + mTooltipInvite.setScale( new ScaledResolution(Minecraft.getMinecraft()).getScaleFactor()); + mTooltipInvite.open(this); + } else if (PartyManager.INSTANCE.getAskToJoinSecret() != null) { + MTooltipInvite mTooltipInvite = new MTooltipInvite(); + mTooltipInvite.setScale( new ScaledResolution(Minecraft.getMinecraft()).getScaleFactor()); + mTooltipInvite.open(this); + } else { + MModalMessage mTooltipInvite = new MModalMessage("Error", "You need to have Ask To Join Enabled to use this feature. Run /dg atj to enable ask to join", () -> {}); + mTooltipInvite.setScale( new ScaledResolution(Minecraft.getMinecraft()).getScaleFactor()); + mTooltipInvite.open(this); + } + }); + discordInvite.setBackground(RenderUtils.blendAlpha(0xFF141414, 0.05f)); + add(discordInvite); + add(settings); + navigation = new MPanelScaledGUI() { + @Override + public void onBoundsUpdate() { + super.onBoundsUpdate(); + Dimension dimension = getEffectiveDimension(); + previous.setBounds(new Rectangle(0,0,50,dimension.height)); + next.setBounds(new Rectangle(dimension.width-50,0,50,dimension.height)); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + super.render(absMousex, absMousey, relMousex0, relMousey0, partialTicks, scissor); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + Gui.drawRect(0,0,getEffectiveDimension().width, getEffectiveDimension().height, RenderUtils.blendAlpha(0xFF141414, 0.08f)); + fr.drawString("Page "+page, (getEffectiveDimension().width-fr.getStringWidth("Page "+page))/2, (getEffectiveDimension().height-fr.FONT_HEIGHT)/2, -1); + } + }; + navigation.add(next); navigation.add(previous); + add(navigation); + } + + public String getHighlightNote() { + return panelPartyFinderSettings.getHighlightText(); + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + panelPartyFinderSettings.setBounds(new Rectangle(3*bounds.width/5+1, fr.FONT_HEIGHT*2+21, 2*bounds.width/5 -1, (bounds.height-fr.FONT_HEIGHT*2-21))); + panelPartyFinderSettings.setScale(scaledResolution.getScaleFactor()); + + navigation.setBounds(new Rectangle(0,fr.FONT_HEIGHT*2 + 21, 3*bounds.width/5, 20*scaledResolution.getScaleFactor())); + navigation.setScale(scaledResolution.getScaleFactor()); + scrollablePanel.setBounds(new Rectangle(0, navigation.getBounds().y+navigation.getBounds().height, 3*bounds.width/5, bounds.height - (navigation.getBounds().y+navigation.getBounds().height))); + goBack.setBounds(new Rectangle(0,0, fr.FONT_HEIGHT*2+20, fr.FONT_HEIGHT*2+20)); + settings.setBounds(new Rectangle(bounds.width - 75, 0, 75, fr.FONT_HEIGHT*2+20)); + discordInvite.setBounds(new Rectangle(bounds.width-275, 0, 200, fr.FONT_HEIGHT*2+20)); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + // background + Gui.drawRect(0,0,getBounds().width, getBounds().height, RenderUtils.blendAlpha(0xFF141414, 0.0f)); + // top bar + Gui.drawRect(0,0,getBounds().width, fr.FONT_HEIGHT*2+21, RenderUtils.blendAlpha(0xFF141414, 0.05f)); + // lines + Gui.drawRect(0,fr.FONT_HEIGHT*2+20,getBounds().width, fr.FONT_HEIGHT*2+21, -1); + Gui.drawRect(panelPartyFinderSettings.getBounds().x-1,fr.FONT_HEIGHT*2+20,panelPartyFinderSettings.getBounds().x, getBounds().height, -1); + // prev next bar + + GlStateManager.pushMatrix(); + GlStateManager.translate(fr.FONT_HEIGHT*2+21, 0,0); + GlStateManager.scale(2,2,1); + fr.drawString("Party Finder", 5,5,-1); + GlStateManager.popMatrix(); + } + + public synchronized void onChestUpdate(WindowUpdateEvent windowUpdateEvent) { + if (windowUpdateEvent == null) { + GuiChest guiChest = guiCustomPartyFinder.getGuiChest(); + if (guiChest == null) { + panelPartyListElementMap.clear(); + } else { + for (int x = 1; x<=7; x++) { + for (int y = 1; y <= 3; y++) { + int i = y * 9 + x; + Slot s = guiChest.inventorySlots.getSlot(i); + PanelPartyListElement prev = panelPartyListElementMap.remove(i); + if (s == null || !s.getHasStack()) { continue; } + if (!filter(s.getStack())) continue; + + if (prev == null) prev = new PanelPartyListElement(this, i); + panelPartyListElementMap.put(i, prev); + } + } + + { + Slot next = guiChest.inventorySlots.getSlot(9 * 2 + 8); + if (next.getStack() != null && next.getStack().getItem() == Items.arrow) { + this.next.setEnabled(true); + extractPage(next.getStack()); + } else { + this.next.setEnabled(false); + } + + Slot prev = guiChest.inventorySlots.getSlot(9 * 2 + 0); + if (prev.getStack() != null && prev.getStack().getItem() == Items.arrow) { + this.previous.setEnabled(true); + extractPage(prev.getStack()); + } else { + this.previous.setEnabled(false); + } + + Slot delist = guiChest.inventorySlots.getSlot(9 * 5 + 7); + panelPartyFinderSettings.setDelistable(delist.getStack() != null && delist.getStack().getItem() == Item.getItemFromBlock(Blocks.bookshelf)); + } + } + } else { + if (windowUpdateEvent.getPacketSetSlot() != null) { + int i = windowUpdateEvent.getPacketSetSlot().func_149173_d(); + + ItemStack stack = windowUpdateEvent.getPacketSetSlot().func_149174_e(); + if (i == 9*2+8) { + if (stack != null && stack.getItem() == Items.arrow) { + this.next.setEnabled(true); + extractPage(stack); + } else { + this.next.setEnabled(false); + } + } else if (i == 9*2) { + if (stack != null && stack.getItem() == Items.arrow) { + this.previous.setEnabled(true); + extractPage(stack); + } else { + this.previous.setEnabled(false); + } + } else if (i == 9*5+7) { + panelPartyFinderSettings.setDelistable(stack != null && stack.getItem() == Item.getItemFromBlock(Blocks.bookshelf)); + } + + if (i%9 == 0 || i%9 == 8 || i/9 == 0 || i/9 >= 4) { + return; + } + + PanelPartyListElement prev = panelPartyListElementMap.remove(i); + if (filter(stack)) { + if (prev == null) prev = new PanelPartyListElement(this, i); + panelPartyListElementMap.put(i, prev); + } + } else if (windowUpdateEvent.getWindowItems() != null) { + for (int x = 1; x<=7; x++) { + for (int y = 1; y <= 3; y++) { + int i = y * 9 + x; + ItemStack item = windowUpdateEvent.getWindowItems().getItemStacks()[i]; + PanelPartyListElement prev = panelPartyListElementMap.remove(i); + if (!filter(item)) continue; + + if (prev == null) prev = new PanelPartyListElement(this, i); + panelPartyListElementMap.put(i, prev); + } + } + + { + ItemStack next = windowUpdateEvent.getWindowItems().getItemStacks()[9 * 2 + 8]; + if (next != null && next.getItem() == Items.arrow) { + this.next.setEnabled(true); + extractPage(next); + } else { + this.next.setEnabled(false); + } + + ItemStack prev = windowUpdateEvent.getWindowItems().getItemStacks()[9 * 2]; + if (prev != null && prev.getItem() == Items.arrow) { + this.previous.setEnabled(true); + extractPage(prev); + } else { + this.previous.setEnabled(false); + } + + ItemStack delist = windowUpdateEvent.getWindowItems().getItemStacks()[9*5+7]; + panelPartyFinderSettings.setDelistable(delist != null && delist.getItem() == Item.getItemFromBlock(Blocks.bookshelf)); + } + } + } + + addItems(); + } + + public boolean filter(ItemStack item) { + return !(item == null || item.getItem() == null || item.getItem() == Item.getItemFromBlock(Blocks.air)) && panelPartyFinderSettings.filter(item); + } + + public void extractPage(ItemStack itemStack) { + NBTTagCompound stackTagCompound = itemStack.getTagCompound(); + if (stackTagCompound.hasKey("display", 10)) { + NBTTagCompound nbttagcompound = stackTagCompound.getCompoundTag("display"); + + if (nbttagcompound.getTagId("Lore") == 9) { + NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8); + + for (int i = 0; i < nbttaglist1.tagCount(); i++) { + String str = nbttaglist1.getStringTagAt(i); + if (str.startsWith("§ePage ")) { + int pg = Integer.parseInt(str.substring(7)); + if (itemStack.getDisplayName().equals("§aPrevious Page")) page = pg+1; + else page = pg-1; + } + } + } + } + } + + public void addItems() { + for (MPanel childComponent : list.getChildComponents()) { + list.remove(childComponent); + } + for (Map.Entry<Integer, PanelPartyListElement> value : panelPartyListElementMap.entrySet()) { + list.add(value.getValue()); + } + scrollablePanel.evalulateContentArea(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinderSettings.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinderSettings.java new file mode 100644 index 00000000..d59d1640 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinderSettings.java @@ -0,0 +1,295 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.customgui; + +import kr.syeyoung.dungeonsguide.chat.ChatProcessor; +import kr.syeyoung.dungeonsguide.chat.PartyManager; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Items; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.EnumChatFormatting; + +import java.awt.*; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class PanelPartyFinderSettings extends MPanelScaledGUI { + private PanelPartyFinder panelPartyFinder; + + private MButton refresh = new MButton(), createNew = new MButton(), settings = new MButton(); + private MPassiveLabelAndElement filterCantjoin, filterWhitelistNote, filterBlacklistNote, plaeHighlightNote, cataLv,blacklistClass; private MToggleButton filterCantjoinButton; + private MTextField filterWhitelist, filterBlacklist, highlightNote, blacklistClassTxt; + private MIntegerSelectionButton integerSelection; + + @Getter @Setter + boolean delistable = false; + + public void setDelistable(boolean delistable) { + this.delistable = delistable; + updateCreateNew(); + } + + public void updateCreateNew() { + createNew.setText((PartyManager.INSTANCE.getPartyContext() != null && !PartyManager.INSTANCE.isLeader()) ? "Leave Party" : (delistable ? "De-list" : "Create New")); + } + + public PanelPartyFinderSettings(PanelPartyFinder panelPartyFinder) { + this.panelPartyFinder = panelPartyFinder; + + createNew.setOnActionPerformed(this::createNew); + createNew.setBackground(0xFF00838F); + createNew.setHover(0xFF00ACC1); + createNew.setClicked(0xFF0097A7); + add(createNew); + updateCreateNew(); + refresh.setText("Refresh"); + refresh.setOnActionPerformed(this::refresh); + add(refresh); + + settings.setText("Search Settings"); + settings.setOnActionPerformed(this::settings); + add(settings); + + { + filterCantjoinButton = new MToggleButton(); + filterCantjoin = new MPassiveLabelAndElement("Filter Unjoinable", filterCantjoinButton); + filterCantjoin.setDivideRatio(0.7); + filterCantjoinButton.setOnToggle(() -> panelPartyFinder.onChestUpdate(null)); + add(filterCantjoin); + } + { + filterWhitelist = new MTextField() { + @Override + public void edit(String str) { + panelPartyFinder.onChestUpdate(null); + FeatureRegistry.PARTYKICKER_CUSTOM.setWhitelist(str); + } + }; + filterBlacklist = new MTextField() { + @Override + public void edit(String str) { + FeatureRegistry.PARTYKICKER_CUSTOM.setBlacklist(str); + panelPartyFinder.onChestUpdate(null); + } + }; + highlightNote = new MTextField() { + @Override + public void edit(String str) { + super.edit(str); + FeatureRegistry.PARTYKICKER_CUSTOM.setHighlight(str); + } + }; + blacklistClassTxt = new MTextField() { + @Override + public void edit(String str) { + super.edit(str); + FeatureRegistry.PARTYKICKER_CUSTOM.setBlacklistClass(str); + panelPartyFinder.onChestUpdate(null); + } + }; + + filterWhitelist.setText(FeatureRegistry.PARTYKICKER_CUSTOM.getWhitelist()); + filterBlacklist.setText(FeatureRegistry.PARTYKICKER_CUSTOM.getBlacklist()); + highlightNote.setText(FeatureRegistry.PARTYKICKER_CUSTOM.getHighlight()); + blacklistClassTxt.setText(FeatureRegistry.PARTYKICKER_CUSTOM.getBlacklistClass()); + + filterWhitelistNote = new MPassiveLabelAndElement("Whitelist Note", filterWhitelist); + filterBlacklistNote = new MPassiveLabelAndElement("Blacklist Note", filterBlacklist); + plaeHighlightNote = new MPassiveLabelAndElement("Highlight Note", highlightNote); + blacklistClass = new MPassiveLabelAndElement("Blacklist Class", blacklistClassTxt); + + filterWhitelistNote.setDivideRatio(0.5); + filterBlacklistNote.setDivideRatio(0.5); + plaeHighlightNote.setDivideRatio(0.5); + blacklistClass.setDivideRatio(0.5); + add(filterWhitelistNote); + add(filterBlacklistNote); + add(plaeHighlightNote); + add(blacklistClass); + } + { + integerSelection = new MIntegerSelectionButton(FeatureRegistry.PARTYKICKER_CUSTOM.getMinimumCata()); + integerSelection.setOnUpdate(() -> { + FeatureRegistry.PARTYKICKER_CUSTOM.setMinimumCata(integerSelection.getData()); + panelPartyFinder.onChestUpdate(null); + }); + cataLv = new MPassiveLabelAndElement("Minimum Cata Lv", integerSelection); + cataLv.setDivideRatio(0.5); add(cataLv); + } + } + + private void createNew() { + if (PartyManager.INSTANCE.getPartyContext() != null && !PartyManager.INSTANCE.isLeader()) { + ChatProcessor.INSTANCE.addToChatQueue("/p leave ", () -> {}, true); + return; + } + GuiChest chest = panelPartyFinder.getGuiCustomPartyFinder().getGuiChest(); + if (delistable) + Minecraft.getMinecraft().playerController.windowClick(chest.inventorySlots.windowId, 9*5+7, 0, 0, Minecraft.getMinecraft().thePlayer); + else + Minecraft.getMinecraft().playerController.windowClick(chest.inventorySlots.windowId, 9*5+0, 0, 0, Minecraft.getMinecraft().thePlayer); + + } + + public String getHighlightText() { + return highlightNote.getText(); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj; + + + GuiCustomPartyFinder guiCustomPartyFinder = panelPartyFinder.getGuiCustomPartyFinder(); + if (guiCustomPartyFinder.getGuiChest() == null) return; + Slot s = guiCustomPartyFinder.getGuiChest().inventorySlots.getSlot(9*5+5); + ItemStack itemStack = s.getStack(); + if (itemStack == null) return; + + String dungeon="", floor="", text=""; + { + NBTTagCompound stackTagCompound = itemStack.getTagCompound(); + if (stackTagCompound.hasKey("display", 10)) { + NBTTagCompound nbttagcompound = stackTagCompound.getCompoundTag("display"); + + if (nbttagcompound.getTagId("Lore") == 9) { + NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8); + + for (int i = 0; i < nbttaglist1.tagCount(); i++) { + String str = nbttaglist1.getStringTagAt(i); + if (str.startsWith("§aDungeon: ")) { + dungeon = str.substring(11); + } else if (str.startsWith("§aFloor: ")) { + floor = str.substring(9); + } else if (str.startsWith("§aSearch text: ")) { + text = str.substring(15); + } + } + } + } + } + fontRenderer.drawString("§aSearching: "+dungeon+" §7- "+floor, 5,155,-1); + fontRenderer.drawString("§aSearch text: "+text, 5,155+fontRenderer.FONT_HEIGHT,-1); + + Gui.drawRect(0,160+fontRenderer.FONT_HEIGHT*2,getBounds().width, 161+fontRenderer.FONT_HEIGHT*2, -1); + GlStateManager.translate(5,165+fontRenderer.FONT_HEIGHT*2,0); + + s = guiCustomPartyFinder.getGuiChest().inventorySlots.getSlot(9*5+8); + itemStack = s.getStack(); + if (itemStack == null || itemStack.getItem() != Items.skull) return; + + List<String> list = itemStack.getTooltip(Minecraft.getMinecraft().thePlayer, Minecraft.getMinecraft().gameSettings.advancedItemTooltips); + for (int i = 0; i < list.size(); ++i) { + if (i == 0) { + list.set(i, itemStack.getRarity().rarityColor + list.get(i)); + } else { + list.set(i, EnumChatFormatting.GRAY + list.get(i)); + } + } + for (int i = 0; i < list.size(); i++) { + fontRenderer.drawString(list.get(i), 0, (i)*fontRenderer.FONT_HEIGHT, -1); + } + } + + public void refresh() { + GuiChest chest = panelPartyFinder.getGuiCustomPartyFinder().getGuiChest(); + Minecraft.getMinecraft().playerController.windowClick(chest.inventorySlots.windowId, 9*5+1, 0, 0, Minecraft.getMinecraft().thePlayer); + } + public void settings() { + GuiChest chest = panelPartyFinder.getGuiCustomPartyFinder().getGuiChest(); + Minecraft.getMinecraft().playerController.windowClick(chest.inventorySlots.windowId, 9*5+5, 0, 0, Minecraft.getMinecraft().thePlayer); + } + + @Override + public void onBoundsUpdate() { + Dimension bounds = getEffectiveDimension(); + refresh.setBounds(new Rectangle(5,5,(bounds.width-10)/2,15)); + createNew.setBounds(new Rectangle(bounds.width/2,5,(bounds.width-10)/2,15)); + filterCantjoin.setBounds(new Rectangle(5,22,bounds.width-10,15)); + filterWhitelistNote.setBounds(new Rectangle(5,39,bounds.width-10,15)); + filterBlacklistNote.setBounds(new Rectangle(5,56,bounds.width-10,15)); + plaeHighlightNote.setBounds(new Rectangle(5,73,bounds.width-10,15)); + cataLv.setBounds(new Rectangle(5,90,bounds.width-10,15)); + blacklistClass.setBounds(new Rectangle(5,107,bounds.width-10,15)); + settings.setBounds(new Rectangle(5,124,bounds.width-10,15)); + } + + public boolean filter(ItemStack itemStack) { + NBTTagCompound stackTagCompound = itemStack.getTagCompound(); + String note = ""; + int dLV = 0; + Set<String> invalidClasses = new HashSet<>(); + for (String s : blacklistClassTxt.getText().split(",")) { + invalidClasses.add(s.toLowerCase()); + } + if (stackTagCompound.hasKey("display", 10)) { + NBTTagCompound nbttagcompound = stackTagCompound.getCompoundTag("display"); + + if (nbttagcompound.getTagId("Lore") == 9) { + NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8); + + for (int i = 0; i < nbttaglist1.tagCount(); i++) { + String str = nbttaglist1.getStringTagAt(i); + if (str.startsWith("§cRequires ") && filterCantjoinButton.isEnabled()) return false; + if (str.startsWith("§7§7Note:")) { + note = str.substring(12); + } + if (str.startsWith("§7Dungeon Level Required: §b")) { + dLV = Integer.parseInt(str.substring(28)); + } + if (str.startsWith(" ") && str.contains(":")) { + String clazz = TextUtils.stripColor(str).trim().split(" ")[1]; + if (invalidClasses.contains(clazz.toLowerCase())) return false; + } + } + } + } + if (integerSelection.getData() >dLV) return false; + + if (!filterBlacklist.getText().isEmpty()) { + for (String s1 : filterBlacklist.getText().split(",")) { + if (note.toLowerCase().contains(s1.toLowerCase())) return false; + } + } + if (!filterWhitelist.getText().isEmpty()) { + boolean s = false; + for (String s1 : filterWhitelist.getText().split(",")) { + if (note.toLowerCase().contains(s1.toLowerCase())) { + s = true; break; + } + } + if (!s) return false; + } + return true; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyListElement.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyListElement.java new file mode 100644 index 00000000..67771f46 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyListElement.java @@ -0,0 +1,236 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.customgui; + +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MTooltip; +import kr.syeyoung.dungeonsguide.gui.elements.MTooltipText; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.entity.RenderItem; +import net.minecraft.init.Blocks; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.EnumChatFormatting; + +import java.awt.*; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class PanelPartyListElement extends MPanel { + private PanelPartyFinder panelPartyFinder; + private int slot; + + public PanelPartyListElement(PanelPartyFinder panelPartyFinder, int slot) { + this.panelPartyFinder = panelPartyFinder; + this.slot = slot; + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(-1, 32); + } + + private MTooltip mTooltip; + + private ItemStack lastStack; + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + GuiCustomPartyFinder guiCustomPartyFinder = panelPartyFinder.getGuiCustomPartyFinder(); + if (guiCustomPartyFinder.getGuiChest() == null) return; + Slot s = guiCustomPartyFinder.getGuiChest().inventorySlots.getSlot(slot); + ItemStack itemStack = s.getStack(); + if (itemStack == null && lastStack == null) return; + if (itemStack != null) + lastStack = itemStack; + else + itemStack = lastStack; + int color = RenderUtils.blendAlpha(0x141414, 0.0f); + + String note = ""; + boolean notfound = false; + boolean cantjoin = false; + if (itemStack.getItem() == Item.getItemFromBlock(Blocks.bedrock)) { + cantjoin = true; + notfound = true; + } + int minClass = -1, minDungeon = -1; + int pplIn = 0; + Set<String> dungeonClasses = new HashSet<>(); + { + NBTTagCompound stackTagCompound = itemStack.getTagCompound(); + if (stackTagCompound.hasKey("display", 10)) { + NBTTagCompound nbttagcompound = stackTagCompound.getCompoundTag("display"); + + if (nbttagcompound.getTagId("Lore") == 9) { + NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8); + + for (int i = 0; i < nbttaglist1.tagCount(); i++) { + String str = nbttaglist1.getStringTagAt(i); + if (str.startsWith("§7§7Note:")) { + note = str.substring(12); + } else if (str.startsWith("§7Class Level Required: §b")) { + minClass = Integer.parseInt(str.substring(26)); + } else if (str.startsWith("§7Dungeon Level Required: §b")) { + minDungeon = Integer.parseInt(str.substring(28)); + } else if (str.startsWith("§cRequires ")) cantjoin = true; + if (str.endsWith("§b)")) pplIn ++; + + if (str.startsWith(" ") && str.contains(":")) { + String clazz = TextUtils.stripColor(str).trim().split(" ")[1]; + dungeonClasses.add(clazz); + } + } + } + } + } + + boolean nodupe = note.toLowerCase().contains("nodupe") || note.toLowerCase().contains("no dupe") || (note.toLowerCase().contains("nd") && (note.toLowerCase().indexOf("nd") == 0 || note.charAt(note.toLowerCase().indexOf("nd")-1) == ' ')); + + note = note.replaceAll("(?i)(S\\+)", "§6$1§r"); + note = note.replaceAll("(?i)(carry)", "§4$1§r"); + + try { + if (!panelPartyFinder.getHighlightNote().isEmpty()) { + for (String s1 : panelPartyFinder.getHighlightNote().split(",")) { + note = note.replaceAll("(?i)(" + s1 + ")", "§e§l$1§r"); + } + } + } catch (Exception e) {} + + if (cantjoin) {} + else if (clicked) { + color = RenderUtils.blendAlpha(0x141414, 0.10f); + } else if (lastAbsClip.contains(absMousex, absMousey) && (getTooltipsOpen() == 0 || (mTooltip != null && mTooltip.isOpen()))) { + color = RenderUtils.blendAlpha(0x141414, 0.12f); + } + if (cantjoin) {} + else if (note.contains("§e")) { + color = RenderUtils.blendTwoColors(color, 0x44FFFF00); + } else if (note.contains("§6")){ + color = RenderUtils.blendTwoColors(color, 0x44FFAA00); + } + + if (nodupe && dungeonClasses.contains(FeatureRegistry.PARTYKICKER_CUSTOM.getLastClass())) { + color = RenderUtils.blendTwoColors(color, 0x44FF0000); + note = note.replace("nodupe", "§cnodupe§r").replace("no dupe", "§cno dupe§r").replace("nd", "§cnd§r"); + } + Gui.drawRect(0,0,getBounds().width,getBounds().height,color); + + RenderItem renderItem= Minecraft.getMinecraft().getRenderItem(); + GlStateManager.pushMatrix(); + RenderHelper.disableStandardItemLighting(); + RenderHelper.enableGUIStandardItemLighting(); + GlStateManager.scale(2,2,1); + GlStateManager.enableDepth(); + renderItem.renderItemAndEffectIntoGUI(itemStack, 0,0); + GlStateManager.popMatrix(); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GlStateManager.pushMatrix(); + GlStateManager.translate(37,(32 - 2*fr.FONT_HEIGHT)/2,0); + GlStateManager.scale(2,2,1); + String name = itemStack.getDisplayName(); + if (name.contains("'")) + name = name.substring(0, name.indexOf("'")); + fr.drawString(name, 0,0,-1); + + if (!notfound) + note = "§7("+pplIn+") §f"+note; + fr.drawString(note, fr.getStringWidth("AAAAAAAAAAAAAAAA")+5, 0,-1); + GlStateManager.popMatrix(); + GlStateManager.pushMatrix(); + String sideNote = ""; + if (minClass != -1) sideNote += "§7CLv ≥§b"+minClass+" "; + if (minDungeon != -1) sideNote += "§7DLv ≥§b"+minDungeon+" "; + if (cantjoin && !notfound) sideNote = "§cCan't join"; + sideNote = sideNote.trim(); + + GlStateManager.translate(getBounds().width,(32 - 2*fr.FONT_HEIGHT)/2,0); + GlStateManager.scale(2,2,0); + GlStateManager.translate(-fr.getStringWidth(sideNote), 0,0); + fr.drawString(sideNote, 0,0,-1); + + GlStateManager.popMatrix(); + if (lastAbsClip.contains(absMousex, absMousey) && (mTooltip == null || !mTooltip.isOpen()) && getTooltipsOpen() == 0) { + if (mTooltip != null) mTooltip.close(); + List<String> list = itemStack.getTooltip(Minecraft.getMinecraft().thePlayer, Minecraft.getMinecraft().gameSettings.advancedItemTooltips); + for (int i = 0; i < list.size(); ++i) { + if (i == 0) { + list.set(i, itemStack.getRarity().rarityColor + list.get(i)); + } else { + list.set(i, EnumChatFormatting.GRAY + list.get(i)); + } + } + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + mTooltip = new MTooltipText(list); + mTooltip.setScale(scaledResolution.getScaleFactor()); + mTooltip.open(this); + } else if (!lastAbsClip.contains(absMousex, absMousey)){ + if (mTooltip != null) + mTooltip.close(); + mTooltip = null; + } + } + + @Override + public void setParent(MPanel parent) { + super.setParent(parent); + if (parent == null && mTooltip != null) { + mTooltip.close(); + mTooltip = null; + } + } + + boolean clicked = false; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (lastAbsClip.contains(absMouseX, absMouseY)&& (getTooltipsOpen() == 0 || (mTooltip != null && mTooltip.isOpen()))) { + clicked = true; + + GuiChest chest = panelPartyFinder.getGuiCustomPartyFinder().getGuiChest(); + Minecraft.getMinecraft().playerController.windowClick(chest.inventorySlots.windowId, slot, 0, 0, Minecraft.getMinecraft().thePlayer); + } + } + + @Override + public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) { + clicked = false; + } + + @Override + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + if (lastAbsClip.contains(absMouseX, absMouseY) && (getTooltipsOpen() == 0 || (mTooltip != null && mTooltip.isOpen()))) { + setCursor(EnumCursor.POINTING_HAND); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRenderDungeonFloorStat.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRenderDungeonFloorStat.java new file mode 100644 index 00000000..a1b1d36b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRenderDungeonFloorStat.java @@ -0,0 +1,101 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.*; +import kr.syeyoung.dungeonsguide.features.impl.party.api.*; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraftforge.fml.client.config.GuiUtils; + +import java.awt.*; +import java.util.Arrays; + +public class DataRenderDungeonFloorStat implements DataRenderer { + private final DungeonType dungeonType; + private final int floor; + public DataRenderDungeonFloorStat(DungeonType dungeonType, int floor) { + this.dungeonType = dungeonType; + this.floor = floor; + } + + @Override + public Dimension renderData(PlayerProfile playerProfile) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + String floorName = (dungeonType == DungeonType.CATACOMBS ? "F" : "M") + floor; + + boolean flag = false; + DungeonSpecificData<DungeonStat> dungeonStatDungeonSpecificData = playerProfile.getDungeonStats().get(dungeonType); + if (dungeonStatDungeonSpecificData != null) { + FloorSpecificData<DungeonStat.PlayedFloor> playedFloorFloorSpecificData = dungeonStatDungeonSpecificData.getData().getPlays().get(floor); + if (playedFloorFloorSpecificData != null) { + flag = true; + fr.drawString("§b" + floorName + " §a" + playedFloorFloorSpecificData.getData().getBestScore() + " §f" + playedFloorFloorSpecificData.getData().getCompletions() + "§7/§f" + playedFloorFloorSpecificData.getData().getWatcherKills() + "§7/§f" + playedFloorFloorSpecificData.getData().getTimes_played() + " §7(" + (int) (playedFloorFloorSpecificData.getData().getCompletions()*100 / (double) playedFloorFloorSpecificData.getData().getWatcherKills()) + "%)", 0, 0, -1); + fr.drawString("§6S+ §e" + (playedFloorFloorSpecificData.getData().getFastestTimeSPlus() != -1 ? TextUtils.formatTime(playedFloorFloorSpecificData.getData().getFastestTimeSPlus()) : "§7N/A") + " §6S §e" + (playedFloorFloorSpecificData.getData().getFastestTimeS() != -1 ? TextUtils.formatTime(playedFloorFloorSpecificData.getData().getFastestTimeS()) : "§7N/A"), 0, fr.FONT_HEIGHT, -1); + } + } + if (!flag) { + fr.drawString("§cNo Stat for "+floorName, 0,0,-1); + } + + return getDimension(); + } + + @Override + public Dimension renderDummy() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + String floorName = (dungeonType == DungeonType.CATACOMBS ? "F" : "M") + floor; + + + fr.drawString("§b"+floorName+" §a305 §f10§7/§f35§7/§f50 §7("+(int)(1000.0/35.0)+"%)", 0,0,-1); + fr.drawString("§6S+ §e10m 53s §6S §e15m 13s", 0, fr.FONT_HEIGHT, -1); + return getDimension(); + } + + @Override + public Dimension getDimension() { + return new Dimension(100, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT*2); + } + + @Override + public void onHover(PlayerProfile playerProfile, int mouseX, int mouseY) { + + DungeonSpecificData<DungeonStat> dungeonStatDungeonSpecificData = playerProfile.getDungeonStats().get(dungeonType); + if (dungeonStatDungeonSpecificData == null) return; + FloorSpecificData<DungeonStat.PlayedFloor> playedFloorFloorSpecificData = dungeonStatDungeonSpecificData.getData().getPlays().get(floor); + if (playedFloorFloorSpecificData == null) return; + String floorName = (dungeonType == DungeonType.CATACOMBS ? "F" : "M") + floor; + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + GuiUtils.drawHoveringText(Arrays.asList( + "§bFloor "+floorName, + "§bBest Score§7: §f"+playedFloorFloorSpecificData.getData().getBestScore(), + "§bTotal Completions§7: §f"+playedFloorFloorSpecificData.getData().getCompletions(), + "§bTotal Watcher kills§7: §f"+playedFloorFloorSpecificData.getData().getWatcherKills(), + "§bTotal Runs§7: §f"+playedFloorFloorSpecificData.getData().getTimes_played(), + "§bFastest S+§7: §f"+(playedFloorFloorSpecificData.getData().getFastestTimeSPlus() != -1? TextUtils.formatTime(playedFloorFloorSpecificData.getData().getFastestTimeSPlus()) : "§7N/A"), + "§bFastest S§7: §f"+(playedFloorFloorSpecificData.getData().getFastestTimeS() != -1? TextUtils.formatTime(playedFloorFloorSpecificData.getData().getFastestTimeS()) : "§7N/A"), + "§bFastest Run§7: §f"+(playedFloorFloorSpecificData.getData().getFastestTime() != -1? TextUtils.formatTime(playedFloorFloorSpecificData.getData().getFastestTime()) : "§7N/A"), + "§bMost Mobs Killed§7: §f"+playedFloorFloorSpecificData.getData().getMostMobsKilled(), + "§bTotal Mobs Killed§7: §f"+playedFloorFloorSpecificData.getData().getMobsKilled() + ), mouseX, mouseY, scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, Minecraft.getMinecraft().fontRendererObj); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRenderDungeonHighestFloorStat.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRenderDungeonHighestFloorStat.java new file mode 100644 index 00000000..7ab9a396 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRenderDungeonHighestFloorStat.java @@ -0,0 +1,103 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.*; +import kr.syeyoung.dungeonsguide.features.impl.party.api.*; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraftforge.fml.client.config.GuiUtils; + +import java.awt.*; +import java.util.Arrays; + +public class DataRenderDungeonHighestFloorStat implements DataRenderer { + private final DungeonType dungeonType; + public DataRenderDungeonHighestFloorStat(DungeonType dungeonType) { + this.dungeonType = dungeonType; + } + + @Override + public Dimension renderData(PlayerProfile playerProfile) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + boolean flag = false; + DungeonSpecificData<DungeonStat> dungeonStatDungeonSpecificData = playerProfile.getDungeonStats().get(dungeonType); + if (dungeonStatDungeonSpecificData != null) { + if (dungeonStatDungeonSpecificData.getData().getHighestCompleted() != -1) { + FloorSpecificData<DungeonStat.PlayedFloor> playedFloorFloorSpecificData = dungeonStatDungeonSpecificData.getData().getPlays().get(dungeonStatDungeonSpecificData.getData().getHighestCompleted()); + String floorName = (dungeonType == DungeonType.CATACOMBS ? "F" : "M") + dungeonStatDungeonSpecificData.getData().getHighestCompleted(); + if (playedFloorFloorSpecificData != null) { + flag = true; + fr.drawString("§bH: " + floorName + " §a" + playedFloorFloorSpecificData.getData().getBestScore() + " §f" + playedFloorFloorSpecificData.getData().getCompletions() + "§7/§f" + playedFloorFloorSpecificData.getData().getWatcherKills() + "§7/§f" + playedFloorFloorSpecificData.getData().getTimes_played() + " §7(" + (int) (playedFloorFloorSpecificData.getData().getCompletions() *100/ (double) playedFloorFloorSpecificData.getData().getWatcherKills()) + "%)", 0, 0, -1); + fr.drawString("§6S+ §e" + (playedFloorFloorSpecificData.getData().getFastestTimeSPlus() != -1 ? TextUtils.formatTime(playedFloorFloorSpecificData.getData().getFastestTimeSPlus()) : "§7N/A") + " §6S §e" + (playedFloorFloorSpecificData.getData().getFastestTimeS() != -1 ? TextUtils.formatTime(playedFloorFloorSpecificData.getData().getFastestTimeS()) : "§7N/A"), 0, fr.FONT_HEIGHT, -1); + } + } + } + if (!flag) { + fr.drawString("§cNo Highest Floor for ", 0,0,-1); + fr.drawString("§c"+dungeonType.getFamiliarName(), 0,fr.FONT_HEIGHT,-1); + } + + return getDimension(); + } + + @Override + public Dimension renderDummy() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + String floorName = (dungeonType == DungeonType.CATACOMBS ? "F" : "M") + "9"; + + + fr.drawString("§bH: "+floorName+" §a305 §f10§7/§f35§7/§f50 §7("+(int)(1000.0/35.0)+"%)", 0,0,-1); + fr.drawString("§6S+ §e10m 53s §6S §e15m 13s", 0, fr.FONT_HEIGHT, -1); + return getDimension(); + } + + @Override + public Dimension getDimension() { + return new Dimension(100, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT*2); + } + + @Override + public void onHover(PlayerProfile playerProfile, int mouseX, int mouseY) { + + DungeonSpecificData<DungeonStat> dungeonStatDungeonSpecificData = playerProfile.getDungeonStats().get(dungeonType); + if (dungeonStatDungeonSpecificData == null) return; + if (dungeonStatDungeonSpecificData.getData().getHighestCompleted() == -1) return; + FloorSpecificData<DungeonStat.PlayedFloor> playedFloorFloorSpecificData = dungeonStatDungeonSpecificData.getData().getPlays().get( dungeonStatDungeonSpecificData.getData().getHighestCompleted()); + if (playedFloorFloorSpecificData == null) return; + String floorName = (dungeonType == DungeonType.CATACOMBS ? "F" : "M") + dungeonStatDungeonSpecificData.getData().getHighestCompleted(); + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + GuiUtils.drawHoveringText(Arrays.asList( + "§bFloor "+floorName, + "§bBest Score§7: §f"+playedFloorFloorSpecificData.getData().getBestScore(), + "§bTotal Completions§7: §f"+playedFloorFloorSpecificData.getData().getCompletions(), + "§bTotal Watcher kills§7: §f"+playedFloorFloorSpecificData.getData().getWatcherKills(), + "§bTotal Runs§7: §f"+playedFloorFloorSpecificData.getData().getTimes_played(), + "§bFastest S+§7: §f"+(playedFloorFloorSpecificData.getData().getFastestTimeSPlus() != -1? TextUtils.formatTime(playedFloorFloorSpecificData.getData().getFastestTimeSPlus()) : "§7N/A"), + "§bFastest S§7: §f"+(playedFloorFloorSpecificData.getData().getFastestTimeS() != -1? TextUtils.formatTime(playedFloorFloorSpecificData.getData().getFastestTimeS()) : "§7N/A"), + "§bFastest Run§7: §f"+(playedFloorFloorSpecificData.getData().getFastestTime() != -1? TextUtils.formatTime(playedFloorFloorSpecificData.getData().getFastestTime()) : "§7N/A"), + "§bMost Mobs Killed§7: §f"+playedFloorFloorSpecificData.getData().getMostMobsKilled(), + "§bTotal Mobs Killed§7: §f"+playedFloorFloorSpecificData.getData().getMobsKilled() + ), mouseX, mouseY, scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, Minecraft.getMinecraft().fontRendererObj); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRenderer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRenderer.java new file mode 100644 index 00000000..406963e6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRenderer.java @@ -0,0 +1,33 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; + +import java.awt.*; + +public interface DataRenderer { + Dimension renderData(PlayerProfile playerProfile); + void onHover(PlayerProfile playerProfile, int mouseX, int mouseY); + + + Dimension renderDummy(); + + Dimension getDimension(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererClassLv.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererClassLv.java new file mode 100644 index 00000000..a2a468d1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererClassLv.java @@ -0,0 +1,88 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.ClassSpecificData; +import kr.syeyoung.dungeonsguide.features.impl.party.api.DungeonClass; +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import kr.syeyoung.dungeonsguide.features.impl.party.api.*; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import kr.syeyoung.dungeonsguide.utils.XPUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraftforge.fml.client.config.GuiUtils; + +import java.awt.*; +import java.util.Arrays; + +public class DataRendererClassLv implements DataRenderer { + private final DungeonClass dungeonClass; + public DataRendererClassLv(DungeonClass dungeonClass) { + this.dungeonClass = dungeonClass; + } + @Override + public Dimension renderData(PlayerProfile playerProfile) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + ClassSpecificData<PlayerProfile.PlayerClassData> dungeonStatDungeonSpecificData = playerProfile.getPlayerClassData().get(dungeonClass); + boolean selected = playerProfile.getSelectedClass() == dungeonClass; + if (dungeonStatDungeonSpecificData == null) { + fr.drawString(dungeonClass.getFamilarName(), 0,0, 0xFF55ffff); + fr.drawString("Unknown", fr.getStringWidth(dungeonClass.getFamilarName()+" "),0,0xFFFFFFFF); + if (selected) + fr.drawString("★", fr.getStringWidth(dungeonClass.getFamilarName()+" Unknown "),0,0xFFAAAAAA); + } else { + XPUtils.XPCalcResult xpCalcResult = XPUtils.getCataXp(dungeonStatDungeonSpecificData.getData().getExperience()); + fr.drawString(dungeonClass.getFamilarName(), 0,0, 0xFF55ffff); + fr.drawString(xpCalcResult.getLevel()+"", fr.getStringWidth(dungeonClass.getFamilarName()+" "),0,0xFFFFFFFF); + if (selected) + fr.drawString("★", fr.getStringWidth(dungeonClass.getFamilarName()+" "+xpCalcResult.getLevel()+" "),0,0xFFAAAAAA); + + RenderUtils.renderBar(0, fr.FONT_HEIGHT, 100,xpCalcResult.getRemainingXp() == 0 ? 1 : (float) (xpCalcResult.getRemainingXp() / xpCalcResult.getNextLvXp())); + } + + return new Dimension(100, fr.FONT_HEIGHT*2); + } + + @Override + public Dimension renderDummy() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString(dungeonClass.getFamilarName(), 0,0, 0xFF55ffff); + fr.drawString("99", fr.getStringWidth(dungeonClass.getFamilarName()+" "),0,0xFFFFFFFF); + fr.drawString("★", fr.getStringWidth(dungeonClass.getFamilarName()+" 99 "),0,0xFFAAAAAA); + RenderUtils.renderBar(0, fr.FONT_HEIGHT, 100,1.0f); + return new Dimension(100, fr.FONT_HEIGHT*2); + } + @Override + public Dimension getDimension() { + return new Dimension(100, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT*2); + } + + @Override + public void onHover(PlayerProfile playerProfile, int mouseX, int mouseY) { + ClassSpecificData<PlayerProfile.PlayerClassData> dungeonStatDungeonSpecificData = playerProfile.getPlayerClassData().get(dungeonClass); + if (dungeonStatDungeonSpecificData == null) return; + XPUtils.XPCalcResult xpCalcResult = XPUtils.getCataXp(dungeonStatDungeonSpecificData.getData().getExperience()); + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + + GuiUtils.drawHoveringText(Arrays.asList("§bCurrent Lv§7: §e"+xpCalcResult.getLevel(),"§bExp§7: §e"+ TextUtils.format((long)xpCalcResult.getRemainingXp()) + "§7/§e"+TextUtils.format((long)xpCalcResult.getNextLvXp()), "§bTotal Xp§7: §e"+ TextUtils.format((long)dungeonStatDungeonSpecificData.getData().getExperience())),mouseX, mouseY, + scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, Minecraft.getMinecraft().fontRendererObj); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererDungeonLv.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererDungeonLv.java new file mode 100644 index 00000000..cabbdc02 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererDungeonLv.java @@ -0,0 +1,81 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.DungeonSpecificData; +import kr.syeyoung.dungeonsguide.features.impl.party.api.DungeonStat; +import kr.syeyoung.dungeonsguide.features.impl.party.api.DungeonType; +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import kr.syeyoung.dungeonsguide.utils.XPUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraftforge.fml.client.config.GuiUtils; + +import java.awt.*; +import java.util.Arrays; + +public class DataRendererDungeonLv implements DataRenderer { + private final DungeonType dungeonType; + public DataRendererDungeonLv(DungeonType dungeonType) { + this.dungeonType = dungeonType; + } + @Override + public Dimension renderData(PlayerProfile playerProfile) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + DungeonSpecificData<DungeonStat> dungeonStatDungeonSpecificData = playerProfile.getDungeonStats().get(dungeonType); + if (dungeonStatDungeonSpecificData == null) { + fr.drawString(dungeonType.getFamiliarName(), 0,0, 0xFFFF5555); + fr.drawString("Unknown", fr.getStringWidth(dungeonType.getFamiliarName()+" "),0,0xFFFFFFFF); + } else { + XPUtils.XPCalcResult xpCalcResult = XPUtils.getCataXp(dungeonStatDungeonSpecificData.getData().getExperience()); + fr.drawString(dungeonType.getFamiliarName(), 0,0, 0xFFFF5555); + fr.drawString(xpCalcResult.getLevel()+"", fr.getStringWidth(dungeonType.getFamiliarName()+" "),0,0xFFFFFFFF); + + RenderUtils.renderBar(0, fr.FONT_HEIGHT, 100,xpCalcResult.getRemainingXp() == 0 ? 1 : (float) (xpCalcResult.getRemainingXp() / xpCalcResult.getNextLvXp())); + } + + return new Dimension(100, fr.FONT_HEIGHT*2); + } + + @Override + public Dimension renderDummy() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString(dungeonType.getFamiliarName(), 0,0, 0xFFFF5555); + fr.drawString("99", fr.getStringWidth(dungeonType.getFamiliarName()+" "),0,0xFFFFFFFF); + RenderUtils.renderBar(0, fr.FONT_HEIGHT, 100,1.0f); + return new Dimension(100, fr.FONT_HEIGHT*2); + } + @Override + public Dimension getDimension() { + return new Dimension(100, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT*2); + } + + @Override + public void onHover(PlayerProfile playerProfile, int mouseX, int mouseY) { + DungeonSpecificData<DungeonStat> dungeonStatDungeonSpecificData = playerProfile.getDungeonStats().get(dungeonType); + if (dungeonStatDungeonSpecificData == null) return; + XPUtils.XPCalcResult xpCalcResult = XPUtils.getCataXp(dungeonStatDungeonSpecificData.getData().getExperience()); + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + GuiUtils.drawHoveringText(Arrays.asList("§bCurrent Lv§7: §e"+xpCalcResult.getLevel(),"§bExp§7: §e"+TextUtils.format((long)xpCalcResult.getRemainingXp()) + "§7/§e"+TextUtils.format((long)xpCalcResult.getNextLvXp()), "§bTotal Xp§7: §e"+ TextUtils.format((long)dungeonStatDungeonSpecificData.getData().getExperience())),mouseX, mouseY, + scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, Minecraft.getMinecraft().fontRendererObj); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererEditor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererEditor.java new file mode 100644 index 00000000..fd3261c1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererEditor.java @@ -0,0 +1,356 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class DataRendererEditor extends MPanel { + private final FeatureViewPlayerOnJoin feature; + + public DataRendererEditor(FeatureViewPlayerOnJoin featureViewPlayerOnJoin) { + this.feature = featureViewPlayerOnJoin; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10, 260)); + } + + private String currentlySelected; + private int selectedX; + private int selectedY; + private int lastX; + private int lastY; + private int scrollY; + private final int baseWidth = 120; + private final int hamburgerWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth("=="); + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + Gui.drawRect(0,0,getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.12f)); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Available", (310 + baseWidth + hamburgerWidth -fr.getStringWidth("Available")) / 2, 4, 0xFFFFFFFF); + fr.drawString("Current", (baseWidth + hamburgerWidth+10 -fr.getStringWidth("Current")) /2 , 4, 0xFFFFFFFF); + Gui.drawRect(4,4 + fr.FONT_HEIGHT + 3,baseWidth + hamburgerWidth+6 + 1, 236+ fr.FONT_HEIGHT + 3, 0xFF222222); + Gui.drawRect(5,5+ fr.FONT_HEIGHT + 3,baseWidth + hamburgerWidth + 5 + 1, 235+ fr.FONT_HEIGHT + 3, RenderUtils.blendAlpha(0x141414, 0.15f)); + Gui.drawRect(5 + hamburgerWidth,4+ fr.FONT_HEIGHT + 3,6 + hamburgerWidth, 236+ fr.FONT_HEIGHT + 3, 0xFF222222); + + Gui.drawRect(154,4 + fr.FONT_HEIGHT + 3,150 + baseWidth + hamburgerWidth + 6+1, 236+ fr.FONT_HEIGHT + 3, 0xFF222222); + Gui.drawRect(155,5+ fr.FONT_HEIGHT + 3,150 + baseWidth + hamburgerWidth + 5+1, 235+ fr.FONT_HEIGHT + 3, RenderUtils.blendAlpha(0x141414, 0.15f)); + Gui.drawRect(155 + hamburgerWidth,4 + fr.FONT_HEIGHT + 3,156 + hamburgerWidth, 236+ fr.FONT_HEIGHT + 3, 0xFF222222); + + GlStateManager.pushMatrix(); + clip(scissor.x + 6+hamburgerWidth, scissor.y + 5+fr.FONT_HEIGHT+3, baseWidth, 230); + GlStateManager.translate(6+hamburgerWidth, 5+fr.FONT_HEIGHT+3, 0); + int culmutativeY = 0; + int relSelectedY = selectedY - (5+ fr.FONT_HEIGHT + 3); + boolean drewit = false; + for (String datarenderers : feature.<List<String>>getParameter("datarenderers").getValue()) { + + if (0 <= selectedX && selectedX <= hamburgerWidth+11 && currentlySelected != null) { + DataRenderer dataRenderer = DataRendererRegistry.getDataRenderer(currentlySelected); + Dimension dim; + if (dataRenderer == null) dim = new Dimension(0,fr.FONT_HEIGHT*2); + else dim = dataRenderer.getDimension(); + + if (culmutativeY + dim.height > relSelectedY && relSelectedY >= culmutativeY && !drewit) { + clip(scissor.x + 6 + hamburgerWidth, scissor.y + 5+fr.FONT_HEIGHT+3, baseWidth, 230); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + if (dataRenderer == null) { + fr.drawString("Couldn't find Datarenderer", 0,0, 0xFFFF0000); + fr.drawString(currentlySelected, 0,fr.FONT_HEIGHT, 0xFFFF0000); + dim = new Dimension(0, fr.FONT_HEIGHT * 2); + } else { + GlStateManager.pushMatrix(); + dim = dataRenderer.renderDummy(); + GlStateManager.popMatrix(); + } + clip(scissor.x, scissor.y, scissor.width, scissor.height); + GlStateManager.translate(-hamburgerWidth-1, 0, 0); + Gui.drawRect(0,0, hamburgerWidth, dim.height-1, 0xFF777777); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("=",fr.getStringWidth("=")/2,(dim.height - fr.FONT_HEIGHT) / 2, 0xFFFFFFFF); + GlStateManager.translate(hamburgerWidth+1,dim.height,0); + drewit = true; + } + } + + DataRenderer dataRenderer = DataRendererRegistry.getDataRenderer(datarenderers); + clip(scissor.x + 6 + hamburgerWidth, scissor.y + 5+fr.FONT_HEIGHT+3, baseWidth, 230); + Dimension dim; + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + if (dataRenderer == null) { + fr.drawString("Couldn't find Datarenderer", 0,0, 0xFFFF0000); + fr.drawString(datarenderers, 0,fr.FONT_HEIGHT, 0xFFFF0000); + dim = new Dimension(0, fr.FONT_HEIGHT * 2); + } else { + GlStateManager.pushMatrix(); + dim = dataRenderer.renderDummy(); + GlStateManager.popMatrix(); + } + clip(scissor.x, scissor.y, scissor.width, scissor.height); + GlStateManager.translate(-hamburgerWidth-1, 0, 0); + Gui.drawRect(0,0, hamburgerWidth, dim.height-1, 0xFFAAAAAA); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("=",fr.getStringWidth("=")/2,(dim.height - fr.FONT_HEIGHT) / 2, 0xFFFFFFFF); + GlStateManager.translate(hamburgerWidth+1,dim.height,0); + + culmutativeY += dim.height; + } + + if (currentlySelected != null && new Rectangle(0,5+fr.FONT_HEIGHT + 3, hamburgerWidth+11, 232).contains(selectedX, selectedY) && !drewit) { + DataRenderer dataRenderer = DataRendererRegistry.getDataRenderer(currentlySelected); + Dimension dim; + clip(scissor.x + 6 + hamburgerWidth, scissor.y + 5+fr.FONT_HEIGHT+3, baseWidth, 230); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + if (dataRenderer == null) { + fr.drawString("Couldn't find Datarenderer", 0,0, 0xFFFF0000); + fr.drawString(currentlySelected, 0,fr.FONT_HEIGHT, 0xFFFF0000); + dim = new Dimension(0, fr.FONT_HEIGHT * 2); + } else { + GlStateManager.pushMatrix(); + dim = dataRenderer.renderDummy(); + GlStateManager.popMatrix(); + } + clip(scissor.x, scissor.y, scissor.width, scissor.height); + GlStateManager.translate(-hamburgerWidth-1, 0, 0); + Gui.drawRect(0,0, hamburgerWidth, dim.height-1, 0xFF777777); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("=",fr.getStringWidth("=")/2,(dim.height - fr.FONT_HEIGHT) / 2, 0xFFFFFFFF); + GlStateManager.translate(hamburgerWidth+1,dim.height,0); + } + GlStateManager.popMatrix(); + + + GlStateManager.pushMatrix(); + GlStateManager.translate(156+hamburgerWidth, 5+fr.FONT_HEIGHT+3 - scrollY, 0); + + Set<String> rest = new HashSet<>(DataRendererRegistry.getValidDataRenderer()); + rest.removeAll( feature.<List<String>>getParameter("datarenderers").getValue()); + rest.remove(currentlySelected); + for (String datarenderers : rest) { + DataRenderer dataRenderer = DataRendererRegistry.getDataRenderer(datarenderers); + clip(scissor.x + 156 + hamburgerWidth, scissor.y + 5+fr.FONT_HEIGHT+3, baseWidth, 230); + Dimension dim; + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + if (dataRenderer == null) { + fr.drawString("Couldn't find Datarenderer", 0,0, 0xFFFF0000); + fr.drawString(datarenderers, 0,fr.FONT_HEIGHT, 0xFFFF0000); + dim = new Dimension(0, fr.FONT_HEIGHT * 2); + } else { + GlStateManager.pushMatrix(); + dim = dataRenderer.renderDummy(); + GlStateManager.popMatrix(); + } + clip(scissor.x + 155, scissor.y + 5+fr.FONT_HEIGHT+3, hamburgerWidth, 230); + GlStateManager.translate(-hamburgerWidth-1, 0, 0); + Gui.drawRect(0,0, hamburgerWidth, dim.height-1, 0xFFAAAAAA); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("=",fr.getStringWidth("=")/2,(dim.height - fr.FONT_HEIGHT) / 2, 0xFFFFFFFF); + GlStateManager.translate(hamburgerWidth+1,dim.height,0); + } + GlStateManager.popMatrix(); + clip(0,0,sr.getScaledWidth(), sr.getScaledHeight()); + { + if (currentlySelected != null) { + GlStateManager.pushMatrix(); + GlStateManager.translate(selectedX+hamburgerWidth+1, selectedY, 0); + DataRenderer dataRenderer = DataRendererRegistry.getDataRenderer(currentlySelected); + Dimension dim; + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + if (dataRenderer == null) { + fr.drawString("Couldn't find Datarenderer", 0, 0, 0xFFFF0000); + fr.drawString(currentlySelected, 0, fr.FONT_HEIGHT, 0xFFFF0000); + dim = new Dimension(0, fr.FONT_HEIGHT * 2); + } else { + GlStateManager.pushMatrix(); + dim = dataRenderer.renderDummy(); + GlStateManager.popMatrix(); + } + GlStateManager.translate(-hamburgerWidth-1, 0, 0); + Gui.drawRect(0,0, hamburgerWidth, dim.height-1, 0xFFAAAAAA); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("=",fr.getStringWidth("=")/2,(dim.height - fr.FONT_HEIGHT) / 2, 0xFFFFFFFF); + GlStateManager.popMatrix(); + } + } + clip(scissor.x, scissor.y, scissor.width, scissor.height); + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + super.mouseClicked(absMouseX, absMouseY, relMouseX, relMouseY, mouseButton); + lastX = relMouseX; + lastY = relMouseY; + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int legitRelY = relMouseY - (5+fr.FONT_HEIGHT+3); + if (new Rectangle(155,5+fr.FONT_HEIGHT + 3, hamburgerWidth, 230).contains(relMouseX, relMouseY)) { + Set<String> rest = new HashSet<>(DataRendererRegistry.getValidDataRenderer()); + rest.removeAll( feature.<List<String>>getParameter("datarenderers").getValue()); + rest.remove(currentlySelected); + int culmutativeY = -scrollY; + for (String datarenderers : rest) { + DataRenderer dataRenderer = DataRendererRegistry.getDataRenderer(datarenderers); + Dimension dim; + if (dataRenderer == null) { + dim = new Dimension(0, fr.FONT_HEIGHT * 2); + } else { + GlStateManager.pushMatrix(); + dim = dataRenderer.getDimension(); + GlStateManager.popMatrix(); + } + culmutativeY += dim.height; + + if (legitRelY < culmutativeY) { + currentlySelected = datarenderers; + selectedX = 155; + selectedY = culmutativeY - dim.height + 5+fr.FONT_HEIGHT + 3; + break; + } + } + } + if (new Rectangle(5,5+fr.FONT_HEIGHT + 3, hamburgerWidth, 230).contains(relMouseX, relMouseY)) { + List<String> rest = feature.<List<String>>getParameter("datarenderers").getValue(); + int culmutativeY = 0; + for (String datarenderers : rest) { + DataRenderer dataRenderer = DataRendererRegistry.getDataRenderer(datarenderers); + Dimension dim; + if (dataRenderer == null) { + dim = new Dimension(0, fr.FONT_HEIGHT * 2); + } else { + GlStateManager.pushMatrix(); + dim = dataRenderer.getDimension(); + GlStateManager.popMatrix(); + } + culmutativeY += dim.height; + + if (legitRelY < culmutativeY) { + currentlySelected = datarenderers; + selectedX = 5; + selectedY = culmutativeY - dim.height + 5+fr.FONT_HEIGHT + 3; + rest.remove(datarenderers); + break; + } + } + } + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + super.mouseClickMove(absMouseX, absMouseY, relMouseX, relMouseY, clickedMouseButton, timeSinceLastClick); + if (currentlySelected != null) { + int dx = relMouseX - lastX; + int dy = relMouseY - lastY; + selectedX += dx; + selectedY += dy; + } + lastX = relMouseX; + lastY = relMouseY; + } + + @Override + public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) { + super.mouseReleased(absMouseX, absMouseY, relMouseX, relMouseY, state); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int legitRelY = selectedY - (5+fr.FONT_HEIGHT+3); + if (currentlySelected != null && new Rectangle(0,5+fr.FONT_HEIGHT + 3, hamburgerWidth+11, 232).contains(selectedX, selectedY)) { + Set<String> rest = new HashSet<>(DataRendererRegistry.getValidDataRenderer()); + int culmutativeY = 0; + List<String > asdasdkasd = feature.<List<String>>getParameter("datarenderers").getValue(); + int index = asdasdkasd.size(); + for (int i = 0; i <asdasdkasd.size(); i++) { + String datarenderers = asdasdkasd.get(i); + DataRenderer dataRenderer = DataRendererRegistry.getDataRenderer(datarenderers); + Dimension dim; + if (dataRenderer == null) { + dim = new Dimension(0, fr.FONT_HEIGHT * 2); + } else { + GlStateManager.pushMatrix(); + dim = dataRenderer.getDimension(); + GlStateManager.popMatrix(); + } + culmutativeY += dim.height; + + if (legitRelY < culmutativeY) { + index = i; + break; + } + } + + asdasdkasd.add(index, currentlySelected); + } + + currentlySelected = null; + } + + @Override + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + super.mouseScrolled(absMouseX, absMouseY, relMouseX0, relMouseY0, scrollAmount); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + if (!new Rectangle(155,5+fr.FONT_HEIGHT + 3, hamburgerWidth+baseWidth+1, 230).contains(relMouseX0, relMouseY0)) return; + + if (scrollAmount < 0) scrollY += 20; + if (scrollAmount > 0) scrollY -= 20; + if (scrollY < 0) scrollY = 0; + + + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererFairySouls.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererFairySouls.java new file mode 100644 index 00000000..d9fae9d6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererFairySouls.java @@ -0,0 +1,49 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; + +import java.awt.*; + +public class DataRendererFairySouls implements DataRenderer { + @Override + public Dimension renderData(PlayerProfile playerProfile) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString("§eFairy Souls §f"+playerProfile.getFairySouls(), 0,0,-1); + return new Dimension(100, fr.FONT_HEIGHT); + } + + @Override + public Dimension renderDummy() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString("§eFairy Souls §f300", 0,0,-1); + return new Dimension(100, fr.FONT_HEIGHT); + } + @Override + public Dimension getDimension() { + return new Dimension(100, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT); + } + + @Override + public void onHover(PlayerProfile playerProfile, int mouseX, int mouseY) { + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererLilyWeight.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererLilyWeight.java new file mode 100644 index 00000000..bdbd782d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererLilyWeight.java @@ -0,0 +1,70 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraftforge.fml.client.config.GuiUtils; + +import java.awt.*; +import java.util.Arrays; + +public class DataRendererLilyWeight implements DataRenderer { + @Override + public Dimension renderData(PlayerProfile playerProfile) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + if (playerProfile.getLilyWeight() == null) + fr.drawString("§eLily Weight §cAPI DISABLED", 0,0,-1); + else + fr.drawString("§eLily Weight §b"+String.format("%.3f", playerProfile.getLilyWeight().getTotal()), 0,0,-1); + return new Dimension(100, fr.FONT_HEIGHT); + } + + @Override + public Dimension renderDummy() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString("§eLily Weight §b300", 0,0,-1); + return new Dimension(100, fr.FONT_HEIGHT); + } + @Override + public Dimension getDimension() { + return new Dimension(100, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT); + } + + @Override + public void onHover(PlayerProfile playerProfile, int mouseX, int mouseY) { + PlayerProfile.LilyWeight lilyWeight= playerProfile.getLilyWeight(); + if (lilyWeight == null) return; + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + GuiUtils.drawHoveringText(Arrays.asList( + "§bDungeon Weights§7: §e"+ String.format("%.3f",lilyWeight.getCatacombs_base()+lilyWeight.getCatacombs_master()+lilyWeight.getCatacombs_exp()), + " §bCatacomb Completion§7: §e"+String.format("%.3f",lilyWeight.getCatacombs_base()), + " §bMaster Completion§7: §e"+String.format("%.3f", lilyWeight.getCatacombs_master()), + " §bExperience§7: §e"+String.format("%.3f", lilyWeight.getCatacombs_exp()), + "§bSkill Weights§7: §e"+ String.format("%.3f", lilyWeight.getSkill_base() + lilyWeight.getSkill_overflow()), + " §bSkill Weight§7: §e"+String.format("%.3f", lilyWeight.getSkill_base()), + " §bOverflow Weight§7: §e"+String.format("%.3f", lilyWeight.getSkill_overflow()), + "§bSlayer Weight§7: §e"+String.format("%.3f", lilyWeight.getSlayer()), + "§bTotal§7: §e"+String.format("%.3f", lilyWeight.getTotal()) + ),mouseX, mouseY, + scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, Minecraft.getMinecraft().fontRendererObj); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererRegistry.java new file mode 100644 index 00000000..bf1e68ac --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererRegistry.java @@ -0,0 +1,63 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.DungeonClass; +import kr.syeyoung.dungeonsguide.features.impl.party.api.DungeonType; +import kr.syeyoung.dungeonsguide.features.impl.party.api.Skill; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class DataRendererRegistry { + private static final Map<String, DataRenderer> dataRendererMap = new HashMap<>(); + + public static DataRenderer getDataRenderer(String id) { + return dataRendererMap.get(id); + } + + public static Set<String> getValidDataRenderer() { + return dataRendererMap.keySet(); + } + + static { + dataRendererMap.put("catalv", new DataRendererDungeonLv(DungeonType.CATACOMBS)); + for (DungeonClass value : DungeonClass.values()) { + dataRendererMap.put("class_"+value.getJsonName()+"_lv", new DataRendererClassLv(value)); + } + dataRendererMap.put("selected_class_lv", new DataRendererSelectedClassLv()); + for (Skill value : Skill.values()) { + dataRendererMap.put("skill_"+value.getJsonName()+"_lv", new DataRendererSkillLv(value)); + } + for (DungeonType value : DungeonType.values()) { + for (Integer validFloor : value.getValidFloors()) { + dataRendererMap.put("dungeon_"+value.getJsonName()+"_"+validFloor+"_stat", new DataRenderDungeonFloorStat(value, validFloor)); + } + dataRendererMap.put("dungeon_"+value.getJsonName()+"_higheststat", new DataRenderDungeonHighestFloorStat(value)); + } + dataRendererMap.put("fairysouls", new DataRendererFairySouls()); + dataRendererMap.put("secrets", new DataRendererSecrets()); + + dataRendererMap.put("dummy", new DataRendererSetUrOwn()); + + dataRendererMap.put("talismans", new DataRendererTalismans()); + dataRendererMap.put("weight", new DataRendererLilyWeight()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSecrets.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSecrets.java new file mode 100644 index 00000000..d06039cb --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSecrets.java @@ -0,0 +1,52 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; + +import java.awt.*; + +public class DataRendererSecrets implements DataRenderer { + @Override + public Dimension renderData(PlayerProfile playerProfile) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + double theint = playerProfile.getTotalSecrets()/ (double)playerProfile.getDungeonStats().values().stream().flatMap(s -> s.getData().getPlays().values().stream()) + .map(fs -> fs.getData().getWatcherKills()).reduce(0, Integer::sum); + fr.drawString("§eSecrets §b"+playerProfile.getTotalSecrets()+" §7("+ + String.format("%.2f", theint)+"/run)", 0,0,-1); + return new Dimension(100, fr.FONT_HEIGHT); + } + + @Override + public Dimension renderDummy() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString("§eSecrets §b99999 §7(X/run)", 0,0,-1); + return new Dimension(100, fr.FONT_HEIGHT); + } + @Override + public Dimension getDimension() { + return new Dimension(100, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT); + } + + @Override + public void onHover(PlayerProfile playerProfile, int mouseX, int mouseY) { + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSelectedClassLv.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSelectedClassLv.java new file mode 100644 index 00000000..013193e0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSelectedClassLv.java @@ -0,0 +1,76 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.ClassSpecificData; +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import kr.syeyoung.dungeonsguide.utils.XPUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraftforge.fml.client.config.GuiUtils; + +import java.awt.*; +import java.util.Arrays; + +public class DataRendererSelectedClassLv implements DataRenderer { + @Override + public Dimension renderData(PlayerProfile playerProfile) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + ClassSpecificData<PlayerProfile.PlayerClassData> dungeonStatDungeonSpecificData = playerProfile.getPlayerClassData().get(playerProfile.getSelectedClass()); + if (dungeonStatDungeonSpecificData == null) { + fr.drawString("Unknown Selected", 0,0, 0xFF55ffff); + } else { + XPUtils.XPCalcResult xpCalcResult = XPUtils.getCataXp(dungeonStatDungeonSpecificData.getData().getExperience()); + fr.drawString(playerProfile.getSelectedClass().getFamilarName(), 0,0, 0xFF55ffff); + fr.drawString(xpCalcResult.getLevel()+"", fr.getStringWidth(playerProfile.getSelectedClass().getFamilarName()+" "),0,0xFFFFFFFF); + fr.drawString("★", fr.getStringWidth(playerProfile.getSelectedClass().getFamilarName()+" "+xpCalcResult.getLevel()+" "),0,0xFFAAAAAA); + + RenderUtils.renderBar(0, fr.FONT_HEIGHT, 100,xpCalcResult.getRemainingXp() == 0 ? 1 : (float) (xpCalcResult.getRemainingXp() / xpCalcResult.getNextLvXp())); + } + + return new Dimension(100, fr.FONT_HEIGHT*2); + } + + @Override + public Dimension renderDummy() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString("SelectedClass", 0,0, 0xFF55ffff); + fr.drawString("99", fr.getStringWidth("SelectedClass "),0,0xFFFFFFFF); + fr.drawString("★", fr.getStringWidth("SelectedClass 99 "),0,0xFFAAAAAA); + RenderUtils.renderBar(0, fr.FONT_HEIGHT, 100,1.0f); + return new Dimension(100, fr.FONT_HEIGHT*2); + } + @Override + public Dimension getDimension() { + return new Dimension(100, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT*2); + } + + @Override + public void onHover(PlayerProfile playerProfile, int mouseX, int mouseY) { + ClassSpecificData<PlayerProfile.PlayerClassData> dungeonStatDungeonSpecificData = playerProfile.getPlayerClassData().get(playerProfile.getSelectedClass()); + if (dungeonStatDungeonSpecificData == null) return; + XPUtils.XPCalcResult xpCalcResult = XPUtils.getCataXp(dungeonStatDungeonSpecificData.getData().getExperience()); + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + GuiUtils.drawHoveringText(Arrays.asList("§bCurrent Lv§7: §e"+xpCalcResult.getLevel(),"§bExp§7: §e"+ TextUtils.format((long)xpCalcResult.getRemainingXp()) + "§7/§e"+TextUtils.format((long)xpCalcResult.getNextLvXp()), "§bTotal Xp§7: §e"+ TextUtils.format((long)dungeonStatDungeonSpecificData.getData().getExperience())),mouseX, mouseY, + scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, Minecraft.getMinecraft().fontRendererObj); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSetUrOwn.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSetUrOwn.java new file mode 100644 index 00000000..aaccb3ae --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSetUrOwn.java @@ -0,0 +1,56 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; + +import java.awt.*; + +public class DataRendererSetUrOwn implements DataRenderer { + @Override + public Dimension renderData(PlayerProfile playerProfile) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString("§aCustomize at /dg", 0,0,-1); + fr.drawString("§a-> Party Kicker", 0,fr.FONT_HEIGHT,-1); + fr.drawString("§a-> View Player Stats", 0,fr.FONT_HEIGHT*2,-1); + fr.drawString("§a-> Edit", 0,fr.FONT_HEIGHT*3,-1); + return new Dimension(100, fr.FONT_HEIGHT*4); + } + + @Override + public void onHover(PlayerProfile playerProfile, int mouseX, int mouseY) { + + } + + @Override + public Dimension renderDummy() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString("§aCustomize at /dg", 0,0,-1); + fr.drawString("§a-> Party Kicker", 0,fr.FONT_HEIGHT,-1); + fr.drawString("§a-> View Player Stats", 0,fr.FONT_HEIGHT*2,-1); + fr.drawString("§a-> Edit", 0,fr.FONT_HEIGHT*3,-1); + return new Dimension(100, fr.FONT_HEIGHT*4); + } + @Override + public Dimension getDimension() { + return new Dimension(100, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT*4); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSkillLv.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSkillLv.java new file mode 100644 index 00000000..9620b883 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererSkillLv.java @@ -0,0 +1,79 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import kr.syeyoung.dungeonsguide.features.impl.party.api.Skill; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import kr.syeyoung.dungeonsguide.utils.XPUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraftforge.fml.client.config.GuiUtils; + +import java.awt.*; +import java.util.Arrays; + +public class DataRendererSkillLv implements DataRenderer { + private final Skill skill; + public DataRendererSkillLv(Skill skill) { + this.skill = skill; + } + @Override + public Dimension renderData(PlayerProfile playerProfile) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + Double xp = playerProfile.getSkillXp().get(skill); + if (xp == null) { + fr.drawString(skill.getFriendlyName(), 0,0, 0xFF55ffff); + fr.drawString("§cSkill API Disabled", 0, fr.FONT_HEIGHT,0xFFFFFFFF); + } else { + XPUtils.XPCalcResult xpCalcResult = XPUtils.getSkillXp(skill, xp); + fr.drawString(skill.getFriendlyName(), 0,0, 0xFF55ffff); + fr.drawString(xpCalcResult.getLevel()+"", fr.getStringWidth(skill.getFriendlyName()+" "),0,0xFFFFFFFF); + + RenderUtils.renderBar(0, fr.FONT_HEIGHT, 100,xpCalcResult.getRemainingXp() == 0 ? 1 : (float) (xpCalcResult.getRemainingXp() / xpCalcResult.getNextLvXp())); + } + + return new Dimension(100, fr.FONT_HEIGHT*2); + } + + @Override + public Dimension renderDummy() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString(skill.getFriendlyName(), 0,0, 0xFF55ffff); + fr.drawString("99", fr.getStringWidth(skill.getFriendlyName()+" "),0,0xFFFFFFFF); + RenderUtils.renderBar(0, fr.FONT_HEIGHT, 100,1.0f); + return new Dimension(100, fr.FONT_HEIGHT*2); + } + @Override + public Dimension getDimension() { + return new Dimension(100, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT*2); + } + + @Override + public void onHover(PlayerProfile playerProfile, int mouseX, int mouseY) { + Double xp = playerProfile.getSkillXp().get(skill); + if (xp == null) return; + XPUtils.XPCalcResult xpCalcResult = XPUtils.getSkillXp(skill, xp); + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + GuiUtils.drawHoveringText(Arrays.asList("§bCurrent Lv§7: §e"+xpCalcResult.getLevel(),"§bExp§7: §e"+ TextUtils.format((long)xpCalcResult.getRemainingXp()) + "§7/§e"+TextUtils.format((long)xpCalcResult.getNextLvXp()), "§bTotal Xp§7: §e"+ TextUtils.format(xp.longValue())),mouseX, mouseY, + scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, Minecraft.getMinecraft().fontRendererObj); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererTalismans.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererTalismans.java new file mode 100644 index 00000000..5bd423ca --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/DataRendererTalismans.java @@ -0,0 +1,122 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.fml.client.config.GuiUtils; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class DataRendererTalismans implements DataRenderer { + @Override + public Dimension renderData(PlayerProfile playerProfile) { + boolean apiDisabled = playerProfile.getTalismans() == null || playerProfile.getInventory() == null; + if (!playerProfile.getAdditionalProperties().containsKey("talismanCnt") && !apiDisabled) { + int[] cnts = new int[Rarity.values().length]; + for (ItemStack talisman : playerProfile.getTalismans()) { + if (talisman == null) continue; + Rarity r = getRarity(talisman); + if (r != null) cnts[r.ordinal()]++; + } + for (ItemStack itemStack : playerProfile.getInventory()) { + if (itemStack == null) continue; + Rarity r = getRarity(itemStack); + if (r != null) cnts[r.ordinal()]++; + } + playerProfile.getAdditionalProperties().put("talismanCnt", cnts); + } + int[] rawData = (int[]) playerProfile.getAdditionalProperties().get("talismanCnt"); + + String str = ""; + if (rawData != null) + for (Rarity r : Rarity.values()) { + str = r.color+rawData[r.idx] +" "+ str; + } + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + if (apiDisabled) + fr.drawString("§eTalis §cAPI DISABLED", 0,0,-1); + else + fr.drawString("§eTalis §f"+str, 0,0,-1); + return new Dimension(100, fr.FONT_HEIGHT); + } + + private Rarity getRarity(ItemStack itemStack) { + NBTTagCompound display = itemStack.getTagCompound().getCompoundTag("display"); + if (display == null) return null; + NBTTagList lore = display.getTagList("Lore", 8); + if (lore == null) return null; + for (int i = 0; i < lore.tagCount(); i++) { + String line = lore.getStringTagAt(i); + for (Rarity value : Rarity.values()) { + if (line.startsWith(value.getColor()) && line.contains("CCESSORY")) return value; + } + } + return null; + } + + @Override + public Dimension renderDummy() { + String str = ""; + for (Rarity r : Rarity.values()) { + str = r.color+(r.idx+5)*2+" "+str; + } + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString("§eTalis §f"+str, 0,0,-1); + return new Dimension(100, fr.FONT_HEIGHT); + } + @Override + public Dimension getDimension() { + return new Dimension(100, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT); + } + + @Override + public void onHover(PlayerProfile playerProfile, int mouseX, int mouseY) { + int[] rawData = (int[]) playerProfile.getAdditionalProperties().get("talismanCnt"); + if (rawData == null) return; + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + List<String> list = new ArrayList<>(); + + for (Rarity r : Rarity.values()) { + list.add(r.getColor()+r.name()+"§7: §e"+rawData[r.idx]); + } + GuiUtils.drawHoveringText(list,mouseX, mouseY, + scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, Minecraft.getMinecraft().fontRendererObj); + } + + + @AllArgsConstructor @Getter + public static enum Rarity { + COMMON("§f", 0), UNCOMMON("§a",1), RARE("§9",2), EPIC("§5",3), LEGENDARY("§6",4), MYTHIC("§d",5); + + private String color; + private int idx; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java new file mode 100644 index 00000000..17df170c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java @@ -0,0 +1,623 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.party.playerpreview; + +import com.google.common.base.Supplier; +import com.mojang.authlib.GameProfile; +import io.github.moulberry.hychat.HyChat; +import io.github.moulberry.hychat.chat.ChatManager; +import io.github.moulberry.hychat.gui.GuiChatBox; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator; +import kr.syeyoung.dungeonsguide.config.guiconfig.MFeatureEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.MParameterEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.RootConfigPanel; +import kr.syeyoung.dungeonsguide.features.impl.party.api.ApiFetchur; +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import kr.syeyoung.dungeonsguide.features.impl.party.api.SkinFetchur; +import kr.syeyoung.dungeonsguide.features.listener.ChatListener; +import kr.syeyoung.dungeonsguide.features.listener.GuiClickListener; +import kr.syeyoung.dungeonsguide.features.listener.GuiPostRenderListener; +import kr.syeyoung.dungeonsguide.chat.ChatProcessor; +import kr.syeyoung.dungeonsguide.chat.PartyManager; +import kr.syeyoung.dungeonsguide.cosmetics.ActiveCosmetic; +import kr.syeyoung.dungeonsguide.cosmetics.CosmeticData; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.features.impl.party.api.*; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import lombok.Getter; +import lombok.Setter; +import lombok.SneakyThrows; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.client.gui.*; +import net.minecraft.client.gui.inventory.GuiInventory; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.event.HoverEvent; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.scoreboard.Team; +import net.minecraft.util.*; +import net.minecraft.world.World; +import net.minecraftforge.client.event.ClientChatReceivedEvent; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.fml.client.config.GuiUtils; +import net.minecraftforge.fml.common.Loader; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.*; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public class FeatureViewPlayerOnJoin extends SimpleFeature implements GuiPostRenderListener, ChatListener, GuiClickListener { + + public FeatureViewPlayerOnJoin() { + super("Party", "View player stats when join", "view player rendering when joining/someone joins the party", "partykicker.viewstats", true); + this.parameters.put("datarenderers", new FeatureParameter<List<String>>("datarenderers", "DataRenderers","Datarenderssdasd", new ArrayList<>(Arrays.asList( + "catalv", "selected_class_lv", "dungeon_catacombs_higheststat", "dungeon_master_catacombs_higheststat", "skill_combat_lv", "skill_foraging_lv", "skill_mining_lv", "fairysouls", "dummy" + )), "stringlist")); + } + + private Rectangle popupRect; + private String lastuid; // actually current uid + private Future<Optional<PlayerProfile>> profileFuture; + private Future<Optional<GameProfile>> gfFuture; + private Future<SkinFetchur.SkinSet> skinFuture; + private FakePlayer fakePlayer; + private boolean drawInv = false; + @SneakyThrows + @Override + public void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered) { + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChat)) { + cancelRender(); + return; + } + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + IChatComponent ichatcomponent = getHoveredComponent(scaledResolution); + String uid = null; + if (ichatcomponent != null && ichatcomponent.getChatStyle().getChatHoverEvent() instanceof HoverEventRenderPlayer) { + uid = ((HoverEventRenderPlayer) ichatcomponent.getChatStyle().getChatHoverEvent()).getUuid(); + } + reqRender(uid); + } + + public void cancelRender() { + popupRect = null; + profileFuture = null; + lastuid = null; + gfFuture = null; + skinFuture= null; + fakePlayer= null; + drawInv = false; + } + + public void reqRender(String uid) { + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + + if (!((popupRect != null && (popupRect.contains(mouseX, mouseY) || drawInv)) || uid != null && uid.equals(lastuid))) { + cancelRender(); + } + + if (uid != null && !uid.equals(lastuid) && (popupRect==null || (!popupRect.contains(mouseX, mouseY) && !drawInv)) ) { + cancelRender(); + lastuid = uid; + } + if (lastuid == null) return; + + + if (popupRect == null) { + popupRect = new Rectangle(mouseX, mouseY, 220, 220); + if (popupRect.y + popupRect.height > scaledResolution.getScaledHeight()) { + popupRect.y -= popupRect.y + popupRect.height - scaledResolution.getScaledHeight(); + } + } + + if (profileFuture == null) { + profileFuture = ApiFetchur.fetchMostRecentProfileAsync(lastuid, FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey()); + } + + if (gfFuture == null) { + gfFuture = ApiFetchur.getSkinGameProfileByUUIDAsync(lastuid); + } + boolean plsSetAPIKEY = false; + if (skinFuture == null && gfFuture.isDone()) { + try { + skinFuture = SkinFetchur.getSkinSet(gfFuture.get().orElse(null)); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + + try { + if (fakePlayer == null && skinFuture != null && profileFuture != null && skinFuture.isDone() && profileFuture.isDone() && profileFuture.get().isPresent()) { + fakePlayer = new FakePlayer(gfFuture.get().orElse(null), skinFuture.get(), profileFuture.get().orElse(null)); + } + } catch (InterruptedException | ExecutionException e) { + plsSetAPIKEY = true; + } + + + try { + render(popupRect, scaledResolution, mouseX, mouseY, plsSetAPIKEY ? null : (profileFuture.isDone() ? profileFuture.get() : null), plsSetAPIKEY); + } catch (InterruptedException | ExecutionException e) { + } + + } + + public static void clip(ScaledResolution resolution, int x, int y, int width, int height) { + if (width < 0 || height < 0) return; + + int scale = resolution.getScaleFactor(); + GL11.glScissor((x ) * scale, Minecraft.getMinecraft().displayHeight - (y + height) * scale, (width) * scale, height * scale); + } + private void render(Rectangle popupRect, ScaledResolution scaledResolution, int mouseX, int mouseY, Optional<PlayerProfile> playerProfile, boolean apiKeyPlsSet) { + + GlStateManager.pushMatrix(); + GlStateManager.translate(popupRect.x, popupRect.y, 0); + Gui.drawRect(0,0, popupRect.width, popupRect.height, 0xFF23272a); + Gui.drawRect(2,2, popupRect.width-2, popupRect.height-2, 0XFF2c2f33); + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + if (apiKeyPlsSet) { + Minecraft.getMinecraft().fontRendererObj.drawString("Please set API KEY on /dg -> Party Kicker", 5,5, 0xFFFFFFFF); + GlStateManager.popMatrix(); + return; + } + if (playerProfile == null) { + Minecraft.getMinecraft().fontRendererObj.drawString("Fetching data...", 5,5, 0xFFFFFFFF); + GlStateManager.popMatrix(); + return; + } + if (!playerProfile.isPresent()) { + Minecraft.getMinecraft().fontRendererObj.drawString("User could not be found", 5,5, 0xFFFFFFFF); + GlStateManager.popMatrix(); + return; + } + int relX = mouseX - popupRect.x; + int relY = mouseY - popupRect.y; + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + + GL11.glEnable(GL11.GL_SCISSOR_TEST); + clip(scaledResolution, popupRect.x, popupRect.y, popupRect.width, popupRect.height); + + Gui.drawRect(0,168, 90, 195, 0xFF23272a); + Gui.drawRect(2,170, 88, 193, new Rectangle(2,170,86,23).contains(relX, relY) ? 0xFFff7777 : 0xFFFF3333); + + Gui.drawRect(0,193, 90, 220, 0xFF23272a); + Gui.drawRect(2,195, 88, 218, new Rectangle(2,195,86,23).contains(relX, relY) ? 0xFF859DF0 : 0xFF7289da); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Kick", (90 - fr.getStringWidth("Kick")) / 2,(364 - fr.FONT_HEIGHT) / 2, 0xFFFFFFFF); + fr.drawString("Invite", (90 - fr.getStringWidth("Invite")) / 2,(414 - fr.FONT_HEIGHT) / 2, 0xFFFFFFFF); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(95, 5, 0); + int culmutativeY = 5; + DataRenderer dataRendererToHover = null; + for (String datarenderers : this.<List<String>>getParameter("datarenderers").getValue()) { + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + DataRenderer dataRenderer = DataRendererRegistry.getDataRenderer(datarenderers); + Dimension dim; + if (dataRenderer == null) { + fr.drawString("Couldn't find Datarenderer", 0,0, 0xFFFF0000); + fr.drawString(datarenderers, 0,fr.FONT_HEIGHT, 0xFFFF0000); + dim = new Dimension(0, fr.FONT_HEIGHT * 2); + } else { + GlStateManager.pushMatrix(); + dim = dataRenderer.renderData(playerProfile.get()); + GlStateManager.popMatrix(); + } + if (relX >= 95 && relX <= popupRect.width && relY >= culmutativeY && relY < culmutativeY+dim.height && dataRenderer != null) { + dataRendererToHover = dataRenderer; + } + culmutativeY += dim.height; + GlStateManager.translate(0,dim.height,0); + } + + GlStateManager.popMatrix(); + + Gui.drawRect(0,0, 90, 170, 0xFF23272a); + Gui.drawRect(2,2, 88, 168, 0xFF444444); + Gui.drawRect(80,159, 90, 170, 0xFF23272a); + Gui.drawRect(82,161, 88, 168, 0xFF444444); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("§eI", 83,161,-1); + GlStateManager.color(1, 1, 1, 1.0F); + if (fakePlayer != null) { + clip(scaledResolution, popupRect.x+2, popupRect.y+2, 86, 166); + GuiInventory.drawEntityOnScreen(45, 150, 60, -(mouseX - popupRect.x - 75), 0, fakePlayer); + + String toDraw = fakePlayer.getName(); + List<ActiveCosmetic> activeCosmetics = DungeonsGuide.getDungeonsGuide().getCosmeticsManager().getActiveCosmeticByPlayer().get(UUID.fromString(TextUtils.insertDashUUID(playerProfile.get().getMemberUID()))); + CosmeticData prefix = null, color = null; + if (activeCosmetics != null) { + for (ActiveCosmetic activeCosmetic : activeCosmetics) { + CosmeticData cosmeticData = DungeonsGuide.getDungeonsGuide().getCosmeticsManager().getCosmeticDataMap().get(activeCosmetic.getCosmeticData()); + if (cosmeticData != null) { + if (cosmeticData.getCosmeticType().equals("prefix")) prefix = cosmeticData; + if (cosmeticData.getCosmeticType().equals("color")) color = cosmeticData; + } + } + } + toDraw = (color == null ? "§e" : color.getData().replace("&", "§"))+toDraw; + if (prefix != null) toDraw = prefix.getData().replace("&", "§") + " "+toDraw; + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(toDraw, (90 - fr.getStringWidth(toDraw)) / 2, 15, -1); + + ItemStack toHover = null; + if (relX > 20 && relX < 70) { + if (33<=relY && relY <= 66) { + toHover = fakePlayer.getInventory()[3]; + } else if (66 <= relY && relY <= 108) { + toHover = fakePlayer.getInventory()[2]; + } else if (108 <= relY && relY <= 130) { + toHover = fakePlayer.getInventory()[1]; + } else if (130 <= relY && relY <= 154) { + toHover = fakePlayer.getInventory()[0]; + } + } else if (relX > 0 && relX <= 20) { + if (80 <= relY && relY <= 120) { + toHover = fakePlayer.inventory.mainInventory[fakePlayer.inventory.currentItem]; + } + } + + if (toHover != null) { + List<String> list = toHover.getTooltip(Minecraft.getMinecraft().thePlayer, Minecraft.getMinecraft().gameSettings.advancedItemTooltips); + for (int i = 0; i < list.size(); ++i) { + if (i == 0) { + list.set(i, toHover.getRarity().rarityColor + list.get(i)); + } else { + list.set(i, EnumChatFormatting.GRAY + list.get(i)); + } + } + FontRenderer font = toHover.getItem().getFontRenderer(toHover); + GlStateManager.popMatrix(); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + FontRenderer theRenderer = (font == null ? fr : font); + GuiUtils.drawHoveringText(list,mouseX, mouseY, scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, theRenderer); + GL11.glEnable(GL11.GL_SCISSOR_TEST); + GlStateManager.pushMatrix(); + GlStateManager.translate(popupRect.x, popupRect.y, 0); + } + clip(scaledResolution, popupRect.x, popupRect.y, popupRect.width, popupRect.height); + } else { + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Loading", 5,35, 0xFFEFFF00); + } + + GlStateManager.popMatrix(); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + if (dataRendererToHover != null && !drawInv) { + dataRendererToHover.onHover(playerProfile.get(), mouseX, mouseY); + } + GL11.glEnable(GL11.GL_SCISSOR_TEST); + GlStateManager.pushMatrix(); + GlStateManager.translate(popupRect.x, popupRect.y, 0); + + if (drawInv) { + int startX = 81; + int startY = 86; + clip(scaledResolution, popupRect.x+startX-1, popupRect.y+startY-1, 164, 74); + GlStateManager.translate(startX,startY,1); + Gui.drawRect(-1,-1,163,73, 0xFF000000); + GlStateManager.disableLighting(); + ItemStack toHover = null; + int rx = relX - startX; + int ry = relY - startY; + + if (playerProfile.get().getInventory() != null) { + GlStateManager.disableRescaleNormal(); + RenderHelper.enableGUIStandardItemLighting(); + GlStateManager.disableLighting(); + for (int i = 0; i < playerProfile.get().getInventory().length; i++) { + int x = (i%9) * 18; + int y = (i/9) * 18; + if (x <= rx && rx<x+18 && y<=ry&&ry<y+18) { + toHover = playerProfile.get().getInventory()[(i+9) % 36]; + } + Gui.drawRect(x,y,x+18,y+18, 0xFF000000); + Gui.drawRect(x+1,y+1,x+17,y+17, 0xFF666666); + GlStateManager.color(1, 1, 1, 1.0F); + + Minecraft.getMinecraft().getRenderItem().renderItemAndEffectIntoGUI(playerProfile.get().getInventory()[(i+9) % 36], (i%9) * 18+1,(i/9) * 18+1); + } + + if (toHover != null) { + List<String> list = toHover.getTooltip(Minecraft.getMinecraft().thePlayer, Minecraft.getMinecraft().gameSettings.advancedItemTooltips); + for (int i = 0; i < list.size(); ++i) { + if (i == 0) { + list.set(i, toHover.getRarity().rarityColor + list.get(i)); + } else { + list.set(i, EnumChatFormatting.GRAY + list.get(i)); + } + } + FontRenderer font = toHover.getItem().getFontRenderer(toHover); + GlStateManager.popMatrix(); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + FontRenderer theRenderer = (font == null ? fr : font); + GuiUtils.drawHoveringText(list,mouseX, mouseY, scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, theRenderer); + GL11.glEnable(GL11.GL_SCISSOR_TEST); + GlStateManager.pushMatrix(); + } + } else { + Gui.drawRect(0,0,162,72, 0xFF666666); + fr.drawSplitString("Player has disabled Inventory API", 5,5, 142, -1); + } + + } + GL11.glDisable(GL11.GL_SCISSOR_TEST); + + + GlStateManager.popMatrix(); // 33 66 108 130 154 // 5 75 + } + @Override + public void onMouseInput(GuiScreenEvent.MouseInputEvent.Pre mouseInputEvent) { + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + if (Mouse.getEventButton() != -1 && Mouse.isButtonDown(Mouse.getEventButton()) && drawInv) drawInv = false; + if (popupRect == null || !popupRect.contains(mouseX, mouseY)) return; + + mouseInputEvent.setCanceled(true); + + int relX = mouseX - popupRect.x; + int relY = mouseY - popupRect.y; + + + try { + PlayerProfile playerProfile = profileFuture.isDone() ? profileFuture.get().orElse(null) : null; + if (playerProfile == null) return; + if (Mouse.getEventButton() != -1 && Mouse.isButtonDown(Mouse.getEventButton())) { + if (new Rectangle(2, 195, 86, 23).contains(relX, relY)) { + // invite + ChatProcessor.INSTANCE.addToChatQueue("/p invite " + ApiFetchur.fetchNicknameAsync(playerProfile.getMemberUID()).get().orElse("-"), () -> {}, true); + } else if (new Rectangle(2, 170, 86, 23).contains(relX, relY)) { + // kick + ChatProcessor.INSTANCE.addToChatQueue("/p kick " + ApiFetchur.fetchNicknameAsync(playerProfile.getMemberUID()).get().orElse("-"), () -> {}, true); + } else if (new Rectangle(80,159,10,11).contains(relX, relY)) { + drawInv = true; + } + } + + } catch (InterruptedException | ExecutionException e) { + } + + + } + + public IChatComponent getHoveredComponent(ScaledResolution scaledResolution) { + IChatComponent ichatcomponent = null; + if (Loader.isModLoaded("hychat")) { + try { + ChatManager chatManager = HyChat.getInstance().getChatManager(); + GuiChatBox guiChatBox = chatManager.getFocusedChat(); + + int x = guiChatBox.getX(scaledResolution); + int y = guiChatBox.getY(scaledResolution); + ichatcomponent = guiChatBox.chatArray.getHoveredComponent(guiChatBox.getSelectedTab().getChatLines(), Mouse.getX(), Mouse.getY(), x, y); + } catch (Throwable t) {} + } + if (ichatcomponent == null) { + ichatcomponent = Minecraft.getMinecraft().ingameGUI.getChatGUI().getChatComponent(Mouse.getX(), Mouse.getY()); + } + return ichatcomponent; + } + + @Override + public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + if (!isEnabled()) return; + String str = clientChatReceivedEvent.message.getFormattedText(); + if (str.contains("§r§ejoined the dungeon group! (§r§b")) { + String username = TextUtils.stripColor(str).split(" ")[3]; + if (username.equalsIgnoreCase(Minecraft.getMinecraft().getSession().getUsername())) { + PartyManager.INSTANCE.requestPartyList((context) -> { + if (context == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cBugged Dungeon Party ")); + } else { + + for (String member : context.getPartyRawMembers()) { + ApiFetchur.fetchUUIDAsync(member) + .thenAccept((a) -> { + if (a == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+member+"§f's Profile §cCouldn't fetch uuid")); + } else { + ApiFetchur.fetchMostRecentProfileAsync(a.get(), FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey()); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+member+"§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null)))))); + } + }); + } + } + }); + } else { + ApiFetchur.fetchUUIDAsync(username) + .thenAccept(a -> { + if (a == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+username+"§f's Profile §cCouldn't fetch uuid")); + return; + } + ApiFetchur.fetchMostRecentProfileAsync(a.get(), FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey()); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+username+"§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null)))))); + }); + } + } + } + + + public static class HoverEventRenderPlayer extends HoverEvent { + @Getter + private final String uuid; + public HoverEventRenderPlayer(String uuid) { + super(Action.SHOW_TEXT, new ChatComponentText("")); + this.uuid = uuid; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + HoverEventRenderPlayer that = (HoverEventRenderPlayer) o; + return Objects.equals(uuid, that.uuid); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), uuid); + } + + private IChatComponent cached; + + @Override + public IChatComponent getValue() { + if (cached == null) + return cached = new ChatComponentText("").setChatStyle(new ChatStyle().setChatHoverEvent(new HoverEvent(Action.SHOW_TEXT, new ChatComponentText(uuid)))); + return cached; + } + } + + public static class FakePlayer extends EntityOtherPlayerMP { + @Setter + @Getter + private PlayerProfile skyblockProfile; + private final SkinFetchur.SkinSet skinSet; + private final PlayerProfile.Armor armor; + private FakePlayer(World w) { + super(w, null); + throw new UnsupportedOperationException("what"); + } + public FakePlayer(GameProfile playerProfile, SkinFetchur.SkinSet skinSet, PlayerProfile skyblockProfile) { + super(Minecraft.getMinecraft().theWorld, playerProfile); + this.skyblockProfile = skyblockProfile; + this.skinSet = skinSet; + armor= skyblockProfile.getCurrentArmor(); + this.inventory.armorInventory = skyblockProfile.getCurrentArmor().getArmorSlots(); + + int highestDungeonScore = Integer.MIN_VALUE; + if (skyblockProfile.getInventory() != null) { + ItemStack highestItem = null; + for (ItemStack itemStack : skyblockProfile.getInventory()) { + if (itemStack == null) continue; + NBTTagCompound display = itemStack.getTagCompound().getCompoundTag("display"); + if (display == null) continue; + NBTTagList nbtTagList = display.getTagList("Lore", 8); + if (nbtTagList == null) continue; + for (int i = 0; i < nbtTagList.tagCount(); i++) { + String str = nbtTagList.getStringTagAt(i); + if (TextUtils.stripColor(str).startsWith("Gear")) { + int dungeonScore = Integer.parseInt(TextUtils.keepIntegerCharactersOnly(TextUtils.stripColor(str).split(" ")[2])); + if (dungeonScore > highestDungeonScore) { + highestItem = itemStack; + highestDungeonScore = dungeonScore; + } + } + } + } + + this.inventory.mainInventory[0] = highestItem; + this.inventory.currentItem = 0; + } + } + + public String getSkinType() { + return this.skinSet == null ? DefaultPlayerSkin.getSkinType(getGameProfile().getId()) : this.skinSet.getSkinType(); + } + + public ResourceLocation getLocationSkin() { + return com.google.common.base.Objects.firstNonNull(skinSet.getSkinLoc(), DefaultPlayerSkin.getDefaultSkin(getGameProfile().getId())); + } + + public ResourceLocation getLocationCape() { + return skinSet.getCapeLoc(); + } + + @Override + public ItemStack[] getInventory() { + return this.inventory.armorInventory; + } + + @Override + public boolean isInvisibleToPlayer(EntityPlayer player) { + return true; + } + + @Override + public Team getTeam() { + return new ScorePlayerTeam(null, null) { + @Override + public EnumVisible getNameTagVisibility() { + return EnumVisible.NEVER; + } + }; + } + } + + + + @Override + public String getEditRoute(RootConfigPanel rootConfigPanel) { + ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() { + @Override + public MPanel get() { + + MFeatureEdit featureEdit = new MFeatureEdit(FeatureViewPlayerOnJoin.this, rootConfigPanel); + featureEdit.addParameterEdit("datarenderers", new DataRendererEditor(FeatureViewPlayerOnJoin.this)); + for (FeatureParameter parameter: getParameters()) { + if (parameter.getKey().equals("datarenderers")) continue; + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeatureViewPlayerOnJoin.this, parameter, rootConfigPanel)); + } + return featureEdit; + } + }); + return "base." + getKey() ; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureActions.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureActions.java new file mode 100644 index 00000000..ab9fdcd9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureActions.java @@ -0,0 +1,144 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.features.text.StyledText; +import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; +import kr.syeyoung.dungeonsguide.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FeatureActions extends TextHUDFeature { + public FeatureActions() { + super("Dungeon Secrets", "Action Viewer", "View List of actions that needs to be taken", "secret.actionview", false, 200, getFontRenderer().FONT_HEIGHT * 10); + + getStyles().add(new TextStyle("pathfinding", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("mechanic", new AColor(0x55, 0xFF,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("state", new AColor(0x55, 0xFF,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("current", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("number", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("dot", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("action", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false)); + getStyles().add(new TextStyle("afterline", new AColor(0xAA, 0xAA,0xAA,255), new AColor(0, 0,0,0), false)); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + @Override + public boolean doesScaleWithHeight() { + return false; + } + + @Override + public boolean isHUDViewable() { + if (!skyblockStatus.isOnDungeon()) return false; + if (skyblockStatus.getContext() == null || !skyblockStatus.getContext().getMapProcessor().isInitialized()) return false; + DungeonContext context = skyblockStatus.getContext(); + + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom == null) return false; + return dungeonRoom.getRoomProcessor() instanceof GeneralRoomProcessor; + } + + private static final List<StyledText> dummyText= new ArrayList<StyledText>(); + static { + dummyText.add(new StyledText("Pathfinding ","pathfinding")); + dummyText.add(new StyledText("Secret ","mechanic")); + dummyText.add(new StyledText("-> ","separator")); + dummyText.add(new StyledText("Found\n","state")); + dummyText.add(new StyledText("> ","current")); + dummyText.add(new StyledText("1","number")); + dummyText.add(new StyledText(". ","dot")); + dummyText.add(new StyledText("Move ","action")); + dummyText.add(new StyledText("OffsetPoint{x=1,y=42,z=1} \n","afterline")); + dummyText.add(new StyledText(" ","current")); + dummyText.add(new StyledText("2","number")); + dummyText.add(new StyledText(". ","dot")); + dummyText.add(new StyledText("Click ","action")); + dummyText.add(new StyledText("OffsetPoint{x=1,y=42,z=1} \n","afterline")); + dummyText.add(new StyledText(" ","current")); + dummyText.add(new StyledText("3","number")); + dummyText.add(new StyledText(". ","dot")); + dummyText.add(new StyledText("Profit ","action")); + } + + @Override + public List<String> getUsedTextStyle() { + return Arrays.asList("pathfinding","mechanic","separator","state","current", "number", "dot", "action", "afterline"); + } + + @Override + public List<StyledText> getDummyText() { + return dummyText; + } + + + @Override + public List<StyledText> getText() { + List<StyledText> actualBit = new ArrayList<StyledText>(); + + DungeonContext context = skyblockStatus.getContext(); + + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + + for (ActionRoute path : ((GeneralRoomProcessor) dungeonRoom.getRoomProcessor()).getPath().values()) { + actualBit.add(new StyledText("Pathfinding ","pathfinding")); + actualBit.add(new StyledText(path.getMechanic()+" ","mechanic")); + actualBit.add(new StyledText("-> ","separator")); + actualBit.add(new StyledText(path.getState()+"\n","state")); + + for (int i = Math.max(0,path.getCurrent()-2); i < path.getActions().size(); i++) { + actualBit.add(new StyledText((i == path.getCurrent() ? ">" : " ") +" ","current")); + actualBit.add(new StyledText(i+"","number")); + actualBit.add(new StyledText(". ","dot")); + Action action = path.getActions().get(i); + String[] str = action.toString().split("\n"); + actualBit.add(new StyledText(str[0] + " ","action")); + actualBit.add(new StyledText("(","afterline")); + for (int i1 = 1; i1 < str.length; i1++) { + String base = str[i1].trim(); + if (base.startsWith("-")) + base = base.substring(1); + base = base.trim(); + actualBit.add(new StyledText(base+" ","afterline")); + } + actualBit.add(new StyledText(")\n","afterline")); + } + } + return actualBit; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureBloodRush.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureBloodRush.java new file mode 100644 index 00000000..857dc9f0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureBloodRush.java @@ -0,0 +1,45 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret; + +import kr.syeyoung.dungeonsguide.features.listener.KeybindPressedListener; +import kr.syeyoung.dungeonsguide.events.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ChatComponentText; +import org.lwjgl.input.Keyboard; + +public class FeatureBloodRush extends SimpleFeature implements KeybindPressedListener { + public FeatureBloodRush() { + super("Dungeon Secrets.Blood Rush", "Blood Rush Mode", "Auto pathfind to witherdoors. \nCan be toggled with key set in settings", "secret.bloodrush", false); + this.parameters.put("key", new FeatureParameter<Integer>("key", "Key", "Press to toggle Blood Rush", Keyboard.KEY_NONE, "keybind")); + } + + @Override + public void onKeybindPress(KeyBindPressedEvent keyBindPressedEvent) { + if (keyBindPressedEvent.getKey() == this.<Integer>getParameter("key").getValue()) { + setEnabled(!isEnabled()); + try { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fToggled Blood Rush to §e"+(FeatureRegistry.SECRET_BLOOD_RUSH.isEnabled() ? "on":"off"))); + } catch (Exception ignored) {} + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureCreateRefreshLine.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureCreateRefreshLine.java new file mode 100644 index 00000000..d8e3ac2f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureCreateRefreshLine.java @@ -0,0 +1,69 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret; + +import com.google.common.base.Supplier; +import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator; +import kr.syeyoung.dungeonsguide.config.guiconfig.MFeatureEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.MParameterEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.RootConfigPanel; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import org.lwjgl.input.Keyboard; + +import java.util.LinkedHashMap; + +public class FeatureCreateRefreshLine extends SimpleFeature { + public FeatureCreateRefreshLine() { + super("Dungeon Secrets.Keybinds", "Refresh pathfind line or Trigger pathfind", "A keybind for creating or refresh pathfind lines for pathfind contexts that doesn't have line, or contexts that has refresh rate set to -1.\nPress settings to edit the key", "secret.refreshPathfind", true); + this.parameters = new LinkedHashMap<>(); + this.parameters.put("key", new FeatureParameter<Integer>("key", "Key","Press to refresh or create pathfind line", Keyboard.KEY_NONE, "keybind")); + this.parameters.put("pathfind", new FeatureParameter<Boolean>("pathfind", "Enable Pathfinding", "Force Enable pathfind for future actions when used", false, "boolean")); + this.parameters.put("refreshrate", new FeatureParameter<Integer>("refreshrate", "Line Refreshrate", "Ticks to wait per line refresh, to be overriden. If the line already has pathfind enabled, this value does nothing. Specify it to -1 to don't refresh line at all", 10, "integer")); + } + public int getKeybind() {return this.<Integer>getParameter("key").getValue();} + public boolean isPathfind() { + return this.<Boolean>getParameter("pathfind").getValue(); + } + public int getRefreshRate() { + return this.<Integer>getParameter("refreshrate").getValue(); + } + + + public String getEditRoute(RootConfigPanel rootConfigPanel) { + ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() { + @Override + public MPanel get() { + MFeatureEdit featureEdit = new MFeatureEdit(FeatureCreateRefreshLine.this, rootConfigPanel); + for (FeatureParameter parameter: getParameters()) { + if (parameter.getKey().equals("refreshrate")) + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeatureCreateRefreshLine.this, parameter, rootConfigPanel, a -> !isPathfind())); + else + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeatureCreateRefreshLine.this, parameter, rootConfigPanel, a -> false)); + } + return featureEdit; + } + }); + return "base." + getKey() ; + } + + + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureFreezePathfind.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureFreezePathfind.java new file mode 100644 index 00000000..225a7850 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureFreezePathfind.java @@ -0,0 +1,45 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret; + +import kr.syeyoung.dungeonsguide.features.listener.KeybindPressedListener; +import kr.syeyoung.dungeonsguide.events.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ChatComponentText; +import org.lwjgl.input.Keyboard; + +public class FeatureFreezePathfind extends SimpleFeature implements KeybindPressedListener { + public FeatureFreezePathfind() { + super("Dungeon Secrets.Keybinds", "Global Freeze Pathfind", "Freeze Pathfind, meaning the pathfind lines won't change when you move.\nPress settings to edit the key", "secret.freezepathfind", false); + this.parameters.put("key", new FeatureParameter<Integer>("key", "Key", "Press to toggle freeze pathfind", Keyboard.KEY_NONE, "keybind")); + } + + @Override + public void onKeybindPress(KeyBindPressedEvent keyBindPressedEvent) { + if (keyBindPressedEvent.getKey() == this.<Integer>getParameter("key").getValue()) { + setEnabled(!isEnabled()); + try { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fToggled Pathfind Freeze to §e"+(FeatureRegistry.SECRET_FREEZE_LINES.isEnabled() ? "on":"off"))); + } catch (Exception ignored) {} + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeaturePathfindStrategy.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeaturePathfindStrategy.java new file mode 100644 index 00000000..6e1dccbc --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeaturePathfindStrategy.java @@ -0,0 +1,106 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret; + +import com.google.common.base.Supplier; +import com.google.gson.JsonObject; +import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator; +import kr.syeyoung.dungeonsguide.gui.elements.MStringSelectionButton; +import kr.syeyoung.dungeonsguide.config.guiconfig.MFeatureEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.MParameterEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.RootConfigPanel; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.awt.*; +import java.util.Arrays; +import java.util.stream.Collectors; + +public class FeaturePathfindStrategy extends SimpleFeature { + public FeaturePathfindStrategy() { + super("Dungeon Secrets", "Pathfind Algorithm", "Select pathfind algorithm used by paths", "secret.secretpathfind.algorithm", true); + this.parameters.put("strategy", new FeatureParameter<String>("strategy", "Pathfind Strategy", "Pathfind Strategy", "THETA_STAR", "string")); + + } + + @Override + public boolean isDisyllable() { + return false; + } + + @Override + public String getEditRoute(RootConfigPanel rootConfigPanel) { + ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() { + @Override + public MPanel get() { + + MFeatureEdit featureEdit = new MFeatureEdit(FeaturePathfindStrategy.this, rootConfigPanel); + PathfindStrategy alignment = getPathfindStrat(); + MStringSelectionButton mStringSelectionButton = new MStringSelectionButton(Arrays.stream(PathfindStrategy.values()).map(Enum::name).collect(Collectors.toList()), alignment.name()) { + @Override + public Dimension getPreferredSize() { + return new Dimension(150, 20); + } + }; + mStringSelectionButton.setOnUpdate(() -> { + FeaturePathfindStrategy.this.<String>getParameter("strategy").setValue(mStringSelectionButton.getSelected()); + FeaturePathfindStrategy.this.<String>getParameter("strategy").setDescription(getPathfindStrat().getDescription()); + featureEdit.removeParameterEdit(null); + }); + featureEdit.addParameterEdit("strategy", new MParameterEdit(FeaturePathfindStrategy.this, FeaturePathfindStrategy.this.<String>getParameter("strategy"), rootConfigPanel, mStringSelectionButton, (a) -> false)); + + for (FeatureParameter parameter: getParameters()) { + if (parameter.getKey().equals("strategy")) continue; + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeaturePathfindStrategy.this, parameter, rootConfigPanel)); + } + return featureEdit; + } + }); + return "base." + getKey() ; + } + + @Getter @RequiredArgsConstructor + public enum PathfindStrategy { + THETA_STAR("The default pathfinding algorithm. It will generate sub-optimal path quickly."), + A_STAR_DIAGONAL("New pathfinding algorithm. It will generate path that looks like the one JPS generates"), + A_STAR_FINE_GRID("New pathfinding algorithm. It will generate path that kind of looks like stair"), + JPS_LEGACY("The improved pathfinding algorithm. Not suggested for usage. It will have problems on diagonal movements, thus giving wrong routes"), + A_STAR_LEGACY("The first pathfinding algorithm. It may have problem on navigating through stairs. This is the one used by Minecraft for mob pathfind."); + + private final String description; + } + + @Override + public void loadConfig(JsonObject jsonObject) { + super.loadConfig(jsonObject); + FeaturePathfindStrategy.PathfindStrategy alignment; + try { + alignment = PathfindStrategy.valueOf(FeaturePathfindStrategy.this.<String>getParameter("strategy").getValue()); + } catch (Exception e) {alignment = PathfindStrategy.THETA_STAR;} + FeaturePathfindStrategy.this.<String>getParameter("strategy").setValue(alignment.name()); + FeaturePathfindStrategy.this.<String>getParameter("strategy").setDescription(alignment.getDescription()); + } + + public PathfindStrategy getPathfindStrat() { + return PathfindStrategy.valueOf(FeaturePathfindStrategy.this.<String>getParameter("strategy").getValue()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeaturePathfindToAll.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeaturePathfindToAll.java new file mode 100644 index 00000000..886eefef --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeaturePathfindToAll.java @@ -0,0 +1,45 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret; + +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +public class FeaturePathfindToAll extends SimpleFeature { + public FeaturePathfindToAll(){ + super("Dungeon Secrets.Pathfind To All", "Start pathfind to all secrets upon entering a room", "Auto browse to all secrets in the room", "secret.secretpathfind.allbrowse", false); + this.parameters.put("bat", new FeatureParameter<Boolean>("bat", "Trigger pathfind to Bat", "This feature will trigger pathfind to all bats in this room when entering a room", true, "boolean")); + this.parameters.put("chest", new FeatureParameter<Boolean>("chest", "Trigger pathfind to Chest", "This feature will trigger pathfind to all chests in this room when entering a room", true, "boolean")); + this.parameters.put("essence", new FeatureParameter<Boolean>("essence", "Trigger pathfind to Essence", "This feature will trigger pathfind to all essences in this room when entering a room", true, "boolean")); + this.parameters.put("itemdrop", new FeatureParameter<Boolean>("itemdrop", "Trigger pathfind to Itemdrop", "This feature will trigger pathfind to all itemdrops in this room when entering a room", true, "boolean")); + } + + public boolean isBat() { + return this.<Boolean>getParameter("bat").getValue(); + } + public boolean isChest() { + return this.<Boolean>getParameter("chest").getValue(); + } + public boolean isEssence() { + return this.<Boolean>getParameter("essence").getValue(); + } + public boolean isItemdrop() { + return this.<Boolean>getParameter("itemdrop").getValue(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureSoulRoomWarning.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureSoulRoomWarning.java new file mode 100644 index 00000000..983674fd --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureSoulRoomWarning.java @@ -0,0 +1,233 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret; + +import com.google.common.base.Supplier; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator; +import kr.syeyoung.dungeonsguide.config.guiconfig.MFeatureEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.MParameterEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.RootConfigPanel; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonFairySoul; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonMechanic; +import kr.syeyoung.dungeonsguide.features.listener.TickListener; +import kr.syeyoung.dungeonsguide.features.text.*; +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MPassiveLabelAndElement; +import kr.syeyoung.dungeonsguide.gui.elements.MStringSelectionButton; +import kr.syeyoung.dungeonsguide.gui.elements.MToggleButton; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoomInfoRegistry; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.text.*; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.*; +import java.util.List; +import java.util.function.Predicate; + +public class FeatureSoulRoomWarning extends TextHUDFeature implements TickListener { + + public FeatureSoulRoomWarning() { + super("Dungeon.Dungeon Information","Secret Soul Alert", "Alert if there is an fairy soul in the room", "secret.fairysoulwarn", true, getFontRenderer().getStringWidth("There is a fairy soul in this room!"), getFontRenderer().FONT_HEIGHT); + getStyles().add(new TextStyle("warning", new AColor(0xFF, 0x69,0x17,255), new AColor(0, 0,0,0), false)); + + this.parameters.put("roomuids", new FeatureParameter("roomuids", "Disabled room Names", "Disable for these rooms", new ArrayList<>(), "stringlist")); + } + + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + @Override + public boolean isHUDViewable() { + return warning > System.currentTimeMillis(); + } + + @Override + public List<String> getUsedTextStyle() { + return Collections.singletonList("warning"); + } + + private UUID lastRoomUID = UUID.randomUUID(); + private long warning = 0; + + private static final List<StyledText> text = new ArrayList<StyledText>(); + static { + text.add(new StyledText("There is a fairy soul in this room!", "warning")); + } + + @Override + public List<StyledText> getText() { + return text; + } + + + @Override + public void onTick() { + if (!skyblockStatus.isOnDungeon()) return; + if (skyblockStatus.getContext() == null || !skyblockStatus.getContext().getMapProcessor().isInitialized()) return; + DungeonContext context = skyblockStatus.getContext(); + + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + if (thePlayer == null) return; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom == null) return; + if (!(dungeonRoom.getRoomProcessor() instanceof GeneralRoomProcessor)) return; + + if (!dungeonRoom.getDungeonRoomInfo().getUuid().equals(lastRoomUID)) { + for (DungeonMechanic value : dungeonRoom.getMechanics().values()) { + if (value instanceof DungeonFairySoul) + warning = System.currentTimeMillis() + 2500; + } + lastRoomUID = dungeonRoom.getDungeonRoomInfo().getUuid(); + } + } + + @Override + public String getEditRoute(RootConfigPanel rootConfigPanel) { + ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() { + @Override + public MPanel get() { + + MFeatureEdit featureEdit = new MFeatureEdit(FeatureSoulRoomWarning.this, rootConfigPanel); + featureEdit.addParameterEdit("textStyleNEW", new PanelTextParameterConfig(FeatureSoulRoomWarning.this)); + + StyledTextRenderer.Alignment alignment = StyledTextRenderer.Alignment.valueOf(FeatureSoulRoomWarning.this.<String>getParameter("alignment").getValue()); + MStringSelectionButton mStringSelectionButton = new MStringSelectionButton(Arrays.asList("LEFT", "CENTER", "RIGHT"), alignment.name()); + mStringSelectionButton.setOnUpdate(() -> { + FeatureSoulRoomWarning.this.<String>getParameter("alignment").setValue(mStringSelectionButton.getSelected()); + }); + featureEdit.addParameterEdit("alignment", new MParameterEdit(FeatureSoulRoomWarning.this, FeatureSoulRoomWarning.this.<String>getParameter("alignment"), rootConfigPanel, mStringSelectionButton, (a) -> false)); + + for (FeatureParameter parameter: getParameters()) { + if (parameter.getKey().equals("textStylesNEW")) continue; + if (parameter.getKey().equals("alignment")) continue; + if (parameter.getKey().equals("roomuids")) continue; + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeatureSoulRoomWarning.this, parameter, rootConfigPanel)); + } + featureEdit.addParameterEdit("roomuids", new RoomSelectionPanel(FeatureSoulRoomWarning.this.<List<String>>getParameter("roomuids"), (a) -> { + for (DungeonMechanic value : a.getMechanics().values()) { + if (value instanceof DungeonFairySoul) return true; + } + return false; + }) ); + return featureEdit; + } + }); + return "base." + getKey() ; + } + + public static class RoomSelectionPanel extends MPanel { + FeatureParameter<List<String>> uids; + private List<MPassiveLabelAndElement> passiveLabelAndElements = new ArrayList<>(); + private List<MToggleButton> toggleButtons = new ArrayList<>(); + private MButton addAll, removeAll; + public RoomSelectionPanel(FeatureParameter<List<String>> roomuids, Predicate<DungeonRoomInfo> selectableRooms) { + this.uids = roomuids; + for (DungeonRoomInfo dungeonRoomInfo : DungeonRoomInfoRegistry.getRegistered()) { + if (!selectableRooms.test(dungeonRoomInfo)) continue; + MToggleButton mToggleButton = new MToggleButton(); + mToggleButton.setEnabled(!roomuids.getValue().contains(dungeonRoomInfo.getUuid().toString())); + mToggleButton.setOnToggle(() -> { + if (mToggleButton.isEnabled()) + roomuids.getValue().remove(dungeonRoomInfo.getUuid().toString()); + else + roomuids.getValue().add(dungeonRoomInfo.getUuid().toString()); + }); + toggleButtons.add(mToggleButton); + MPassiveLabelAndElement passiveLabelAndElement = new MPassiveLabelAndElement(dungeonRoomInfo.getName(), mToggleButton); + passiveLabelAndElement.setDivideRatio(0.7); + passiveLabelAndElements.add(passiveLabelAndElement); + } + for (MPassiveLabelAndElement passiveLabelAndElement : passiveLabelAndElements) { + add(passiveLabelAndElement); + } + { + addAll = new MButton(); addAll.setText("Enable All"); + addAll.setOnActionPerformed(() -> { + roomuids.getValue().clear(); + for (MToggleButton toggleButton : toggleButtons) { + toggleButton.setEnabled(true); + } + }); + removeAll = new MButton(); removeAll.setText("Disable All"); + removeAll.setOnActionPerformed(() -> { + for (MToggleButton toggleButton : toggleButtons) { + toggleButton.setEnabled(false); + toggleButton.getOnToggle().run(); + } + }); + add(addAll); add(removeAll); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(-1, (int) (20 * Math.ceil(passiveLabelAndElements.size() / 3) + 27)); + } + + @Override + public void onBoundsUpdate() { + int xI = 0; + int y = 22; + int w3 = (getBounds().width-20) / 3; + for (MPassiveLabelAndElement passiveLabelAndElement : passiveLabelAndElements) { + passiveLabelAndElement.setBounds(new Rectangle(5 + xI * (w3+5), y, w3, 20)); + xI ++; + if (xI == 3) { + xI = 0; + y += 20; + } + } + + addAll.setBounds(new Rectangle(getBounds().width-150, 2, 70, 14)); + removeAll.setBounds(new Rectangle(getBounds().width-75, 2, 70, 14)); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + Gui.drawRect(0,0,getBounds().width, getBounds().height,RenderUtils.blendAlpha(0x141414, 0.12f)); + Gui.drawRect(1,18,getBounds().width -1, getBounds().height-1, RenderUtils.blendAlpha(0x141414, 0.15f)); + Gui.drawRect(1,1,getBounds().width-1, 18, RenderUtils.blendAlpha(0x141414, 0.12f)); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GlStateManager.pushMatrix(); + GlStateManager.translate(5,5,0); + GlStateManager.scale(1.0,1.0,0); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Enable for these rooms", 0,0, 0xFFFFFFFF); + GlStateManager.popMatrix(); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureTogglePathfind.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureTogglePathfind.java new file mode 100644 index 00000000..b4d41096 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/FeatureTogglePathfind.java @@ -0,0 +1,45 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret; + +import kr.syeyoung.dungeonsguide.features.listener.KeybindPressedListener; +import kr.syeyoung.dungeonsguide.events.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ChatComponentText; +import org.lwjgl.input.Keyboard; + +public class FeatureTogglePathfind extends SimpleFeature implements KeybindPressedListener { + public FeatureTogglePathfind() { + super("Dungeon Secrets.Keybinds", "Toggle Pathfind Lines", "A key for toggling pathfound line visibility.\nPress settings to edit the key", "secret.togglePathfind"); + this.parameters.put("key", new FeatureParameter<Integer>("key", "Key", "Press to toggle pathfind lines", Keyboard.KEY_NONE, "keybind")); + } + public boolean togglePathfindStatus = false; + + @Override + public void onKeybindPress(KeyBindPressedEvent keyBindPressedEvent) { + if (keyBindPressedEvent.getKey() == this.<Integer>getParameter("key").getValue() && isEnabled()) { + togglePathfindStatus = !togglePathfindStatus; + try { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fToggled Pathfind Line visibility to §e"+(togglePathfindStatus ? "on":"off"))); + } catch (Exception ignored) {} + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/PathfindLineProperties.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/PathfindLineProperties.java new file mode 100644 index 00000000..9405814d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/PathfindLineProperties.java @@ -0,0 +1,115 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret; + +import com.google.common.base.Supplier; +import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.config.guiconfig.MFeatureEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.MParameterEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.RootConfigPanel; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.gui.MPanel; + +import java.util.LinkedHashMap; + +public class PathfindLineProperties extends SimpleFeature { + private PathfindLineProperties parent; + public PathfindLineProperties(String category, String name, String description, String key, boolean useParent, PathfindLineProperties parent) { + super(category, name, description, key); + this.parent = parent; + this.parameters = new LinkedHashMap<>(); + if (parent != null) + this.parameters.put("useGlobal", new FeatureParameter<Boolean>("useGlobal", "Use Global Settings instead of this", "Completely ignore these settings, then use the parent one:: '"+parent.getName()+"'", useParent, "boolean")); + this.parameters.put("pathfind", new FeatureParameter<Boolean>("pathfind", "Enable Pathfinding", "Enable pathfind for secrets", useParent, "boolean")); + this.parameters.put("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the pathfind line", new AColor(0xFFFF0000, true), "acolor")); + this.parameters.put("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the pathfind line",1.0f, "float")); + this.parameters.put("linerefreshrate", new FeatureParameter<Integer>("linerefreshrate", "Line Refreshrate", "Ticks to wait per line refresh. Specify it to -1 to don't refresh line at all", 10, "integer")); + this.parameters.put("beacon", new FeatureParameter<Boolean>("beacon", "Enable Beacons", "Enable beacons for pathfind line targets", true, "boolean")); + this.parameters.put("beamColor", new FeatureParameter<AColor>("beamColor", "Beam Color", "Color of the beacon beam", new AColor(0x77FF0000, true), "acolor")); + this.parameters.put("beamTargetColor", new FeatureParameter<AColor>("beamTargetColor", "Target Color", "Color of the target", new AColor(0x33FF0000, true), "acolor")); + } + + + public String getEditRoute(RootConfigPanel rootConfigPanel) { + ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() { + @Override + public MPanel get() { + MFeatureEdit featureEdit = new MFeatureEdit(PathfindLineProperties.this, rootConfigPanel); + for (FeatureParameter parameter: getParameters()) { + if (parameter.getKey().startsWith("line")) + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(PathfindLineProperties.this, parameter, rootConfigPanel, a -> isGlobal() || !isPathfind())); + else if (parameter.getKey().startsWith("beam")) + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(PathfindLineProperties.this, parameter, rootConfigPanel, a -> isGlobal() || !isBeacon())); + else if (!parameter.getKey().equals("useGlobal")) + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(PathfindLineProperties.this, parameter, rootConfigPanel, a -> isGlobal())); + else + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(PathfindLineProperties.this, parameter, rootConfigPanel, a -> false)); + } + return featureEdit; + } + }); + return "base." + getKey() ; + } + + @Override + public boolean isDisyllable() { + return false; + } + + public boolean isGlobal() { + if (parent == null) return false; + return this.<Boolean>getParameter("useGlobal").getValue(); + } + + public boolean isPathfind() { + return isGlobal() ? parent.isPathfind() : this.<Boolean>getParameter("pathfind").getValue(); + } + public AColor getLineColor() { + return isGlobal() ? parent.getLineColor() : this.<AColor>getParameter("lineColor").getValue(); + } + public float getLineWidth() { + return isGlobal() ? parent.getLineWidth() : this.<Float>getParameter("lineWidth").getValue(); + } + public int getRefreshRate() { + return isGlobal() ? parent.getRefreshRate() : this.<Integer>getParameter("linerefreshrate").getValue(); + } + public boolean isBeacon() { + return isGlobal() ? parent.isBeacon() : this.<Boolean>getParameter("beacon").getValue(); + } + public AColor getBeamColor() { + return isGlobal() ? parent.getBeamColor() : this.<AColor>getParameter("beamColor").getValue(); + } + public AColor getTargetColor() { + return isGlobal() ? parent.getTargetColor() : this.<AColor>getParameter("beamTargetColor").getValue(); + } + public ActionRoute.ActionRouteProperties getRouteProperties() { + ActionRoute.ActionRouteProperties actionRouteProperties = new ActionRoute.ActionRouteProperties(); + actionRouteProperties.setPathfind(isPathfind()); + actionRouteProperties.setLineColor(getLineColor()); + actionRouteProperties.setLineWidth(getLineWidth()); + actionRouteProperties.setLineRefreshRate(getRefreshRate()); + actionRouteProperties.setBeacon(isBeacon()); + actionRouteProperties.setBeaconBeamColor(getBeamColor()); + actionRouteProperties.setBeaconColor(getTargetColor()); + return actionRouteProperties; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/FeatureMechanicBrowse.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/FeatureMechanicBrowse.java new file mode 100644 index 00000000..1979d741 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/FeatureMechanicBrowse.java @@ -0,0 +1,164 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret.mechanicbrowser; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.config.types.GUIRectangle; +import kr.syeyoung.dungeonsguide.features.listener.GuiClickListener; +import kr.syeyoung.dungeonsguide.features.listener.GuiPreRenderListener; +import kr.syeyoung.dungeonsguide.features.listener.WorldRenderListener; +import kr.syeyoung.dungeonsguide.gui.elements.MFloatSelectionButton; +import kr.syeyoung.dungeonsguide.gui.elements.MPassiveLabelAndElement; +import kr.syeyoung.dungeonsguide.config.guiconfig.location.GuiGuiLocationConfig; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.GuiFeature; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.*; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.MathHelper; +import net.minecraftforge.client.event.GuiScreenEvent; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.io.IOException; +import java.util.*; +import java.util.List; + +public class FeatureMechanicBrowse extends GuiFeature implements GuiPreRenderListener, GuiClickListener, WorldRenderListener { + public FeatureMechanicBrowse() { + super("Dungeon Secrets.Secret Browser","Secret Browser", "Browse and Pathfind secrets and mechanics in the current room", "secret.mechanicbrowse", false, 100, 300); + parameters.put("scale", new FeatureParameter<Float>("scale", "Scale", "Scale", 1.0f, "float")); + mGuiMechanicBrowser = new MGuiMechanicBrowser(this); + mGuiMechanicBrowser.setWorldAndResolution(Minecraft.getMinecraft(), Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight); + lastWidth = Minecraft.getMinecraft().displayWidth; lastHeight = Minecraft.getMinecraft().displayHeight; + } + + public double getScale() { + return this.<Float>getParameter("scale").getValue(); + } + + private MGuiMechanicBrowser mGuiMechanicBrowser; + + + @Override + public void drawDemo(float partialTicks) { + super.drawDemo(partialTicks); + double scale = FeatureMechanicBrowse.this.<Float>getParameter("scale").getValue(); + GlStateManager.scale(scale, scale, 1.0); + + Dimension bigDim = getFeatureRect().getRectangleNoScale().getSize(); + Dimension effectiveDim = new Dimension((int) (bigDim.width / scale),(int)( bigDim.height / scale)); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + Gui.drawRect(0, 0, effectiveDim.width, fr.FONT_HEIGHT + 4, 0xFF444444); + Gui.drawRect(1, 1, effectiveDim.width - 1, fr.FONT_HEIGHT + 3, 0xFF262626); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Selected: ", 2,2, 0xFFAAAAAA); + fr.drawString("Nothing", fr.getStringWidth("Selected: ") + 2,2, 0xFFAA0000); + fr.drawString("Open Chat to Select Secrets", 2, fr.FONT_HEIGHT + 5, 0xFFAAAAAA); + } + + private int lastWidth, lastHeight; + + @Override + public void drawScreen(float partialTicks) { + if (!isEnabled()) return; + int i = Mouse.getEventX(); + int j = Minecraft.getMinecraft().displayHeight - Mouse.getEventY(); + if (Minecraft.getMinecraft().displayWidth != lastWidth || Minecraft.getMinecraft().displayHeight != lastHeight) mGuiMechanicBrowser.initGui(); + lastWidth = Minecraft.getMinecraft().displayWidth; lastHeight = Minecraft.getMinecraft().displayHeight; + mGuiMechanicBrowser.drawScreen(i,j,partialTicks); + } + + @Override + public void setFeatureRect(GUIRectangle featureRect) { + super.setFeatureRect(featureRect); + mGuiMechanicBrowser.initGui(); + } + + @Override + public void drawHUD(float partialTicks) { } + + @Override + public void onMouseInput(GuiScreenEvent.MouseInputEvent.Pre mouseInputEvent) { + if (!isEnabled()) return; + try { + mGuiMechanicBrowser.handleMouseInput(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + @Override + public void onGuiPreRender(GuiScreenEvent.DrawScreenEvent.Pre rendered) { + if (!isEnabled()) return; + int i = Mouse.getEventX(); + int j = Minecraft.getMinecraft().displayHeight - Mouse.getEventY(); + mGuiMechanicBrowser.drawScreen(i, j, rendered.renderPartialTicks); + } + + @Override + public void drawWorld(float partialTicks) { + if (!isEnabled()) return; + SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + if (!skyblockStatus.isOnDungeon()) return; + if (skyblockStatus.getContext() == null || !skyblockStatus.getContext().getMapProcessor().isInitialized()) return; + DungeonContext context = skyblockStatus.getContext(); + + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + Point roomPt = context.getMapProcessor().worldPointToRoomPoint(thePlayer.getPosition()); + DungeonRoom dungeonRoom = context.getRoomMapper().get(roomPt); + if (dungeonRoom == null) return; + if (!(dungeonRoom.getRoomProcessor() instanceof GeneralRoomProcessor)) return; + String id = mGuiMechanicBrowser.getPanelMechanicBrowser().getSelectedID(); + if (id != null) { + Optional.ofNullable(dungeonRoom.getMechanics().get(mGuiMechanicBrowser.getPanelMechanicBrowser().getSelectedID())) + .ifPresent(a -> { + a.highlight(new Color(0,255,255,50), id +" ("+( + dungeonRoom.getMechanics().get(id).getRepresentingPoint(dungeonRoom) != null ? + String.format("%.1f", MathHelper.sqrt_double((dungeonRoom.getMechanics().get(id)).getRepresentingPoint(dungeonRoom).getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()))) : "") + +"m)", dungeonRoom, partialTicks); + }); + } + } + @Override + public List<MPanel> getTooltipForEditor(GuiGuiLocationConfig guiGuiLocationConfig) { + List<MPanel> mPanels = super.getTooltipForEditor(guiGuiLocationConfig); + + mPanels.add(new MPassiveLabelAndElement("Scale", new MFloatSelectionButton(FeatureMechanicBrowse.this.<Float>getParameter("scale").getValue()) {{ + setOnUpdate(() ->{ + FeatureMechanicBrowse.this.<Float>getParameter("scale").setValue(this.getData()); + mGuiMechanicBrowser.initGui(); + }); } + })); + + return mPanels; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/MGuiMechanicBrowser.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/MGuiMechanicBrowser.java new file mode 100644 index 00000000..27d5e583 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/MGuiMechanicBrowser.java @@ -0,0 +1,45 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret.mechanicbrowser; + +import kr.syeyoung.dungeonsguide.gui.MGui; +import lombok.Getter; + +public class MGuiMechanicBrowser extends MGui { + private FeatureMechanicBrowse featureMechanicBrowse; + @Getter + private PanelMechanicBrowser panelMechanicBrowser; + public MGuiMechanicBrowser(FeatureMechanicBrowse mechanicBrowse) { + this.featureMechanicBrowse = mechanicBrowse; + panelMechanicBrowser = new PanelMechanicBrowser(mechanicBrowse); + getMainPanel().add(panelMechanicBrowser); + } + + @Override + public void initGui() { + super.initGui(); + panelMechanicBrowser.setBounds(featureMechanicBrowse.getFeatureRect().getRectangle()); + panelMechanicBrowser.setScale(featureMechanicBrowse.getScale()); + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawScreen(mouseX, mouseY, partialTicks); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/MechanicBrowserElement.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/MechanicBrowserElement.java new file mode 100644 index 00000000..a177684a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/MechanicBrowserElement.java @@ -0,0 +1,61 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret.mechanicbrowser; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import lombok.AllArgsConstructor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; + +import java.awt.*; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +@AllArgsConstructor +public class MechanicBrowserElement extends MPanel { + private Supplier<String> name; + private boolean isCategory = false; + private BiConsumer<MechanicBrowserElement, Point> onClick; + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + if (isCategory || isFocused) + Gui.drawRect(0, 0, bounds.width, bounds.height, 0xFF444444); + else if (lastAbsClip.contains(absMousex, absMousey)) + Gui.drawRect(0, 0, bounds.width, bounds.height, 0xFF555555); + Minecraft.getMinecraft().fontRendererObj.drawString((String)name.get(), 4, 1, 0xFFEEEEEE); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(Minecraft.getMinecraft().fontRendererObj.getStringWidth(name.get()) + 8, Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT); + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (lastAbsClip.contains(absMouseX, absMouseY) && onClick != null) + onClick.accept(this, new Point(lastParentPoint.x + bounds.x, lastParentPoint.y + bounds.y)); + } + + @Override + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + if (lastAbsClip.contains(absMouseX, absMouseY) && onClick != null) + setCursor(EnumCursor.POINTING_HAND); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/MechanicBrowserTooltip.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/MechanicBrowserTooltip.java new file mode 100644 index 00000000..e2a0d028 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/MechanicBrowserTooltip.java @@ -0,0 +1,68 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret.mechanicbrowser; + +import kr.syeyoung.dungeonsguide.gui.elements.MList; +import kr.syeyoung.dungeonsguide.gui.elements.MTooltip; +import lombok.Getter; +import net.minecraft.client.gui.Gui; + +import java.awt.*; + +public class MechanicBrowserTooltip extends MTooltip { + @Getter + private MList mList; + public MechanicBrowserTooltip() { + mList = new MList(); + mList.setGap(0); + add(mList); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + Dimension effectiveDim = getEffectiveDimension(); + Gui.drawRect(0, 0, effectiveDim.width, effectiveDim.height, 0xFF444444); + Gui.drawRect(1, 1, effectiveDim.width - 1, effectiveDim.height - 1, 0xFF262626); + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + mList.setBounds(new Rectangle(1,1, getEffectiveDimension().width-2, getEffectiveDimension().height-2)); + mList.realignChildren(); + } + + @Override + public void setScale(double scale) { + super.setScale(scale); + mList.setBounds(new Rectangle(1,1, getEffectiveDimension().width-2, getEffectiveDimension().height-2)); + mList.realignChildren(); + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = mList.getPreferredSize(); + return new Dimension((int) ((dim.width + 2) * getScale()), (int) ((dim.height + 2) * getScale())); + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (!lastAbsClip.contains(absMouseX, absMouseY)) close(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/PanelMechanicBrowser.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/PanelMechanicBrowser.java new file mode 100644 index 00000000..0457a2a8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/secret/mechanicbrowser/PanelMechanicBrowser.java @@ -0,0 +1,327 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.secret.mechanicbrowser; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.*; +import kr.syeyoung.dungeonsguide.gui.elements.MList; +import kr.syeyoung.dungeonsguide.gui.elements.MPanelScaledGUI; +import kr.syeyoung.dungeonsguide.gui.elements.MScrollablePanel; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiChat; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.MathHelper; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class PanelMechanicBrowser extends MPanelScaledGUI { + private FeatureMechanicBrowse feature; + private MScrollablePanel scrollablePanel; + private MList mList; + private MechanicBrowserTooltip mechanicBrowserTooltip; + + public PanelMechanicBrowser(FeatureMechanicBrowse mechanicBrowse) { + this.feature = mechanicBrowse; + this.scrollablePanel = new MScrollablePanel(1); + add(this.scrollablePanel); + scrollablePanel.getScrollBarY().setWidth(0); + mList = new MList() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0,0,parentWidth,parentHeight)); + Dimension prefSize = getPreferredSize(); + int hei = prefSize.height; + setBounds(new Rectangle(0,0,parentWidth,hei)); + realignChildren(); + } + }; + mList.setDrawLine(false); mList.setGap(0); + scrollablePanel.add(mList); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + toggleTooltip(openGUI()); + + Optional<DungeonRoom> dungeonRoomOpt = Optional.ofNullable(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext()) + .map(DungeonContext::getMapProcessor).map(a->a.worldPointToRoomPoint(Minecraft.getMinecraft().thePlayer.getPosition())) + .map(a -> DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext().getRoomMapper().get(a)); + + DungeonRoom dungeonRoom = dungeonRoomOpt.orElse(null); + renderTick(dungeonRoom); + if (dungeonRoom == null) return; + if (!(dungeonRoom.getRoomProcessor() instanceof GeneralRoomProcessor)) return; + + GeneralRoomProcessor grp = (GeneralRoomProcessor) dungeonRoom.getRoomProcessor(); + + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + Dimension effectiveDim = getEffectiveDimension(); + + Gui.drawRect(0, 0, effectiveDim.width, fr.FONT_HEIGHT + 4, 0xFF444444); + Gui.drawRect(1, 1, effectiveDim.width - 1, fr.FONT_HEIGHT + 3, 0xFF262626); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Selected: ", 2,2, 0xFFAAAAAA); + if (grp.getPath("MECH-BROWSER") == null) + fr.drawString("Nothing", fr.getStringWidth("Selected: ") + 2,2, 0xFFAA0000); + else { + ActionRoute route = grp.getPath("MECH-BROWSER"); + fr.drawString(route.getMechanic()+" -> "+route.getState(), fr.getStringWidth("Selected: ") + 2,2, 0xFFFFFF00); + } + fr.drawString("Open Chat to Select Secrets", 2, fr.FONT_HEIGHT + 5, 0xFFAAAAAA); + + if (!openGUI()) return; + + Gui.drawRect(0, fr.FONT_HEIGHT + 4, effectiveDim.width, effectiveDim.height, 0xFF444444); + Gui.drawRect(1, fr.FONT_HEIGHT + 5, effectiveDim.width - 1,effectiveDim.height - 1, 0xFF262626); + } + + private UUID lastRoomUID = null; + public void renderTick(DungeonRoom dungeonRoom) { + if (dungeonRoom == null && lastRoomUID != null) { + lastRoomUID = null; + for (MPanel childComponent : mList.getChildComponents()) { + mList.remove(childComponent); + } + if (mechanicBrowserTooltip != null) { + mechanicBrowserTooltip.close(); + mechanicBrowserTooltip = null; + } + selectedID = null; + } else if (dungeonRoom != null && lastRoomUID != dungeonRoom.getDungeonRoomInfo().getUuid()) { + lastRoomUID = dungeonRoom.getDungeonRoomInfo().getUuid(); + // SETUP THINGS. + for (MPanel childComponent : mList.getChildComponents()) { + mList.remove(childComponent); + } + if (mechanicBrowserTooltip != null) { + mechanicBrowserTooltip.close(); + mechanicBrowserTooltip = null; + } + selectedID = null; + mList.add(new MechanicBrowserElement(() -> "§bCancel Current", false, (pt, me) -> cancel(pt))); + + boolean found = false; + for (Map.Entry<String, DungeonMechanic> value : dungeonRoom.getMechanics().entrySet()) { + if (value.getValue() instanceof DungeonFairySoul) { + if (!found) { + mList.add(new MechanicBrowserElement(() -> "Fairy Soul", true, null)); + found = true; + } + mList.add(new MechanicBrowserElement(() -> value.getKey()+" §7("+ value.getValue().getCurrentState(dungeonRoom) +", "+ + (value.getValue().getRepresentingPoint(dungeonRoom) != null ? + String.format("%.1f", MathHelper.sqrt_double(value.getValue().getRepresentingPoint(dungeonRoom).getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()))) : "") + +"m)", false, (me, pt) -> onElementClick(value.getKey(), value.getValue(), pt, me))); + } + } + found = false; + for (Map.Entry<String, DungeonMechanic> value : dungeonRoom.getMechanics().entrySet()) { + if (value.getValue() instanceof DungeonSecret) { + if (!found) { + mList.add(new MechanicBrowserElement(() -> "Secrets", true, null)); + found = true; + } + mList.add(new MechanicBrowserElement(() -> value.getKey()+" §7("+ value.getValue().getCurrentState(dungeonRoom) +", "+ + (value.getValue().getRepresentingPoint(dungeonRoom) != null ? + String.format("%.1f", MathHelper.sqrt_double(value.getValue().getRepresentingPoint(dungeonRoom).getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()))) : "") + +"m)", false, (me, pt) -> onElementClick(value.getKey(), value.getValue(), pt, me))); + } + } + found = false; + for (Map.Entry<String, DungeonMechanic> value : dungeonRoom.getMechanics().entrySet()) { + if (value.getValue() instanceof DungeonTomb) { + if (!found) { + mList.add(new MechanicBrowserElement(() -> "Crypts", true, null)); + found = true; + } + mList.add(new MechanicBrowserElement(() -> value.getKey()+" §7("+ value.getValue().getCurrentState(dungeonRoom) +", "+ + (value.getValue().getRepresentingPoint(dungeonRoom) != null ? + String.format("%.1f", MathHelper.sqrt_double(value.getValue().getRepresentingPoint(dungeonRoom).getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()))) : "") + +"m)", false, (me, pt) -> onElementClick(value.getKey(), value.getValue(), pt, me))); + } + } + found = false; + for (Map.Entry<String, DungeonMechanic> value : dungeonRoom.getMechanics().entrySet()) { + if (value.getValue() instanceof DungeonNPC) { + if (!found) { + mList.add(new MechanicBrowserElement(() -> "NPC", true, null)); + found = true; + } + mList.add(new MechanicBrowserElement(() -> value.getKey()+" §7("+ value.getValue().getCurrentState(dungeonRoom) +", "+ + (value.getValue().getRepresentingPoint(dungeonRoom) != null ? + String.format("%.1f", MathHelper.sqrt_double(value.getValue().getRepresentingPoint(dungeonRoom).getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()))) : "") + +"m)", false, (me, pt) -> onElementClick(value.getKey(), value.getValue(), pt, me))); + } + } + found = false; + for (Map.Entry<String, DungeonMechanic> value : dungeonRoom.getMechanics().entrySet()) { + if (value.getValue() instanceof DungeonJournal) { + if (!found) { + mList.add(new MechanicBrowserElement(() -> "Journals", true, null)); + found = true; + } + mList.add(new MechanicBrowserElement(() -> value.getKey()+" §7("+ value.getValue().getCurrentState(dungeonRoom) +", "+ + (value.getValue().getRepresentingPoint(dungeonRoom) != null ? + String.format("%.1f", MathHelper.sqrt_double(value.getValue().getRepresentingPoint(dungeonRoom).getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()))) : "") + +"m)", false, (me, pt) -> onElementClick(value.getKey(), value.getValue(), pt, me))); + } + } + found = false; + for (Map.Entry<String, DungeonMechanic> value : dungeonRoom.getMechanics().entrySet()) { + if (value.getValue() instanceof DungeonRoomDoor){ + if (!found) { + mList.add(new MechanicBrowserElement(() -> "Gates", true, null)); + found = true; + } + mList.add(new MechanicBrowserElement(() -> value.getKey()+" §7("+ value.getValue().getCurrentState(dungeonRoom) +", "+ + (value.getValue().getRepresentingPoint(dungeonRoom) != null ? + String.format("%.1f", MathHelper.sqrt_double(value.getValue().getRepresentingPoint(dungeonRoom).getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()))) : "") + +"m)", false, (me, pt) -> onElementClick(value.getKey(), value.getValue(), pt, me))); + } + } + found = false; + for (Map.Entry<String, DungeonMechanic> value : dungeonRoom.getMechanics().entrySet()) { + if (value.getValue() instanceof DungeonDoor || value.getValue() instanceof DungeonBreakableWall || value.getValue() instanceof DungeonLever + || value.getValue() instanceof DungeonOnewayDoor || value.getValue() instanceof DungeonOnewayLever || value.getValue() instanceof DungeonPressurePlate) { + if (!found) { + mList.add(new MechanicBrowserElement(() -> "ETC", true, null)); + found = true; + } + mList.add(new MechanicBrowserElement(() -> value.getKey()+" §7("+ value.getValue().getCurrentState(dungeonRoom) +", "+ + (value.getValue().getRepresentingPoint(dungeonRoom) != null ? + String.format("%.1f", MathHelper.sqrt_double(value.getValue().getRepresentingPoint(dungeonRoom).getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()))) : "") + +"m)", false, (me, pt) -> onElementClick(value.getKey(), value.getValue(), pt, me))); + } + } + + scrollablePanel.evalulateContentArea(); + + } + } + + private int latestTooltipDY; + @Getter + private String selectedID = null; + public void onElementClick(String id, DungeonMechanic dungeonMechanic, Point pt, MechanicBrowserElement mechanicBrowserElement) { + Optional<DungeonRoom> dungeonRoomOpt = Optional.ofNullable(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext()) + .map(DungeonContext::getMapProcessor).map(a->a.worldPointToRoomPoint(Minecraft.getMinecraft().thePlayer.getPosition())) + .map(a -> DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext().getRoomMapper().get(a)); + selectedID = id; + + DungeonRoom dungeonRoom = dungeonRoomOpt.orElse(null); + if (dungeonRoom == null) return; + DungeonMechanic dungeonMechanic1 = dungeonRoom.getMechanics().get(id); + if (dungeonMechanic1 != dungeonMechanic) return; + Set<String> states = dungeonMechanic1.getPossibleStates(dungeonRoom); + + + if (mechanicBrowserTooltip != null) { + mechanicBrowserTooltip.close(); + } + + latestTooltipDY = (int) (pt.y * getScale() - bounds.y - 1); + + mechanicBrowserTooltip = new MechanicBrowserTooltip(); + for (String state : states) { + mechanicBrowserTooltip.getMList().add(new MechanicBrowserElement(() -> state, false, (m2, pt2) -> { + if (dungeonRoom.getRoomProcessor() instanceof GeneralRoomProcessor) + ((GeneralRoomProcessor)dungeonRoom.getRoomProcessor()).pathfind("MECH-BROWSER", id, state, FeatureRegistry.SECRET_LINE_PROPERTIES_SECRET_BROWSER.getRouteProperties()); +// mechanicBrowserTooltip.close(); +// mechanicBrowserTooltip = null; + })); + } + mechanicBrowserTooltip.setScale(getScale()); + Dimension prefSize = mechanicBrowserTooltip.getPreferredSize(); + mechanicBrowserTooltip.setBounds(new Rectangle(bounds.x + + (bounds.x > Minecraft.getMinecraft().displayWidth/2 ? -prefSize.width : bounds.width), latestTooltipDY + bounds.y, prefSize.width, prefSize.height)); + mechanicBrowserTooltip.open(this); + } + + public void cancel(MechanicBrowserElement mechanicBrowserElement) { + Optional<DungeonRoom> dungeonRoomOpt = Optional.ofNullable(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext()) + .map(DungeonContext::getMapProcessor).map(a->a.worldPointToRoomPoint(Minecraft.getMinecraft().thePlayer.getPosition())) + .map(a -> DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext().getRoomMapper().get(a)); + mechanicBrowserElement.setFocused(false); + if (!dungeonRoomOpt.isPresent()) return; + DungeonRoom dungeonRoom = dungeonRoomOpt.get(); + if (!(dungeonRoom.getRoomProcessor() instanceof GeneralRoomProcessor)) return; + ((GeneralRoomProcessor) dungeonRoom.getRoomProcessor()).cancel("MECH-BROWSER"); + } + + public void toggleTooltip(boolean open) { + if (mechanicBrowserTooltip != null) { + if (open) { + mechanicBrowserTooltip.open(this); + } else { + mechanicBrowserTooltip.close(); + } + } + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + Dimension dimension = getEffectiveDimension(); + int y = Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT + 4; + scrollablePanel.setBounds(new Rectangle(1,y + 1, dimension.width - 2, dimension.height - y - 2)); + scrollablePanel.evalulateContentArea(); + if (mechanicBrowserTooltip != null) { + Dimension prefSize = mechanicBrowserTooltip.getPreferredSize(); + mechanicBrowserTooltip.setScale(getScale()); + mechanicBrowserTooltip.setBounds(new Rectangle(bounds.x + (bounds.x > Minecraft.getMinecraft().displayWidth/2 ? -prefSize.width: bounds.width), latestTooltipDY + bounds.y, prefSize.width, prefSize.height)); + } + } + + public boolean openGUI() { + return Minecraft.getMinecraft().currentScreen != null + && Minecraft.getMinecraft().currentScreen instanceof GuiChat && lastRoomUID != null; + } + + @Override + public List<MPanel> getChildComponents() { + return openGUI() ? super.getChildComponents() : Collections.emptyList(); + } + + @Override + public boolean mouseClicked0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int mouseButton) { + selectedID = null; + if (mechanicBrowserTooltip != null) { + mechanicBrowserTooltip.close(); + mechanicBrowserTooltip = null; + } + + return super.mouseClicked0(absMouseX, absMouseY, relMouseX0, relMouseY0, mouseButton); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverBlaze.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverBlaze.java new file mode 100644 index 00000000..1e698414 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverBlaze.java @@ -0,0 +1,46 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.solvers; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +public class FeatureSolverBlaze extends SimpleFeature { + public FeatureSolverBlaze() { + super("Solver.Floor 2+", "Blaze", "Highlights the blaze that needs to be killed in an blaze room", "solver.blaze"); + parameters.put("normBlazeColor", new FeatureParameter<AColor>("blazecolor", "Normal Blaze Color", "Normal Blaze Color", new AColor(255,255,255,255), "acolor")); + parameters.put("nextBlazeColor", new FeatureParameter<AColor>("blazecolor", "Next Blaze Color", "Next Blaze Color", new AColor(0,255,0,255), "acolor")); + parameters.put("nextUpBlazeColor", new FeatureParameter<AColor>("blazecolor", "Next Up Blaze Color", "Color of blaze after next blaze", new AColor(255,255,0,255), "acolor")); + parameters.put("blazeborder", new FeatureParameter<AColor>("blazeborder", "Blaze Border Color", "Blaze border color", new AColor(255,255,255,0), "acolor")); + } + + public AColor getBlazeColor() { + return this.<AColor>getParameter("normBlazeColor").getValue(); + } + public AColor getNextBlazeColor() { + return this.<AColor>getParameter("nextBlazeColor").getValue(); + } + public AColor getNextUpBlazeColor() { + return this.<AColor>getParameter("nextUpBlazeColor").getValue(); + } + public AColor getBorder() { + return this.<AColor>getParameter("blazeborder").getValue(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverBombdefuse.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverBombdefuse.java new file mode 100644 index 00000000..e9bf623b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverBombdefuse.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.solvers; + +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import org.lwjgl.input.Keyboard; + +public class FeatureSolverBombdefuse extends SimpleFeature { + public FeatureSolverBombdefuse() { + super("Solver.Floor 7+", "Bomb Defuse", "Communicates with others dg using key 'F' for solutions and displays it", "solver.bombdefuse"); + parameters.put("key", new FeatureParameter<Integer>("key", "Key","Press to send solution in chat", Keyboard.KEY_NONE, "keybind")); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverBox.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverBox.java new file mode 100644 index 00000000..c4dcebf6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverBox.java @@ -0,0 +1,57 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.solvers; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +import java.util.LinkedHashMap; + +public class FeatureSolverBox extends SimpleFeature { + public FeatureSolverBox() { + super("Solver.Floor 3+", "Box (Advanced)", "Calculates solution for box puzzle room, and displays it to user", "solver.box"); + this.parameters = new LinkedHashMap<>(); + this.parameters.put("disableText", new FeatureParameter<Boolean>("disableText", "Box Puzzle Solver Disable text", "Disable 'Type recalc to recalculate solution' showing up on top left.\nYou can still type recalc to recalc solution after disabling this feature", false, "boolean")); + this.parameters.put("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the solution line", new AColor(0xFF00FF00, true), "acolor")); + this.parameters.put("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the solution line",1.0f, "float")); + + this.parameters.put("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the target button", new AColor(0x5500FFFF, true), "acolor")); + this.parameters.put("textColor1", new FeatureParameter<AColor>("textColor1", "Text Color", "Color of the text (next step)", new AColor(0xFF00FF00, true), "acolor")); + this.parameters.put("textColor2", new FeatureParameter<AColor>("textColor2", "Text Color", "Color of the text (others)", new AColor(0xFF000000, true), "acolor")); + } + public AColor getLineColor() { + return this.<AColor>getParameter("lineColor").getValue(); + } + public float getLineWidth() { + return this.<Float>getParameter("lineWidth").getValue(); + } + public boolean disableText() { + return this.<Boolean>getParameter("disableText").getValue(); + } + public AColor getTargetColor() { + return this.<AColor>getParameter("targetColor").getValue(); + } + public AColor getTextColor() { + return this.<AColor>getParameter("textColor1").getValue(); + } + public AColor getTextColor2() { + return this.<AColor>getParameter("textColor2").getValue(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverIcefill.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverIcefill.java new file mode 100644 index 00000000..681e6b12 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverIcefill.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.solvers; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +import java.util.LinkedHashMap; + +public class FeatureSolverIcefill extends SimpleFeature { + public FeatureSolverIcefill() { + super("Solver.Floor 3+", "Icepath (Advanced)", "Calculates solution for icepath puzzle and displays it to user", "solver.icepath"); + this.parameters = new LinkedHashMap<>(); + this.parameters.put("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the solution line", new AColor(0xFF00FF00, true), "acolor")); + this.parameters.put("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the solution line",1.0f, "float")); + } + public AColor getLineColor() { + return this.<AColor>getParameter("lineColor").getValue(); + } + public float getLineWidth() { + return this.<Float>getParameter("lineWidth").getValue(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverKahoot.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverKahoot.java new file mode 100644 index 00000000..6055c12b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverKahoot.java @@ -0,0 +1,35 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.solvers; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +public class FeatureSolverKahoot extends SimpleFeature { + public FeatureSolverKahoot() { + super("Solver.Floor 4+", "Quiz", "Highlights the correct solution for trivia puzzle", "solver.trivia"); + + this.parameters.put("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box", new AColor(0,255,0,50), "acolor")); + } + + public AColor getTargetColor() { + return this.<AColor>getParameter("targetColor").getValue(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverRiddle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverRiddle.java new file mode 100644 index 00000000..23bc5a0c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverRiddle.java @@ -0,0 +1,35 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.solvers; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +public class FeatureSolverRiddle extends SimpleFeature { + public FeatureSolverRiddle() { + super("Solver.Any Floor", "Riddle", "Highlights the correct box after clicking on all 3 weirdos", "solver.riddle"); + + this.parameters.put("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box", new AColor(0,255,0,50), "acolor")); + } + + public AColor getTargetColor() { + return this.<AColor>getParameter("targetColor").getValue(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverSilverfish.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverSilverfish.java new file mode 100644 index 00000000..31a4d0e6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverSilverfish.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.solvers; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +import java.util.LinkedHashMap; + +public class FeatureSolverSilverfish extends SimpleFeature { + public FeatureSolverSilverfish() { + super("Solver.Floor 3+", "Silverfish (Advanced)", "Actively calculates solution for silverfish puzzle and displays it to user", "solver.silverfish"); + this.parameters = new LinkedHashMap<>(); + this.parameters.put("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the solution line", new AColor(0xFF00FF00, true), "acolor")); + this.parameters.put("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the solution line",1.0f, "float")); + } + public AColor getLineColor() { + return this.<AColor>getParameter("lineColor").getValue(); + } + public float getLineWidth() { + return this.<Float>getParameter("lineWidth").getValue(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverTeleport.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverTeleport.java new file mode 100644 index 00000000..c7e42516 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverTeleport.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.solvers; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +public class FeatureSolverTeleport extends SimpleFeature { + public FeatureSolverTeleport() { + super("Solver.Any Floor", "Teleport", "Shows teleport pads you've visited in a teleport maze room", "solver.teleport"); + + this.parameters.put("targetColor", new FeatureParameter<AColor>("targetColor", "Solution Color", "Color of the solution teleport pad", new AColor(0,255,0,100), "acolor")); + this.parameters.put("targetColor2", new FeatureParameter<AColor>("targetColor2", "Not-Solution Color", "Color of the solution teleport pads you've been to", new AColor(255,0,0,100), "acolor")); + } + + public AColor getTargetColor() { + return this.<AColor>getParameter("targetColor").getValue(); + } + public AColor getTargetColor2() { + return this.<AColor>getParameter("targetColor2").getValue(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverTictactoe.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverTictactoe.java new file mode 100644 index 00000000..68ca4cb5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/impl/solvers/FeatureSolverTictactoe.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.impl.solvers; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; + +public class FeatureSolverTictactoe extends SimpleFeature { + public FeatureSolverTictactoe() { + super("Solver.Any Floor", "Tictactoe", "Shows the best move that could be taken by player in the tictactoe room", "solver.tictactoe"); + + this.parameters.put("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box during your turn", new AColor(0,255,255,50), "acolor")); + this.parameters.put("targetColor2", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box during enemy turn", new AColor(255,201,0,50), "acolor")); + } + + public AColor getTargetColor() { + return this.<AColor>getParameter("targetColor").getValue(); + } + public AColor getTargetColor2() { + return this.<AColor>getParameter("targetColor2").getValue(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/BossroomEnterListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/BossroomEnterListener.java new file mode 100644 index 00000000..bb1934b0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/BossroomEnterListener.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +public interface BossroomEnterListener { + void onBossroomEnter(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/ChatListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/ChatListener.java new file mode 100644 index 00000000..88d8cd2b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/ChatListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +public interface ChatListener { + void onChat(ClientChatReceivedEvent clientChatReceivedEvent); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/ChatListenerGlobal.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/ChatListenerGlobal.java new file mode 100644 index 00000000..4f8f61de --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/ChatListenerGlobal.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.ClientChatReceivedEvent; + +public interface ChatListenerGlobal { + void onChat(ClientChatReceivedEvent clientChatReceivedEvent); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserJoinRequestListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserJoinRequestListener.java new file mode 100644 index 00000000..99793f69 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserJoinRequestListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import kr.syeyoung.dungeonsguide.events.DiscordUserJoinRequestEvent; + +public interface DiscordUserJoinRequestListener { + void onDiscordUserJoinRequest(DiscordUserJoinRequestEvent event); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserUpdateListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserUpdateListener.java new file mode 100644 index 00000000..d376a21d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserUpdateListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import kr.syeyoung.dungeonsguide.events.DiscordUserUpdateEvent; + +public interface DiscordUserUpdateListener { + void onDiscordUserUpdate(DiscordUserUpdateEvent event); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonContextInitializationListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonContextInitializationListener.java new file mode 100644 index 00000000..53cea3c3 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonContextInitializationListener.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +public interface DungeonContextInitializationListener { + void onDungeonInitialize(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonEndListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonEndListener.java new file mode 100644 index 00000000..ba8ba263 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonEndListener.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +public interface DungeonEndListener { + void onDungeonEnd(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonQuitListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonQuitListener.java new file mode 100644 index 00000000..120d773e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonQuitListener.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +public interface DungeonQuitListener { + void onDungeonQuit(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonStartListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonStartListener.java new file mode 100644 index 00000000..d7497c63 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DungeonStartListener.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +public interface DungeonStartListener { + void onDungeonStart(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/EntityLivingRenderListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/EntityLivingRenderListener.java new file mode 100644 index 00000000..7b982a7f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/EntityLivingRenderListener.java @@ -0,0 +1,26 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.RenderLivingEvent; + +public interface EntityLivingRenderListener { + void onEntityRenderPre(RenderLivingEvent.Pre renderPlayerEvent); + void onEntityRenderPost(RenderLivingEvent.Post renderPlayerEvent); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiBackgroundRenderListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiBackgroundRenderListener.java new file mode 100644 index 00000000..03e525bc --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiBackgroundRenderListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.GuiScreenEvent; + +public interface GuiBackgroundRenderListener { + void onGuiBGRender(GuiScreenEvent.BackgroundDrawnEvent rendered); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiClickListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiClickListener.java new file mode 100644 index 00000000..f860e39f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiClickListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.GuiScreenEvent; + +public interface GuiClickListener { + void onMouseInput(GuiScreenEvent.MouseInputEvent.Pre mouseInputEvent); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiOpenListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiOpenListener.java new file mode 100644 index 00000000..a28ea7a6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiOpenListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.GuiOpenEvent; + +public interface GuiOpenListener { + void onGuiOpen(GuiOpenEvent event); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiPostRenderListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiPostRenderListener.java new file mode 100644 index 00000000..c6c66f99 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiPostRenderListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.GuiScreenEvent; + +public interface GuiPostRenderListener { + void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiPreRenderListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiPreRenderListener.java new file mode 100644 index 00000000..08a44009 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiPreRenderListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.GuiScreenEvent; + +public interface GuiPreRenderListener { + void onGuiPreRender(GuiScreenEvent.DrawScreenEvent.Pre rendered); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiUpdateListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiUpdateListener.java new file mode 100644 index 00000000..2e6389f0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/GuiUpdateListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import kr.syeyoung.dungeonsguide.events.WindowUpdateEvent; + +public interface GuiUpdateListener { + void onGuiUpdate(WindowUpdateEvent windowUpdateEvent); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/InteractListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/InteractListener.java new file mode 100644 index 00000000..4b2fac80 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/InteractListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +public interface InteractListener { + void onInteract(PlayerInteractEvent event); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/KeyInputListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/KeyInputListener.java new file mode 100644 index 00000000..80ec57d8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/KeyInputListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.GuiScreenEvent; + +public interface KeyInputListener { + void onKeyInput(GuiScreenEvent.KeyboardInputEvent keyboardInputEvent); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/KeybindPressedListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/KeybindPressedListener.java new file mode 100644 index 00000000..3d67e326 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/KeybindPressedListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import kr.syeyoung.dungeonsguide.events.KeyBindPressedEvent; + +public interface KeybindPressedListener { + void onKeybindPress(KeyBindPressedEvent keyBindPressedEvent); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/PlayerRenderListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/PlayerRenderListener.java new file mode 100644 index 00000000..33c91fb8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/PlayerRenderListener.java @@ -0,0 +1,26 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.RenderPlayerEvent; + +public interface PlayerRenderListener { + void onEntityRenderPre(RenderPlayerEvent.Pre renderPlayerEvent ); + void onEntityRenderPost(RenderPlayerEvent.Post renderPlayerEvent ); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/ScreenRenderListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/ScreenRenderListener.java new file mode 100644 index 00000000..0f8fec79 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/ScreenRenderListener.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +public interface ScreenRenderListener { + void drawScreen(float partialTicks); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/SkyblockJoinListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/SkyblockJoinListener.java new file mode 100644 index 00000000..67a44f6b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/SkyblockJoinListener.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +public interface SkyblockJoinListener { + void onSkyblockJoin(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/SkyblockLeaveListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/SkyblockLeaveListener.java new file mode 100644 index 00000000..b38c0b75 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/SkyblockLeaveListener.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +public interface SkyblockLeaveListener { + void onSkyblockQuit(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/SoundListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/SoundListener.java new file mode 100644 index 00000000..1b8da9c4 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/SoundListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.sound.PlaySoundEvent; + +public interface SoundListener { + void onSound(PlaySoundEvent playSoundEvent); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/StompConnectedListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/StompConnectedListener.java new file mode 100644 index 00000000..e52d0642 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/StompConnectedListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import kr.syeyoung.dungeonsguide.events.StompConnectedEvent; + +public interface StompConnectedListener { + void onStompConnected(StompConnectedEvent event); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TextureStichListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TextureStichListener.java new file mode 100644 index 00000000..8ecb2315 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TextureStichListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.client.event.TextureStitchEvent; + +public interface TextureStichListener { + void onTextureStitch(TextureStitchEvent event); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TickListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TickListener.java new file mode 100644 index 00000000..cd3a21a5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TickListener.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +public interface TickListener { + void onTick(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TitleListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TitleListener.java new file mode 100644 index 00000000..ac3e5f48 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TitleListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraft.network.play.server.S45PacketTitle; + +public interface TitleListener { + void onTitle(S45PacketTitle renderPlayerEvent); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TooltipListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TooltipListener.java new file mode 100644 index 00000000..5bb78da0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/TooltipListener.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +import net.minecraftforge.event.entity.player.ItemTooltipEvent; + +public interface TooltipListener { + void onTooltip(ItemTooltipEvent event); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/WorldRenderListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/WorldRenderListener.java new file mode 100644 index 00000000..ee4aeb5c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/listener/WorldRenderListener.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.listener; + +public interface WorldRenderListener { + void drawWorld(float partialTicks); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/PanelTextParameterConfig.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/PanelTextParameterConfig.java new file mode 100644 index 00000000..0ded16a8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/PanelTextParameterConfig.java @@ -0,0 +1,283 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.text; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MEditableAColor; +import kr.syeyoung.dungeonsguide.gui.elements.MPanelScaledGUI; +import kr.syeyoung.dungeonsguide.gui.elements.MScrollablePanel; +import kr.syeyoung.dungeonsguide.gui.elements.MToggleButton; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class PanelTextParameterConfig extends MPanel { + + private final StyledTextProvider feature; + + private final MEditableAColor currentColor; + private final MEditableAColor backgroundColor; + private final MToggleButton shadow; + + private MScrollablePanel mScrollablePanel; + private MPanelScaledGUI rendering; + + @Override + public void onBoundsUpdate() { + } + @Override + public Dimension getPreferredSize() { + return new Dimension(400, getPanelBound().height + 20); + } + + public PanelTextParameterConfig(final StyledTextProvider feature) { + this.feature = feature; + setBackgroundColor(new Color(38, 38, 38, 255)); + + currentColor = new MEditableAColor(); + currentColor.setColor(new AColor(0xff555555, true)); + currentColor.setEnableEdit(false); + currentColor.setSize(new Dimension(15, 10)); + currentColor.setOnUpdate(new Runnable() { + @Override + public void run() { + for (String se:selected) + feature.getStylesMap().get(se).setColor(currentColor.getColor()); + } + }); + add(currentColor); + backgroundColor = new MEditableAColor(); + backgroundColor.setColor(new AColor(0xff555555, true)); + backgroundColor.setEnableEdit(false); + backgroundColor.setSize(new Dimension(15, 10)); + backgroundColor.setOnUpdate(new Runnable() { + @Override + public void run() { + for (String se:selected) + feature.getStylesMap().get(se).setBackground(backgroundColor.getColor()); + } + }); + add(backgroundColor); + shadow = new MToggleButton(); + shadow.setSize(new Dimension(20, 10)); + shadow.setOnToggle(new Runnable() { + @Override + public void run() { + for (String se:selected) + feature.getStylesMap().get(se).setShadow(shadow.isEnabled()); + } + }); + add(shadow); + + mScrollablePanel = new MScrollablePanel(3); + mScrollablePanel.setHideScrollBarWhenNotNecessary(true); + add(mScrollablePanel); + + mScrollablePanel.add(rendering = new MPanelScaledGUI() { + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + super.render(absMousex, absMousey, relMousex0, relMousey0, partialTicks, scissor); + + List<StyledText> texts = feature.getDummyText(); + Map<String, TextStyle> styles = feature.getStylesMap(); + List<StyledTextRenderer.StyleTextAssociated> calc = StyledTextRenderer.drawTextWithStylesAssociated(texts, 0,0, getEffectiveDimension().width, styles, StyledTextRenderer.Alignment.LEFT); + boolean bool =scissor.contains(absMousex, absMousey); + for (StyledTextRenderer.StyleTextAssociated calc3: calc) { + if (selected.contains(calc3.getStyledText().getGroup())) { + Gui.drawRect(calc3.getRectangle().x, calc3.getRectangle().y, calc3.getRectangle().x + calc3.getRectangle().width, calc3.getRectangle().y + calc3.getRectangle().height, 0x4244A800); + } else if (bool && calc3.getRectangle().contains(relMousex0, relMousey0)) { + for (StyledTextRenderer.StyleTextAssociated calc2 : calc) { + if (calc2.getStyledText().getGroup().equals(calc3.getStyledText().getGroup())) + Gui.drawRect(calc2.getRectangle().x, calc2.getRectangle().y, calc2.getRectangle().x + calc2.getRectangle().width, calc2.getRectangle().y + calc2.getRectangle().height, 0x55777777); + } + } + } + } + + + private int lastX; + private int lastY; + private boolean dragStart = false; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + List<StyledText> texts = feature.getDummyText(); + Map<String, TextStyle> styles = feature.getStylesMap(); + boolean existed = selected.isEmpty(); + boolean found = false; + List<StyledTextRenderer.StyleTextAssociated> calc = StyledTextRenderer.calculate(texts, 0,0, styles); + for (StyledTextRenderer.StyleTextAssociated calc3: calc) { + if (calc3.getRectangle().contains(relMouseX, relMouseY)) { + if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { + if (!selected.contains(calc3.getStyledText().getGroup())) + selected.add(calc3.getStyledText().getGroup()); + else + selected.remove(calc3.getStyledText().getGroup()); + } else { + selected.clear(); + selected.add(calc3.getStyledText().getGroup()); + } + found = true; + } + } + + if (!found && !(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) && parent.getLastAbsClip().contains(absMouseX * getScale(), absMouseY* getScale())) { + selected.clear(); + dragStart = true; + lastX = absMouseX; + lastY = absMouseY; + } + currentColor.setEnableEdit(selected.size() != 0); + PanelTextParameterConfig.this.backgroundColor.setEnableEdit(selected.size() != 0); + if (existed != selected.isEmpty()) { + if (selected.size() != 0) { + currentColor.setColor(styles.get(selected.iterator().next()).getColor()); + PanelTextParameterConfig.this.backgroundColor.setColor(styles.get(selected.iterator().next()).getBackground()); + shadow.setEnabled(styles.get(selected.iterator().next()).isShadow()); + } else { + currentColor.setColor(new AColor(0xff555555, true)); + PanelTextParameterConfig.this.backgroundColor.setColor(new AColor(0xff555555, true)); + shadow.setEnabled(false); + } + } + + if (selected.size() == 1) { + currentColor.setColor(styles.get(selected.iterator().next()).getColor()); + PanelTextParameterConfig.this.backgroundColor.setColor(styles.get(selected.iterator().next()).getBackground()); + shadow.setEnabled(styles.get(selected.iterator().next()).isShadow()); + } + } + + @Override + public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) { + dragStart = false; + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + if (dragStart) { + int dx= absMouseX - lastX; + int dy= absMouseY - lastY; + int actualOFFX = (int) (dx / getScale()); + int actualOFFY = (int) (dy / getScale()); + lastX =(int) (actualOFFX * getScale())+lastX; + lastY =(int) (actualOFFY * getScale())+lastY; + mScrollablePanel.getScrollBarX().addToCurrent(-actualOFFX); + mScrollablePanel.getScrollBarY().addToCurrent(-actualOFFY); + } + } + + @Override + public Dimension getPreferredSize() { + List<StyledTextRenderer.StyleTextAssociated> calc = StyledTextRenderer.calculate(feature.getDummyText(), 0,0, feature.getStylesMap()); + int w = 0, h = 0; + for (StyledTextRenderer.StyleTextAssociated styleTextAssociated : calc) { + int endX = styleTextAssociated.getRectangle().x + styleTextAssociated.getRectangle().width; + int endY = styleTextAssociated.getRectangle().y + styleTextAssociated.getRectangle().height; + if (endX > w) w = endX; + if (endY > h) h = endY; + } + return new Dimension((int) (w * getScale()),(int) (h * getScale())); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(new Point(0,0), getPreferredSize())); + } + + + @Override + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if ( parent.getLastAbsClip().contains(absMouseX * getScale(), absMouseY* getScale())) { + double scale = rendering.getScale(); + if (scrollAmount > 0) { + scale += 0.1; + } else if (scrollAmount < 0) { + scale -= 0.1; + } + if (scale < 0.1) scale = 0.1f; + if (scale > 5) scale = 5.0f; + rendering.setScale(scale); + mScrollablePanel.setBounds(new Rectangle(new Point(5,5),getPanelBound())); + } + } + }); + + + } + + private final Set<String> selected = new HashSet<String>(); + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + + GlStateManager.pushMatrix(); + + Dimension dim = getPanelBound(); + int width = dim.width, height = dim.height; + Gui.drawRect(0,0,getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.12f)); + Gui.drawRect(4,4,width+6, height+6, 0xFF222222); + Gui.drawRect(5,5,width+5, height+5, RenderUtils.blendAlpha(0x141414, 0.15f)); + + + GlStateManager.translate(5, height + 7, 0); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Press Shift to multi-select", 0, 0, 0xFFBFBFBF); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + GlStateManager.translate(width + 15, 5, 0); + GlStateManager.pushMatrix(); + fr.drawString("Selected Groups: "+selected, 0, 0, 0xFFBFBFBF); + GlStateManager.popMatrix(); + fr.drawString("Text Color: ", 0, 10, 0xFFFFFFFF); + fr.drawString("Background Color: ", 0, 20, 0xFFFFFFFF); + fr.drawString("Shadow: ", 0, 39, 0xFFFFFFFF); + + GlStateManager.popMatrix(); + } + + private Dimension getPanelBound(){ +// return new Dimension((getBounds().width-25)/2, 100); + return new Dimension(150,100); + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + + Dimension dim = getPanelBound(); + currentColor.setBounds(new Rectangle(75+dim.width , 14, 15, 10)); + backgroundColor.setBounds(new Rectangle(110+dim.width , 24, 15, 10)); + shadow.setBounds(new Rectangle(75+dim.width , 43, 30, 10)); + mScrollablePanel.setBounds(new Rectangle(5,5,dim.width,dim.height)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/StyledText.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/StyledText.java new file mode 100644 index 00000000..074243b9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/StyledText.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.text; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class StyledText { + private String text; + private String group; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/StyledTextProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/StyledTextProvider.java new file mode 100644 index 00000000..2b68e4a3 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/StyledTextProvider.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.text; + +import java.util.List; +import java.util.Map; + +public interface StyledTextProvider { + List<StyledText> getDummyText(); + List<StyledText> getText(); + + List<TextStyle> getStyles(); + Map<String, TextStyle> getStylesMap(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/StyledTextRenderer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/StyledTextRenderer.java new file mode 100644 index 00000000..ed6cb2da --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/StyledTextRenderer.java @@ -0,0 +1,244 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.text; + +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraftforge.fml.relauncher.ReflectionHelper; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class StyledTextRenderer { + + public static enum Alignment { + LEFT, CENTER, RIGHT + } + + private static final Method renderChar = ReflectionHelper.findMethod(FontRenderer.class, null, new String[] {"renderChar", "func_181559_a"}, char.class, boolean.class); + private static final Method doDraw = ReflectionHelper.findMethod(FontRenderer.class, null, new String[] {"doDraw"}, float.class); + private static final Field posX = ReflectionHelper.findField(FontRenderer.class, "posX", "field_78295_j"); + private static final Field posY = ReflectionHelper.findField(FontRenderer.class, "posY", "field_78296_k"); + + + public static List<StyleTextAssociated> drawTextWithStylesAssociated(List<StyledText> texts, int x, int y,int width, Map<String, TextStyle> styleMap, Alignment alignment) { + String[] totalLines = (texts.stream().map( a-> a.getText()).collect(Collectors.joining())+" ").split("\n"); + + + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + + int currentLine = 0; + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int currX = alignment == Alignment.LEFT ? x : alignment == Alignment.CENTER ? (x+width-fr.getStringWidth(totalLines[currentLine]))/2 : (x+width-fr.getStringWidth(totalLines[currentLine])); + int currY = y; + int maxHeightForLine = 0; + List<StyleTextAssociated> associateds = new ArrayList<StyleTextAssociated>(); + for (StyledText st : texts) { + TextStyle ts = styleMap.get(st.getGroup()); + String[] lines = st.getText().split("\n"); + for (int i = 0; i < lines.length; i++) { + String str = lines[i]; + Dimension d = null; + try { + d = drawFragmentText(fr, str, ts, currX, currY, false); + } catch (InvocationTargetException | IllegalAccessException e) { + e.printStackTrace(); + } + associateds.add(new StyleTextAssociated(st, new Rectangle(currX, currY, d.width, d.height))); + currX += d.width; + if (maxHeightForLine < d.height) + maxHeightForLine = d.height; + + if (i+1 != lines.length) { + currY += maxHeightForLine ; + currentLine++; + currX = alignment == Alignment.LEFT ? x : alignment == Alignment.CENTER ? (x+width-fr.getStringWidth(totalLines[currentLine]))/2 : (x+width-fr.getStringWidth(totalLines[currentLine])); + maxHeightForLine = 0; + } + } + if (st.getText().endsWith("\n")) { + currY += maxHeightForLine; + currentLine++; + currX = alignment == Alignment.LEFT ? x : alignment == Alignment.CENTER ? (x+width-fr.getStringWidth(totalLines[currentLine]))/2 : (x+width-fr.getStringWidth(totalLines[currentLine])); + maxHeightForLine = 0; + } + } + return associateds; + } + + public static List<StyleTextAssociated> calculate(List<StyledText> texts, int x, int y, Map<String, TextStyle> styleMap) { + int currX = x; + int currY = y; + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int maxHeightForLine = 0; + List<StyleTextAssociated> associateds = new ArrayList<StyleTextAssociated>(); + for (StyledText st : texts) { + TextStyle ts = styleMap.get(st.getGroup()); + String[] lines = st.getText().split("\n"); + for (int i = 0; i < lines.length; i++) { + String str = lines[i]; + Dimension d = null; + try { + d = drawFragmentText(fr, str, ts, currX, currY, true); + } catch (InvocationTargetException | IllegalAccessException e) { + e.printStackTrace(); + } + associateds.add(new StyleTextAssociated(st, new Rectangle(currX, currY, d.width, d.height))); + currX += d.width; + if (maxHeightForLine < d.height) + maxHeightForLine = d.height; + + if (i+1 != lines.length) { + currY += maxHeightForLine; + currX = x; + maxHeightForLine = 0; + } + } + if (st.getText().endsWith("\n")) { + currY += maxHeightForLine; + currX = x; + maxHeightForLine = 0; + } + } + return associateds; + } + + @Data + @AllArgsConstructor + public static class StyleTextAssociated { + private StyledText styledText; + private Rectangle rectangle; + } + + private static Dimension drawFragmentText(FontRenderer fr, String content, TextStyle style, int x, int y, boolean stopDraw) throws InvocationTargetException, IllegalAccessException { + if (stopDraw) + return new Dimension(fr.getStringWidth(content), fr.FONT_HEIGHT); + + int bgColor = RenderUtils.getColorAt(x,y, style.getBackground()); + if ((bgColor & 0xFF000000) != 0) + Gui.drawRect(x,y, x+fr.getStringWidth(content), y + fr.FONT_HEIGHT, bgColor); + + + posX.set(fr, x+1); + posY.set(fr, y+1); + + if (style.isShadow()) { + char[] charArr = content.toCharArray(); + float width = 0; + for (int i = 0; i < charArr.length; i++) { + int color = RenderUtils.getColorAt(x + width, y, style.getColor()); + color = (color & 16579836) >> 2 | color & -16777216; + + width +=renderChar(fr, charArr[i], color,true, false, false, false); + } + } + posX.set(fr, x); + posY.set(fr, y); + { + char[] charArr = content.toCharArray(); + float width = 0; + for (int i = 0; i < charArr.length; i++) { + int color = RenderUtils.getColorAt(x + width, y, style.getColor()); + + width +=renderChar(fr, charArr[i], color, false, false, false, false); + } + return new Dimension((int) width, fr.FONT_HEIGHT); + } + } + + private static float renderChar(FontRenderer fr, char character, int color, boolean shadow, boolean randomStyle, boolean boldStyle, boolean italicStyle) throws InvocationTargetException, IllegalAccessException { + RenderUtils.GL_SETCOLOR(color); + int j = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000".indexOf(character); + + if (randomStyle && j != -1) + { + int k = fr.getCharWidth(character); + char c1; + + while (true) + { + j = fr.fontRandom.nextInt("\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000".length()); + c1 = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000".charAt(j); + + if (k == fr.getCharWidth(c1)) + { + break; + } + } + + character = c1; + } + + float f1 = j == -1 || fr.getUnicodeFlag() ? 0.5f : 1f; + boolean flag = (character == 0 || j == -1 || fr.getUnicodeFlag()) && shadow; + + if (flag) + { + posX.set(fr,(float) posX.get(fr) - f1); + posY.set(fr,(float) posY.get(fr) - f1); + } + + float f = (float) renderChar.invoke(fr, character, italicStyle); + + if (flag) + { + posX.set(fr,(float) posX.get(fr) + f1); + posY.set(fr,(float) posY.get(fr) + f1); + } + + if (boldStyle) + { + posX.set(fr,(float) posX.get(fr) + f1); + + if (flag) + { + posX.set(fr,(float) posX.get(fr) - f1); + posY.set(fr,(float) posY.get(fr) - f1); + } + + renderChar.invoke(fr, character, italicStyle); + posX.set(fr,(float) posX.get(fr) - f1); + + if (flag) + { + posX.set(fr,(float) posX.get(fr) + f1); + posY.set(fr,(float) posY.get(fr) + f1); + } + + ++f; + } + doDraw.invoke(fr, f); + + return f; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/TextHUDFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/TextHUDFeature.java new file mode 100644 index 00000000..5b709904 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/TextHUDFeature.java @@ -0,0 +1,191 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.text; + +import com.google.common.base.Supplier; +import com.google.gson.JsonObject; +import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator; +import kr.syeyoung.dungeonsguide.gui.elements.MStringSelectionButton; +import kr.syeyoung.dungeonsguide.config.guiconfig.MFeatureEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.MParameterEdit; +import kr.syeyoung.dungeonsguide.config.guiconfig.RootConfigPanel; +import kr.syeyoung.dungeonsguide.config.guiconfig.location.GuiGuiLocationConfig; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.GuiFeature; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MFloatSelectionButton; +import kr.syeyoung.dungeonsguide.gui.elements.MPassiveLabelAndElement; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; + +import java.util.*; +import java.util.List; + +public abstract class TextHUDFeature extends GuiFeature implements StyledTextProvider { + protected TextHUDFeature(String category, String name, String description, String key, boolean keepRatio, int width, int height) { + super(category, name, description, key, keepRatio, width, height); + this.parameters.put("textStylesNEW", new FeatureParameter<List<TextStyle>>("textStylesNEW", "", "", new ArrayList<TextStyle>(), "list_textStyle")); + this.parameters.put("alignment", new FeatureParameter<String>("alignment", "Alignment", "Alignment", "LEFT", "string")); + this.parameters.put("scale", new FeatureParameter<Float>("scale", "Scale", "Scale", 1.0f, "float")); + } + + @Override + public void drawHUD(float partialTicks) { + if (isHUDViewable()) { + List<StyledText> asd = getText(); + + double scale = 1; + if (doesScaleWithHeight()) { + FontRenderer fr = getFontRenderer(); + scale = getFeatureRect().getRectangle().getHeight() / (fr.FONT_HEIGHT* countLines(asd)); + } else { + scale = this.<Float>getParameter("scale").getValue(); + } + GlStateManager.scale(scale, scale, 0); + StyledTextRenderer.drawTextWithStylesAssociated(asd, 0, 0, (int) (Math.abs(getFeatureRect().getWidth())/scale), getStylesMap(), + StyledTextRenderer.Alignment.valueOf(TextHUDFeature.this.<String>getParameter("alignment").getValue())); + } + } + + public boolean doesScaleWithHeight() { + return true; + } + + @Override + public void drawDemo(float partialTicks) { + List<StyledText> asd = getDummyText(); + double scale = 1; + if (doesScaleWithHeight()) { + FontRenderer fr = getFontRenderer(); + scale = getFeatureRect().getRectangle().getHeight() / (fr.FONT_HEIGHT* countLines(asd)); + } else { + scale = this.<Float>getParameter("scale").getValue(); + } + GlStateManager.scale(scale, scale, 0); + + StyledTextRenderer.drawTextWithStylesAssociated(asd, 0, 0, (int) (Math.abs(getFeatureRect().getWidth())/scale), getStylesMap(), + StyledTextRenderer.Alignment.valueOf(TextHUDFeature.this.<String>getParameter("alignment").getValue())); + } + + public int countLines(List<StyledText> texts) { + StringBuilder things = new StringBuilder(); + for (StyledText text : texts) { + things.append(text.getText()); + } + String things2 = things.toString().trim(); + int lines = 1; + for (char c : things2.toCharArray()) { + if (c == '\n') lines++; + } + return lines; + } + + public abstract boolean isHUDViewable(); + + public abstract List<String> getUsedTextStyle(); + public List<StyledText> getDummyText() { + return getText(); + } + public abstract List<StyledText> getText(); + + public List<TextStyle> getStyles() { + return this.<List<TextStyle>>getParameter("textStylesNEW").getValue(); + } + private Map<String, TextStyle> stylesMap; + public Map<String, TextStyle> getStylesMap() { + if (stylesMap == null) { + List<TextStyle> styles = getStyles(); + Map<String, TextStyle> res = new HashMap<String, TextStyle>(); + for (TextStyle ts : styles) { + res.put(ts.getGroupName(), ts); + } + for (String str : getUsedTextStyle()) { + if (!res.containsKey(str)) + res.put(str, new TextStyle(str, new AColor(0xffffffff, true), new AColor(0x00777777, true), false)); + } + stylesMap = res; + } + return stylesMap; + } + + + @Override + public String getEditRoute(RootConfigPanel rootConfigPanel) { + ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() { + @Override + public MPanel get() { + + MFeatureEdit featureEdit = new MFeatureEdit(TextHUDFeature.this, rootConfigPanel); + featureEdit.addParameterEdit("textStyleNEW", new PanelTextParameterConfig(TextHUDFeature.this)); + + StyledTextRenderer.Alignment alignment = StyledTextRenderer.Alignment.valueOf(TextHUDFeature.this.<String>getParameter("alignment").getValue()); + MStringSelectionButton mStringSelectionButton = new MStringSelectionButton(Arrays.asList("LEFT", "CENTER", "RIGHT"), alignment.name()); + mStringSelectionButton.setOnUpdate(() -> { + TextHUDFeature.this.<String>getParameter("alignment").setValue(mStringSelectionButton.getSelected()); + }); + featureEdit.addParameterEdit("alignment", new MParameterEdit(TextHUDFeature.this, TextHUDFeature.this.<String>getParameter("alignment"), rootConfigPanel, mStringSelectionButton, (a) -> false)); + + for (FeatureParameter parameter: getParameters()) { + if (parameter.getKey().equals("textStylesNEW")) continue; + if (parameter.getKey().equals("alignment")) continue; + featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(TextHUDFeature.this, parameter, rootConfigPanel)); + } + return featureEdit; + } + }); + return "base." + getKey() ; + } + + @Override + public List<MPanel> getTooltipForEditor(GuiGuiLocationConfig guiGuiLocationConfig) { + List<MPanel> mPanels = super.getTooltipForEditor(guiGuiLocationConfig); + StyledTextRenderer.Alignment alignment = StyledTextRenderer.Alignment.valueOf(this.<String>getParameter("alignment").getValue()); + MStringSelectionButton mStringSelectionButton = new MStringSelectionButton(Arrays.asList("LEFT", "CENTER", "RIGHT"), alignment.name()); + mStringSelectionButton.setOnUpdate(() -> { + TextHUDFeature.this.<String>getParameter("alignment").setValue(mStringSelectionButton.getSelected()); + }); + + mPanels.add(new MPassiveLabelAndElement("Alignment", mStringSelectionButton)); + if (!doesScaleWithHeight()) { + mPanels.add(new MPassiveLabelAndElement("Scale", new MFloatSelectionButton(TextHUDFeature.this.<Float>getParameter("scale").getValue()) {{ + setOnUpdate(() ->{ + TextHUDFeature.this.<Float>getParameter("scale").setValue(this.getData()); + }); } + })); + } + + return mPanels; + } + + @Override + public void onParameterReset() { + stylesMap = null; + } + + @Override + public void loadConfig(JsonObject jsonObject) { + super.loadConfig(jsonObject); + StyledTextRenderer.Alignment alignment; + try { + alignment = StyledTextRenderer.Alignment.valueOf(TextHUDFeature.this.<String>getParameter("alignment").getValue()); + } catch (Exception e) {alignment = StyledTextRenderer.Alignment.LEFT;} + TextHUDFeature.this.<String>getParameter("alignment").setValue(alignment.name()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/TextStyle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/TextStyle.java new file mode 100644 index 00000000..4bf87649 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/features/text/TextStyle.java @@ -0,0 +1,34 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.features.text; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class TextStyle { + private String groupName; + private AColor color; + private AColor background; + private boolean shadow = false; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/GameSDK.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/GameSDK.java new file mode 100644 index 00000000..1a2f519e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/GameSDK.java @@ -0,0 +1,87 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Platform; +import kr.syeyoung.dungeonsguide.gamesdk.jna.GameSDKTypeMapper; +import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK; +import lombok.Getter; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.Collections; + +public class GameSDK { + @Getter + private static NativeGameSDK nativeGameSDK; + + static { + try { + if (System.getProperty("dg.safe") == null) extractLibrary(); + } catch (IOException e) { + e.printStackTrace(); + } + } + public static void extractLibrary() throws IOException { + String libName = System.mapLibraryName("discord_game_sdk"); + String dir = ""; + switch(Platform.getOSType()) { + case Platform.MAC: + dir = "darwin"; + break; + case Platform.LINUX: + dir = "linux"; + break; + case Platform.WINDOWS: + if (Platform.is64Bit()) dir = "win-x64"; + else dir = "win-x86"; + break; + default: + throw new IllegalStateException("Unsupported OS Type"); + } + + String resourceLoc = "/gamesdk/"+dir+"/"+libName; + File targetExtractionPath = new File("native/"+libName); + targetExtractionPath.getParentFile().mkdirs(); + try (InputStream is = GameSDK.class.getResourceAsStream(resourceLoc)) { + Files.copy(is, targetExtractionPath.toPath(), StandardCopyOption.REPLACE_EXISTING); + targetExtractionPath.deleteOnExit(); + } + + nativeGameSDK = (NativeGameSDK) Native.loadLibrary(targetExtractionPath.getAbsolutePath(), NativeGameSDK.class, + Collections.singletonMap(Library.OPTION_TYPE_MAPPER, GameSDKTypeMapper.INSTANCE)); + } + + public static void writeString(byte[] bts, String str) { + System.arraycopy(str.getBytes(), 0, bts, 0, str.getBytes().length); + bts[str.getBytes().length] = 0; + } + public static String readString(byte[] bts) { + int i; + for (i = 0; i < bts.length && bts[i] != 0; i++); + byte[] asdasd = new byte[i]; + System.arraycopy(bts, 0, asdasd, 0, i); + return new String(asdasd); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/GameSDKTypeMapper.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/GameSDKTypeMapper.java new file mode 100644 index 00000000..d9848c55 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/GameSDKTypeMapper.java @@ -0,0 +1,47 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna; + +import com.sun.jna.DefaultTypeMapper; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.*; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.*; + +public class GameSDKTypeMapper extends DefaultTypeMapper { + public static final GameSDKTypeMapper INSTANCE = new GameSDKTypeMapper(); + private GameSDKTypeMapper() { + addTypeConverter(EDiscordResult.class, new EDiscordResult.EDiscordResultTypeConverter()); + addTypeConverter(EDiscordCreateFlags.class, new EDiscordCreateFlags.EDiscordCreateFlagsTypeConverter()); + addTypeConverter(EDiscordLogLevel.class, new EDiscordLogLevel.EDiscordLogLevelTypeConverter()); + addTypeConverter(EDiscordUserFlag.class, new EDiscordUserFlag.EDiscordUserFlagTypeConverter()); + addTypeConverter(EDiscordPremiumType.class, new EDiscordPremiumType.EDiscordPremiumTypeTypeConverter()); + addTypeConverter(EDiscordImageType.class, new EDiscordImageType.EDiscordImageTypeTypeConverter()); + addTypeConverter(EDiscordActivityType.class, new EDiscordActivityType.EDiscordActivityTypeTypeConverter()); + addTypeConverter(EDiscordActivityActionType.class, new EDiscordActivityActionType.EDiscordActivityActionTypeTypeConverter()); + addTypeConverter(EDiscordActivityJoinRequestReply.class, new EDiscordActivityJoinRequestReply.EDiscordActivityJoinRequestReplyTypeConverter()); + addTypeConverter(EDiscordStatus.class, new EDiscordStatus.EDiscordStatusTypeConverter()); + addTypeConverter(EDiscordRelationshipType.class, new EDiscordRelationshipType.EDiscordRelationshipTypeTypeConverter()); + addTypeConverter(EDiscordLobbyType.class, new EDiscordLobbyType.EDiscordLobbyTypeTypeConverter()); + addTypeConverter(EDiscordLobbySearchComparison.class, new EDiscordLobbySearchComparison.EDiscordLobbySearchComparisonTypeConverter()); + addTypeConverter(EDiscordLobbySearchCast.class, new EDiscordLobbySearchCast.EDiscordLobbySearchCastTypeConverter()); + addTypeConverter(EDiscordLobbySearchDistance.class, new EDiscordLobbySearchDistance.EDiscordLobbySearchDistanceTypeConverter()); + addTypeConverter(EDiscordEntitlementType.class, new EDiscordEntitlementType.EDiscordEntitlementTypeTypeConverter()); + addTypeConverter(EDiscordSkuType.class, new EDiscordSkuType.EDiscordSkuTypeTypeConverter()); + addTypeConverter(EDiscordInputModeType.class, new EDiscordInputModeType.EDiscordInputModeTypeTypeConverter()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/NativeGameSDK.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/NativeGameSDK.java new file mode 100644 index 00000000..59fc0339 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/NativeGameSDK.java @@ -0,0 +1,50 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna; + +import com.sun.jna.Callback; +import com.sun.jna.Library; +import com.sun.jna.Pointer; +import com.sun.jna.ptr.PointerByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordCreateParams; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordVersion; + +public interface NativeGameSDK extends Library { + + public static final int DISCORD_VERSION = 2; + public static final int DISCORD_APPLICATION_MANAGER_VERSION = 1; + public static final int DISCORD_USER_MANAGER_VERSION = 1; + public static final int DISCORD_IMAGE_MANAGER_VERSION = 1; + public static final int DISCORD_ACTIVITY_MANAGER_VERSION = 1; + public static final int DISCORD_RELATIONSHIP_MANAGER_VERSION = 1; + public static final int DISCORD_LOBBY_MANAGER_VERSION = 1; + public static final int DISCORD_NETWORK_MANAGER_VERSION = 1; + public static final int DISCORD_OVERLAY_MANAGER_VERSION = 1; + public static final int DISCORD_STORAGE_MANAGER_VERSION = 1; + public static final int DISCORD_STORE_MANAGER_VERSION = 1; + public static final int DISCORD_VOICE_MANAGER_VERSION = 1; + public static final int DISCORD_ACHIEVEMENT_MANAGER_VERSION = 1; + + EDiscordResult DiscordCreate(DiscordVersion version, DiscordCreateParams params, PointerByReference result); // result is double pointer of IDiscordCore + + interface DiscordCallback extends Callback { + void callback(Pointer callbackData, EDiscordResult result); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivity.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivity.java new file mode 100644 index 00000000..71b43431 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivity.java @@ -0,0 +1,50 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityType; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.Int64; + +import java.util.Arrays; +import java.util.List; + + +public class DiscordActivity extends DiscordStruct { + public EDiscordActivityType activityType = EDiscordActivityType.DiscordActivityType_Playing; + public Int64 applicationId = new Int64(); + public byte[] name = new byte[128]; + public byte[] state = new byte[128]; + public byte[] details = new byte[128]; + public DiscordActivityTimestamps timestamps; + public DiscordActivityAssets assets; + public DiscordActivityParty party; + public DiscordActivitySecrets secrets; + public boolean instance; + public DiscordActivity() {super();} public DiscordActivity(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordActivity implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordActivity implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("activityType", "applicationId", "name", "state", "details", "timestamps", "assets", "party", "secrets", "instance"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivityAssets.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivityAssets.java new file mode 100644 index 00000000..03b64f46 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivityAssets.java @@ -0,0 +1,42 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; + +import java.util.Arrays; +import java.util.List; + + +public class DiscordActivityAssets extends DiscordStruct{ + public byte[] large_image = new byte[128]; + public byte[] large_text = new byte[128]; + public byte[] small_image = new byte[128]; + public byte[] small_text = new byte[128]; + public DiscordActivityAssets() {super();}public DiscordActivityAssets(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordActivityAssets implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordActivityAssets implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("large_image", "large_text", "small_image", "small_text"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivityParty.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivityParty.java new file mode 100644 index 00000000..b9a20db3 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivityParty.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; + +import java.util.Arrays; +import java.util.List; + + +public class DiscordActivityParty extends DiscordStruct { + public byte[] id = new byte[128]; + public DiscordPartySize discordActivityParty; + public DiscordActivityParty() {super();} public DiscordActivityParty(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordActivityParty implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordActivityParty implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("id", "discordActivityParty"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivitySecrets.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivitySecrets.java new file mode 100644 index 00000000..2975f97f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivitySecrets.java @@ -0,0 +1,41 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; + +import java.util.Arrays; +import java.util.List; + + +public class DiscordActivitySecrets extends DiscordStruct { + public byte[] match = new byte[128]; + public byte[] join = new byte[128]; + public byte[] spectate = new byte[128]; + public DiscordActivitySecrets() {super();} public DiscordActivitySecrets(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordActivitySecrets implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordActivitySecrets implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("match", "join", "spectate"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivityTimestamps.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivityTimestamps.java new file mode 100644 index 00000000..4765ffb9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordActivityTimestamps.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordTimestamp; + +import java.util.Arrays; +import java.util.List; + +public class DiscordActivityTimestamps extends DiscordStruct { + public DiscordTimestamp start = new DiscordTimestamp(); + public DiscordTimestamp end = new DiscordTimestamp(); + public DiscordActivityTimestamps() {super();} public DiscordActivityTimestamps(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordActivityTimestamps implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordActivityTimestamps implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("start", "end"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordCreateParams.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordCreateParams.java new file mode 100644 index 00000000..0183637e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordCreateParams.java @@ -0,0 +1,73 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct.*; +import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct.*; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordClientID; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordVersion; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt64; + +import java.util.Arrays; +import java.util.List; + +public class DiscordCreateParams extends DiscordStruct { public DiscordCreateParams() {super();} public DiscordCreateParams(Pointer pointer) {super(pointer);} + public DiscordClientID client_id = new DiscordClientID(); + public UInt64 flags = new UInt64(); + public Pointer events; // void* + public Pointer event_data; // void* + public Pointer application_events; + public DiscordVersion application_version = new DiscordVersion(NativeGameSDK.DISCORD_APPLICATION_MANAGER_VERSION); + public IDiscordUserEvents.ByReference user_events; + public DiscordVersion user_version= new DiscordVersion(NativeGameSDK.DISCORD_USER_MANAGER_VERSION); + public Pointer image_events;// void* + public DiscordVersion image_version= new DiscordVersion(NativeGameSDK.DISCORD_IMAGE_MANAGER_VERSION); + public IDiscordActivityEvents.ByReference activity_events; + public DiscordVersion activity_version= new DiscordVersion(NativeGameSDK.DISCORD_ACTIVITY_MANAGER_VERSION); + public IDiscordRelationshipEvents.ByReference relationship_events; + public DiscordVersion relationship_version= new DiscordVersion(NativeGameSDK.DISCORD_RELATIONSHIP_MANAGER_VERSION); + public IDiscordLobbyEvents.ByReference lobby_events; + public DiscordVersion lobby_version= new DiscordVersion(NativeGameSDK.DISCORD_LOBBY_MANAGER_VERSION); + public IDiscordNetworkEvents.ByReference network_events; + public DiscordVersion network_version= new DiscordVersion(NativeGameSDK.DISCORD_NETWORK_MANAGER_VERSION); + public IDiscordOverlayEvents.ByReference overlay_events; + public DiscordVersion overlay_version= new DiscordVersion(NativeGameSDK.DISCORD_OVERLAY_MANAGER_VERSION); + public Pointer storage_events;// void* + public DiscordVersion storage_version= new DiscordVersion(NativeGameSDK.DISCORD_STORAGE_MANAGER_VERSION); + public IDiscordStoreEvents.ByReference store_events; + public DiscordVersion store_version= new DiscordVersion(NativeGameSDK.DISCORD_STORE_MANAGER_VERSION); + public IDiscordVoiceEvents.ByReference voice_events; + public DiscordVersion voice_version= new DiscordVersion(NativeGameSDK.DISCORD_VOICE_MANAGER_VERSION); + public IDiscordAchievementEvents.ByReference achievement_events; + public DiscordVersion achievement_version= new DiscordVersion(NativeGameSDK.DISCORD_ACHIEVEMENT_MANAGER_VERSION); + + public static class ByReference extends DiscordCreateParams implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordCreateParams implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("client_id", "flags", "events", "event_data", "application_events", "application_version", "user_events", + "user_version", "image_events", "image_version", "activity_events", "activity_version", "lobby_events", "lobby_version", + "network_events", "network_version", "overlay_events", "overlay_version", "storage_events", "storage_version", "store_events", + "store_version", "voice_events", "voice_version", "achievement_events", "achievement_version"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordEntitlement.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordEntitlement.java new file mode 100644 index 00000000..6e0f29ac --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordEntitlement.java @@ -0,0 +1,42 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordEntitlementType; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; + +import java.util.Arrays; +import java.util.List; + +public class DiscordEntitlement extends DiscordStruct { + public DiscordSnowflake id = new DiscordSnowflake(); + public EDiscordEntitlementType type = EDiscordEntitlementType.DiscordEntitlementType_Purchase; + public DiscordSnowflake sku_id = new DiscordSnowflake(); + public DiscordEntitlement() {super();} public DiscordEntitlement(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordEntitlement implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordEntitlement implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("id", "type", "sku_id"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordFileStat.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordFileStat.java new file mode 100644 index 00000000..a7e38b37 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordFileStat.java @@ -0,0 +1,42 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; + +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt64; + +import java.util.Arrays; +import java.util.List; + +public class DiscordFileStat extends DiscordStruct { + public byte[] filename = new byte[260]; + public UInt64 size = new UInt64(); + public UInt64 last_modified = new UInt64(); + public DiscordFileStat() {super();} public DiscordFileStat(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordFileStat implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordFileStat implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("filename", "size", "last_modified"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordImageDimensions.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordImageDimensions.java new file mode 100644 index 00000000..d3247b07 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordImageDimensions.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; + +import java.util.Arrays; +import java.util.List; + +public class DiscordImageDimensions extends DiscordStruct { + public UInt32 width = new UInt32(); + public UInt32 height = new UInt32(); + public DiscordImageDimensions() {super();} public DiscordImageDimensions(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordImageDimensions implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) { super(pointer);}} + public static class ByValue extends DiscordImageDimensions implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) { super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("width", "height"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordImageHandle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordImageHandle.java new file mode 100644 index 00000000..2ca33f46 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordImageHandle.java @@ -0,0 +1,43 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordImageType; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.Int64; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; + +import java.util.Arrays; +import java.util.List; + +public class DiscordImageHandle extends DiscordStruct { + public EDiscordImageType type = EDiscordImageType.DiscordImageType_User; + public Int64 id = new Int64(); + public UInt32 size = new UInt32(); + public DiscordImageHandle() {super();} public DiscordImageHandle(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordImageHandle implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordImageHandle implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("type", "id", "size"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordInputMode.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordInputMode.java new file mode 100644 index 00000000..8a69f53a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordInputMode.java @@ -0,0 +1,41 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordInputModeType; + +import java.util.Arrays; +import java.util.List; + + +public class DiscordInputMode extends DiscordStruct { + public EDiscordInputModeType type = EDiscordInputModeType.DiscordInputModeType_PushToTalk; + public byte[] shortcut = new byte[256]; + public DiscordInputMode() {super();} public DiscordInputMode(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordInputMode implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordInputMode implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("type", "shortcut"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordLobby.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordLobby.java new file mode 100644 index 00000000..18453004 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordLobby.java @@ -0,0 +1,47 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordLobbyType; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; + +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; + +import java.util.Arrays; +import java.util.List; + +public class DiscordLobby extends DiscordStruct { + public DiscordSnowflake id = new DiscordSnowflake(); + public EDiscordLobbyType type = EDiscordLobbyType.DiscordLobbyType_Private; + public DiscordSnowflake owner_id = new DiscordSnowflake(); + public byte[] secret = new byte[128]; + public UInt32 capacity = new UInt32(); + public boolean locked; + public DiscordLobby() {super();} public DiscordLobby(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordLobby implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordLobby implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("id", "type", "owner_id", "secret", "capacity", "locked"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordOAuth2Token.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordOAuth2Token.java new file mode 100644 index 00000000..f870f830 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordOAuth2Token.java @@ -0,0 +1,42 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordTimestamp; + +import java.util.Arrays; +import java.util.List; + + +public class DiscordOAuth2Token extends DiscordStruct { + public byte[] access_token = new byte[128]; + public byte[] scopes = new byte[1024]; + public DiscordTimestamp expires = new DiscordTimestamp(); + public DiscordOAuth2Token() {super();} public DiscordOAuth2Token(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordOAuth2Token implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordOAuth2Token implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("access_token", "scopes", "expires"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordPartySize.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordPartySize.java new file mode 100644 index 00000000..43c40723 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordPartySize.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.Int32; + +import java.util.Arrays; +import java.util.List; + +public class DiscordPartySize extends DiscordStruct{ + public Int32 current_size = new Int32(); + public Int32 max_size = new Int32(); + public DiscordPartySize() {super();} public DiscordPartySize(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordPartySize implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordPartySize implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("current_size", "max_size"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordPresence.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordPresence.java new file mode 100644 index 00000000..4e12f175 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordPresence.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordStatus; + +import java.util.Arrays; +import java.util.List; + +public class DiscordPresence extends DiscordStruct { + public EDiscordStatus status = EDiscordStatus.DiscordStatus_Offline; + public DiscordActivity activity; + public DiscordPresence() {super();} public DiscordPresence(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordPresence implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordPresence implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("status", "activity"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordRelationship.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordRelationship.java new file mode 100644 index 00000000..03cbae4a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordRelationship.java @@ -0,0 +1,41 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordRelationshipType; + +import java.util.Arrays; +import java.util.List; + +public class DiscordRelationship extends DiscordStruct { + public EDiscordRelationshipType type = EDiscordRelationshipType.DiscordRelationshipType_None; + public DiscordUser user; + public DiscordPresence presence; + public DiscordRelationship() {super();} public DiscordRelationship(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordRelationship implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordRelationship implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("type", "user", "presence"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordSku.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordSku.java new file mode 100644 index 00000000..2e9aaf1d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordSku.java @@ -0,0 +1,44 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordSkuType; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; + +import java.util.Arrays; +import java.util.List; + + +public class DiscordSku extends DiscordStruct { + public DiscordSnowflake id = new DiscordSnowflake(); + public EDiscordSkuType type = EDiscordSkuType.DiscordSkuType_Application; + public byte[] name = new byte[256]; + public DiscordSkuPrice discordSkuPrice; + public DiscordSku() {super();} public DiscordSku(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordSku implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordSku implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("id", "type", "name", "discordSkuPrice"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordSkuPrice.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordSkuPrice.java new file mode 100644 index 00000000..6eea0924 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordSkuPrice.java @@ -0,0 +1,41 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; + +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; + +import java.util.Arrays; +import java.util.List; + +public class DiscordSkuPrice extends DiscordStruct { + public UInt32 amount = new UInt32(); + public byte[] currency = new byte[16]; + public DiscordSkuPrice() {super();} public DiscordSkuPrice(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordSkuPrice implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordSkuPrice implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("amount", "currency"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordStruct.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordStruct.java new file mode 100644 index 00000000..bd120046 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordStruct.java @@ -0,0 +1,35 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Library; +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.GameSDKTypeMapper; + +import java.util.Collections; +import java.util.Map; + +public abstract class DiscordStruct extends Structure { + public static final Map<String, Object> OPTIONS = Collections.singletonMap(Library.OPTION_TYPE_MAPPER, GameSDKTypeMapper.INSTANCE); + protected DiscordStruct() { + super(GameSDKTypeMapper.INSTANCE); + } + protected DiscordStruct(Pointer p) {super(p); read();} +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordUser.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordUser.java new file mode 100644 index 00000000..bf52860e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordUser.java @@ -0,0 +1,43 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; + +import java.util.Arrays; +import java.util.List; + +public class DiscordUser extends DiscordStruct { + public DiscordSnowflake id = new DiscordSnowflake(); + public byte[] username = new byte[256]; + public byte[] discriminator = new byte[8]; + public byte[] avatar = new byte[128]; + public boolean bot; + public DiscordUser() {super();} public DiscordUser(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordUser implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordUser implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("id", "username", "discriminator", "avatar", "bot"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordUserAchievement.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordUserAchievement.java new file mode 100644 index 00000000..c12dcf56 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordUserAchievement.java @@ -0,0 +1,44 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; + +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; + +import java.util.Arrays; +import java.util.List; + +public class DiscordUserAchievement extends DiscordStruct { + public DiscordSnowflake user_id = new DiscordSnowflake(); + public DiscordSnowflake achievement_id = new DiscordSnowflake(); + public UInt32 percent_complete = new UInt32(); + public byte[] unlocked_at = new byte[64]; + public DiscordUserAchievement() {super();} public DiscordUserAchievement(Pointer pointer) {super(pointer);} + + public static class ByReference extends DiscordUserAchievement implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends DiscordUserAchievement implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override + protected List getFieldOrder() { + return Arrays.asList("user_id", "achievement_id", "percent_complete", "unlocked_at"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordActivityActionType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordActivityActionType.java new file mode 100644 index 00000000..d46fdfc6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordActivityActionType.java @@ -0,0 +1,67 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordActivityActionType { + DiscordActivityActionType_Join(1), + DiscordActivityActionType_Spectate(2); + + @Getter + private final int value; + private EDiscordActivityActionType(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordActivityActionType> valueMap = new HashMap<>(); + static { + for (EDiscordActivityActionType value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordActivityActionType fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordActivityActionTypeTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordActivityActionType.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordActivityActionType)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordActivityJoinRequestReply.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordActivityJoinRequestReply.java new file mode 100644 index 00000000..a8deda60 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordActivityJoinRequestReply.java @@ -0,0 +1,68 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordActivityJoinRequestReply { + DiscordActivityJoinRequestReply_No(0), + DiscordActivityJoinRequestReply_Yes(1), + DiscordActivityJoinRequestReply_Ignore(2); + + @Getter + private final int value; + private EDiscordActivityJoinRequestReply(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordActivityJoinRequestReply> valueMap = new HashMap<>(); + static { + for (EDiscordActivityJoinRequestReply value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordActivityJoinRequestReply fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordActivityJoinRequestReplyTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordActivityJoinRequestReply.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordActivityJoinRequestReply)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordActivityType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordActivityType.java new file mode 100644 index 00000000..9328758a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordActivityType.java @@ -0,0 +1,69 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordActivityType { + DiscordActivityType_Playing(0), + DiscordActivityType_Streaming(1), + DiscordActivityType_Listening(2), + DiscordActivityType_Watching(3); + + @Getter + private final int value; + private EDiscordActivityType(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordActivityType> valueMap = new HashMap<>(); + static { + for (EDiscordActivityType value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordActivityType fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordActivityTypeTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordActivityType.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordActivityType)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordCreateFlags.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordCreateFlags.java new file mode 100644 index 00000000..29598b47 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordCreateFlags.java @@ -0,0 +1,67 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordCreateFlags { + DiscordCreateFlags_Default(0), + DiscordCreateFlags_NoRequireDiscord(1); + + @Getter + private final int value; + private EDiscordCreateFlags(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordCreateFlags> valueMap = new HashMap<>(); + static { + for (EDiscordCreateFlags value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordCreateFlags fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordCreateFlagsTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordCreateFlags.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordCreateFlags)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordEntitlementType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordEntitlementType.java new file mode 100644 index 00000000..d155fbc6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordEntitlementType.java @@ -0,0 +1,72 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordEntitlementType { + DiscordEntitlementType_Purchase(1), + DiscordEntitlementType_PremiumSubscription(2), + DiscordEntitlementType_DeveloperGift(3), + DiscordEntitlementType_TestModePurchase(4), + DiscordEntitlementType_FreePurchase(5), + DiscordEntitlementType_UserGift(6), + DiscordEntitlementType_PremiumPurchase(7); + + @Getter + private final int value; + private EDiscordEntitlementType(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordEntitlementType> valueMap = new HashMap<>(); + static { + for (EDiscordEntitlementType value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordEntitlementType fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordEntitlementTypeTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordEntitlementType.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordEntitlementType)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordImageType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordImageType.java new file mode 100644 index 00000000..db4258db --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordImageType.java @@ -0,0 +1,66 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordImageType { + DiscordImageType_User(0); + + @Getter + private final int value; + private EDiscordImageType(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordImageType> valueMap = new HashMap<>(); + static { + for (EDiscordImageType value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordImageType fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordImageTypeTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordImageType.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + + if (value == null) return 0;return ((EDiscordImageType)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordInputModeType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordInputModeType.java new file mode 100644 index 00000000..1cc49b7e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordInputModeType.java @@ -0,0 +1,67 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordInputModeType { + DiscordInputModeType_VoiceActivity(0), + DiscordInputModeType_PushToTalk(1); + + @Getter + private final int value; + private EDiscordInputModeType(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordInputModeType> valueMap = new HashMap<>(); + static { + for (EDiscordInputModeType value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordInputModeType fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordInputModeTypeTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordInputModeType.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordInputModeType)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbySearchCast.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbySearchCast.java new file mode 100644 index 00000000..5bd97267 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbySearchCast.java @@ -0,0 +1,67 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordLobbySearchCast { + DiscordLobbySearchCast_String(1), + DiscordLobbySearchCast_Number(2); + + @Getter + private final int value; + private EDiscordLobbySearchCast(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordLobbySearchCast> valueMap = new HashMap<>(); + static { + for (EDiscordLobbySearchCast value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordLobbySearchCast fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordLobbySearchCastTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordLobbySearchCast.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordLobbySearchCast)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbySearchComparison.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbySearchComparison.java new file mode 100644 index 00000000..5cc8f934 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbySearchComparison.java @@ -0,0 +1,71 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordLobbySearchComparison { + DiscordLobbySearchComparison_LessThanOrEqual(-2), + DiscordLobbySearchComparison_LessThan(-1), + DiscordLobbySearchComparison_Equal(0), + DiscordLobbySearchComparison_GreaterThan(1), + DiscordLobbySearchComparison_GreaterThanOrEqual(2), + DiscordLobbySearchComparison_NotEqual(3); + + @Getter + private final int value; + private EDiscordLobbySearchComparison(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordLobbySearchComparison> valueMap = new HashMap<>(); + static { + for (EDiscordLobbySearchComparison value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordLobbySearchComparison fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordLobbySearchComparisonTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordLobbySearchComparison.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordLobbySearchComparison)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbySearchDistance.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbySearchDistance.java new file mode 100644 index 00000000..e8a920ea --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbySearchDistance.java @@ -0,0 +1,69 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordLobbySearchDistance { + DiscordLobbySearchDistance_Local(0), + DiscordLobbySearchDistance_Default(1), + DiscordLobbySearchDistance_Extended(2), + DiscordLobbySearchDistance_Global(3); + + @Getter + private final int value; + private EDiscordLobbySearchDistance(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordLobbySearchDistance> valueMap = new HashMap<>(); + static { + for (EDiscordLobbySearchDistance value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordLobbySearchDistance fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordLobbySearchDistanceTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordLobbySearchDistance.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordLobbySearchDistance)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbyType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbyType.java new file mode 100644 index 00000000..d8353d59 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLobbyType.java @@ -0,0 +1,67 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordLobbyType { + DiscordLobbyType_Private(1), + DiscordLobbyType_Public(2); + + @Getter + private final int value; + private EDiscordLobbyType(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordLobbyType> valueMap = new HashMap<>(); + static { + for (EDiscordLobbyType value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordLobbyType fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordLobbyTypeTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordLobbyType.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + + if (value == null) return 0;return ((EDiscordLobbyType)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLogLevel.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLogLevel.java new file mode 100644 index 00000000..0fa0f3ab --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordLogLevel.java @@ -0,0 +1,69 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordLogLevel { + DiscordLogLevel_Error(1), + DiscordLogLevel_Warn(2), + DiscordLogLevel_Info(3), + DiscordLogLevel_Debug(4); + + @Getter + private final int value; + private EDiscordLogLevel(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordLogLevel> valueMap = new HashMap<>(); + static { + for (EDiscordLogLevel value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordLogLevel fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordLogLevelTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordLogLevel.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + + if (value == null) return 0;return ((EDiscordLogLevel)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordPremiumType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordPremiumType.java new file mode 100644 index 00000000..4ca426d5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordPremiumType.java @@ -0,0 +1,68 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordPremiumType { + DiscordPremiumType_None(0), + DiscordPremiumType_Tier1(1), + DiscordPremiumType_Tier2(2); + + @Getter + private final int value; + private EDiscordPremiumType(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordPremiumType> valueMap = new HashMap<>(); + static { + for (EDiscordPremiumType value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordPremiumType fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordPremiumTypeTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordPremiumType.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordPremiumType)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordRelationshipType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordRelationshipType.java new file mode 100644 index 00000000..b2edb714 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordRelationshipType.java @@ -0,0 +1,71 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordRelationshipType { + DiscordRelationshipType_None(0), + DiscordRelationshipType_Friend(1), + DiscordRelationshipType_Blocked(2), + DiscordRelationshipType_PendingIncoming(3), + DiscordRelationshipType_PendingOutgoing(4), + DiscordRelationshipType_Implicit(5); + + @Getter + private final int value; + private EDiscordRelationshipType(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordRelationshipType> valueMap = new HashMap<>(); + static { + for (EDiscordRelationshipType value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordRelationshipType fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordRelationshipTypeTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordRelationshipType.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordRelationshipType)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordResult.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordResult.java new file mode 100644 index 00000000..cb0541bf --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordResult.java @@ -0,0 +1,109 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordResult { + DiscordResult_Ok(0), + DiscordResult_ServiceUnavailable(1), + DiscordResult_InvalidVersion(2), + DiscordResult_LockFailed(3), + DiscordResult_InternalError(4), + DiscordResult_InvalidPayload(5), + DiscordResult_InvalidCommand(6), + DiscordResult_InvalidPermissions(7), + DiscordResult_NotFetched(8), + DiscordResult_NotFound(9), + DiscordResult_Conflict(10), + DiscordResult_InvalidSecret(11), + DiscordResult_InvalidJoinSecret(12), + DiscordResult_NoEligibleActivity(13), + DiscordResult_InvalidInvite(14), + DiscordResult_NotAuthenticated(15), + DiscordResult_InvalidAccessToken(16), + DiscordResult_ApplicationMismatch(17), + DiscordResult_InvalidDataUrl(18), + DiscordResult_InvalidBase64(19), + DiscordResult_NotFiltered(20), + DiscordResult_LobbyFull(21), + DiscordResult_InvalidLobbySecret(22), + DiscordResult_InvalidFilename(23), + DiscordResult_InvalidFileSize(24), + DiscordResult_InvalidEntitlement(25), + DiscordResult_NotInstalled(26), + DiscordResult_NotRunning(27), + DiscordResult_InsufficientBuffer(28), + DiscordResult_PurchaseCanceled(29), + DiscordResult_InvalidGuild(30), + DiscordResult_InvalidEvent(31), + DiscordResult_InvalidChannel(32), + DiscordResult_InvalidOrigin(33), + DiscordResult_RateLimited(34), + DiscordResult_OAuth2Error(35), + DiscordResult_SelectChannelTimeout(36), + DiscordResult_GetGuildTimeout(37), + DiscordResult_SelectVoiceForceRequired(38), + DiscordResult_CaptureShortcutAlreadyListening(39), + DiscordResult_UnauthorizedForAchievement(40), + DiscordResult_InvalidGiftCode(41), + DiscordResult_PurchaseError(42), + DiscordResult_TransactionAborted(43); + + @Getter + private final int value; + private EDiscordResult(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordResult> valueMap = new HashMap<>(); + static { + for (EDiscordResult value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordResult fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordResultTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordResult.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordResult)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordSkuType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordSkuType.java new file mode 100644 index 00000000..ba174a17 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordSkuType.java @@ -0,0 +1,69 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordSkuType { + DiscordSkuType_Application(1), + DiscordSkuType_DLC(2), + DiscordSkuType_Consumable(3), + DiscordSkuType_Bundle(4); + + @Getter + private final int value; + private EDiscordSkuType(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordSkuType> valueMap = new HashMap<>(); + static { + for (EDiscordSkuType value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordSkuType fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordSkuTypeTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordSkuType.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + + if (value == null) return 0;return ((EDiscordSkuType)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordStatus.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordStatus.java new file mode 100644 index 00000000..b788aa62 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordStatus.java @@ -0,0 +1,69 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordStatus { + DiscordStatus_Offline(0), + DiscordStatus_Online(1), + DiscordStatus_Idle(2), + DiscordStatus_DoNotDisturb(3); + + @Getter + private final int value; + private EDiscordStatus(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordStatus> valueMap = new HashMap<>(); + static { + for (EDiscordStatus value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordStatus fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordStatusTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordStatus.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + + if (value == null) return 0;return ((EDiscordStatus)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordUserFlag.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordUserFlag.java new file mode 100644 index 00000000..242e5f1e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/enumuration/EDiscordUserFlag.java @@ -0,0 +1,70 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public enum EDiscordUserFlag { + DiscordUserFlag_Partner(2), + DiscordUserFlag_HypeSquadEvents(4), + DiscordUserFlag_HypeSquadHouse1(64), + DiscordUserFlag_HypeSquadHouse2(128), + DiscordUserFlag_HypeSquadHouse3(256); + + @Getter + private final int value; + private EDiscordUserFlag(int value) { + this.value = value; + } + + private static final Map<Integer,EDiscordUserFlag> valueMap = new HashMap<>(); + static { + for (EDiscordUserFlag value : values()) { + valueMap.put(value.value, value); + } + } + + public static EDiscordUserFlag fromValue(int value) { + return valueMap.get(value); + } + + public static class EDiscordUserFlagTypeConverter implements TypeConverter { + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return EDiscordUserFlag.fromValue((Integer)nativeValue); + } + + @Override + public Object toNative(Object value, ToNativeContext context) { + if (value == null) return 0; + return ((EDiscordUserFlag)value).getValue(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/GameSDKCallback.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/GameSDKCallback.java new file mode 100644 index 00000000..6f139163 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/GameSDKCallback.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Callback; +import com.sun.jna.Library; +import kr.syeyoung.dungeonsguide.gamesdk.jna.GameSDKTypeMapper; + +import java.util.Collections; +import java.util.Map; + +public interface GameSDKCallback extends Callback { + public static final Map<String, Object> OPTIONS = Collections.singletonMap(Library.OPTION_TYPE_MAPPER, GameSDKTypeMapper.INSTANCE); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordAchievementEvents.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordAchievementEvents.java new file mode 100644 index 00000000..b1262022 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordAchievementEvents.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordUserAchievement; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordAchievementEvents extends DiscordStruct { public IDiscordAchievementEvents() {super();} public IDiscordAchievementEvents(Pointer pointer) {super(pointer);} + public interface OnUserAchievementUpdateCallback extends GameSDKCallback { void onUserAchievementUpdate(Pointer eventData, DiscordUserAchievement userAchievement); } + public OnUserAchievementUpdateCallback OnUserAchievementUpdate; + + + + public static class ByReference extends IDiscordAchievementEvents implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordAchievementEvents implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("OnUserAchievementUpdate"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordAchievementManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordAchievementManager.java new file mode 100644 index 00000000..afa18700 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordAchievementManager.java @@ -0,0 +1,57 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import com.sun.jna.ptr.IntByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.Int32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt8; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordUserAchievement; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordAchievementManager extends DiscordStruct { public IDiscordAchievementManager() {super();} public IDiscordAchievementManager(Pointer pointer) {super(pointer);} + public interface SetUserAchievementCallback extends GameSDKCallback { void setUserAchievement(IDiscordAchievementManager manager, DiscordSnowflake achievementId, UInt8 percentComplete, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public SetUserAchievementCallback SetUserAchievement; + + public interface FetchUserAchievementsCallback extends GameSDKCallback { void fetchUserAchievements(IDiscordAchievementManager manager, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public FetchUserAchievementsCallback FetchUserAchievements; + + public interface CountUserAchievementsCallback extends GameSDKCallback { void countUserAchievements(IDiscordAchievementManager manager, IntByReference count); } + public CountUserAchievementsCallback CountUserAchievements; + + public interface GetUserAchievementCallback extends GameSDKCallback { EDiscordResult getUserAchievement(IDiscordAchievementManager manager, DiscordSnowflake userAchievementId, DiscordUserAchievement userAchievement); } + public GetUserAchievementCallback GetUserAchievement; + + public interface GetUserAchievementAtCallback extends GameSDKCallback { EDiscordResult getUserAchievementAt(IDiscordAchievementManager manager, Int32 index, DiscordUserAchievement userAchievement); } + public GetUserAchievementAtCallback GetUserAchievementAt; + + + + public static class ByReference extends IDiscordAchievementManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordAchievementManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("SetUserAchievement", "FetchUserAchievements", "CountUserAchievements", "GetUserAchievement", "GetUserAchievementAt"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordActivityEvents.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordActivityEvents.java new file mode 100644 index 00000000..3e5cba71 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordActivityEvents.java @@ -0,0 +1,50 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityActionType; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordActivity; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordUser; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordActivityEvents extends DiscordStruct { public IDiscordActivityEvents() {super();} public IDiscordActivityEvents(Pointer pointer) {super(pointer);} + public interface OnActivityJoinCallback extends GameSDKCallback { void onActivityJoin(Pointer eventData, String secret); } + public OnActivityJoinCallback OnActivityJoin; + + public interface OnActivitySpectateCallback extends GameSDKCallback { void onActivitySpectate(Pointer eventData, String secret); } + public OnActivitySpectateCallback OnActivitySpectate; + + public interface OnActivityJoinRequestCallback extends GameSDKCallback { void onActivityJoinRequest(Pointer eventData, DiscordUser user); } + public OnActivityJoinRequestCallback OnActivityJoinRequest; + + public interface OnActivityInviteCallback extends GameSDKCallback { void onActivityInvite(Pointer eventData, EDiscordActivityActionType type, DiscordUser user, DiscordActivity activity); } + public OnActivityInviteCallback OnActivityInvite; + + + + public static class ByReference extends IDiscordActivityEvents implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordActivityEvents implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("OnActivityJoin", "OnActivitySpectate", "OnActivityJoinRequest", "OnActivityInvite"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordActivityManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordActivityManager.java new file mode 100644 index 00000000..6e566719 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordActivityManager.java @@ -0,0 +1,63 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityActionType; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordActivity; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityJoinRequestReply; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordActivityManager extends DiscordStruct { public IDiscordActivityManager() {super();} public IDiscordActivityManager(Pointer pointer) {super(pointer);} + public interface RegisterCommandCallback extends GameSDKCallback { EDiscordResult registerCommand(IDiscordActivityManager manager, String command); } + public RegisterCommandCallback RegisterCommand; + + public interface RegisterSteamCallback extends GameSDKCallback { EDiscordResult registerSteam(IDiscordActivityManager manager, UInt32 steamId); } + public RegisterSteamCallback RegisterSteam; + + public interface UpdateActivityCallback extends GameSDKCallback { void updateActivity(IDiscordActivityManager manager, DiscordActivity activity, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public UpdateActivityCallback UpdateActivity; + + public interface ClearActivityCallback extends GameSDKCallback { void clearActivity(IDiscordActivityManager manager, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public ClearActivityCallback ClearActivity; + + public interface SendRequestReplyCallback extends GameSDKCallback { void sendRequestReply(IDiscordActivityManager manager, DiscordSnowflake userId, EDiscordActivityJoinRequestReply reply, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public SendRequestReplyCallback SendRequestReply; + + public interface SendInviteCallback extends GameSDKCallback { void sendInvite(IDiscordActivityManager manager, DiscordSnowflake userId, EDiscordActivityActionType type, String content, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public SendInviteCallback SendInvite; + + public interface AcceptInviteCallback extends GameSDKCallback { void acceptInvite(IDiscordActivityManager manager, DiscordSnowflake userId, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public AcceptInviteCallback AcceptInvite; + + + + public static class ByReference extends IDiscordActivityManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordActivityManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("RegisterCommand", "RegisterSteam", "UpdateActivity", "ClearActivity", "SendRequestReply", "SendInvite", "AcceptInvite"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordApplicationManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordApplicationManager.java new file mode 100644 index 00000000..ba43432f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordApplicationManager.java @@ -0,0 +1,60 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordOAuth2Token; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordApplicationManager extends DiscordStruct { public IDiscordApplicationManager() {super();} public IDiscordApplicationManager(Pointer pointer) {super(pointer);} + public interface ValidateOrExitCallback extends GameSDKCallback { void validateOrExit(IDiscordApplicationManager manager, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public ValidateOrExitCallback ValidateOrExit; + + public interface GetCurrentLocaleCallback extends GameSDKCallback { void getCurrentLocale(IDiscordApplicationManager manager, Pointer locale); } // len 128 memory + public GetCurrentLocaleCallback GetCurrentLocale; + + public interface GetCurrentBranchCallback extends GameSDKCallback { void getCurrentBranch(IDiscordApplicationManager manager, Pointer branch); } // len 4096 mem + public GetCurrentBranchCallback GetCurrentBranch; + + public interface GetOauth2TokenCallback extends GameSDKCallback { void getOauth2Token(IDiscordApplicationManager manager, Pointer callbackData, GetOauth2TokenCallback_Callback callback); } + public interface GetOauth2TokenCallback_Callback extends GameSDKCallback { + void callback(Pointer callbackData, EDiscordResult result, DiscordOAuth2Token oauthToken); + } + + public GetOauth2TokenCallback GetOauth2Token; + + public interface GetTicketCallback extends GameSDKCallback { void getTicket(IDiscordApplicationManager manager, Pointer callbackData, GetTicketCallback_Callback callback); } + public interface GetTicketCallback_Callback extends GameSDKCallback { + void callback(Pointer callbackData, EDiscordResult result, String data); + } + public GetTicketCallback GetTicket; + + + + public static class ByReference extends IDiscordApplicationManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordApplicationManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("ValidateOrExit", "GetCurrentLocale", "GetCurrentBranch", "GetOauth2Token", "GetTicket"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordCore.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordCore.java new file mode 100644 index 00000000..9bc1bb49 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordCore.java @@ -0,0 +1,91 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import com.sun.jna.TypeMapper; +import kr.syeyoung.dungeonsguide.gamesdk.jna.GameSDKTypeMapper; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordLogLevel; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordCore extends DiscordStruct { public IDiscordCore() {super();} public IDiscordCore(Pointer pointer) {super(pointer);} + + public static final TypeMapper TYPE_MAPPER = GameSDKTypeMapper.INSTANCE; + public interface DestroyCallback extends GameSDKCallback { void destroy(IDiscordCore core); } + public DestroyCallback Destroy; + + public interface RunCallbacksCallback extends GameSDKCallback { EDiscordResult runCallbacks(IDiscordCore core); } + public RunCallbacksCallback RunCallbacks; + + public interface SetLogHookCallback extends GameSDKCallback { void setLogHook(IDiscordCore core, EDiscordLogLevel minLevel, Pointer hookData, LogHook hook); } + public interface LogHook extends GameSDKCallback { + void hook(Pointer hookData, EDiscordLogLevel level, String message); + } + public SetLogHookCallback SetLogHook; + + public interface GetApplicationManagerCallback extends GameSDKCallback { IDiscordApplicationManager getApplicationManager(IDiscordCore core); } + public GetApplicationManagerCallback GetApplicationManager; + + public interface GetUserManagerCallback extends GameSDKCallback { IDiscordUserManager getUserManager(IDiscordCore core); } + public GetUserManagerCallback GetUserManager; + + public interface GetImageManagerCallback extends GameSDKCallback { IDiscordImageManager getImageManager(IDiscordCore core); } + public GetImageManagerCallback GetImageManager; + + public interface GetActivityManagerCallback extends GameSDKCallback { IDiscordActivityManager getActivityManager(IDiscordCore core); } + public GetActivityManagerCallback GetActivityManager; + + public interface GetRelationshipManagerCallback extends GameSDKCallback { IDiscordRelationshipManager getRelationshipManager(IDiscordCore core); } + public GetRelationshipManagerCallback GetRelationshipManager; + + public interface GetLobbyManagerCallback extends GameSDKCallback { IDiscordLobbyManager getLobbyManager(IDiscordCore core); } + public GetLobbyManagerCallback GetLobbyManager; + + public interface GetNetworkManagerCallback extends GameSDKCallback { IDiscordNetworkManager getNetworkManager(IDiscordCore core); } + public GetNetworkManagerCallback GetNetworkManager; + + public interface GetOverlayManagerCallback extends GameSDKCallback { IDiscordOverlayManager getOverlayManager(IDiscordCore core); } + public GetOverlayManagerCallback GetOverlayManager; + + public interface GetStorageManagerCallback extends GameSDKCallback { IDiscordStorageManager getStorageManager(IDiscordCore core); } + public GetStorageManagerCallback GetStorageManager; + + public interface GetStoreManagerCallback extends GameSDKCallback { IDiscordStoreManager getStoreManager(IDiscordCore core); } + public GetStoreManagerCallback GetStoreManager; + + public interface GetVoiceManagerCallback extends GameSDKCallback { IDiscordVoiceManager getVoiceManager(IDiscordCore core); } + public GetVoiceManagerCallback GetVoiceManager; + + public interface GetAchievementManagerCallback extends GameSDKCallback { IDiscordAchievementManager getAchievementManager(IDiscordCore core); } + public GetAchievementManagerCallback GetAchievementManager; + + + + public static class ByReference extends IDiscordCore implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);} + } + public static class ByValue extends IDiscordCore implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);} + } + + @Override protected List getFieldOrder() { return Arrays.asList("Destroy", "RunCallbacks", "SetLogHook", "GetApplicationManager", "GetUserManager", "GetImageManager", "GetActivityManager", "GetRelationshipManager", "GetLobbyManager", "GetNetworkManager", "GetOverlayManager", "GetStorageManager", "GetStoreManager", "GetVoiceManager", "GetAchievementManager"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordImageManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordImageManager.java new file mode 100644 index 00000000..df4d9d02 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordImageManager.java @@ -0,0 +1,52 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordImageDimensions; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordImageHandle; + +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.List; + +public class IDiscordImageManager extends DiscordStruct { public IDiscordImageManager() {super();} public IDiscordImageManager(Pointer pointer) {super(pointer);} + public interface FetchCallback_Callback extends GameSDKCallback { + void callback(Pointer callbackData, EDiscordResult result, DiscordImageHandle.ByValue handleResult); + } + public interface FetchCallback extends GameSDKCallback { void fetch(IDiscordImageManager manager, DiscordImageHandle.ByValue handle, boolean refresh, Pointer callbackData, FetchCallback_Callback callback); } + public FetchCallback Fetch; + + public interface GetDimensionsCallback extends GameSDKCallback { EDiscordResult getDimensions(IDiscordImageManager manager, DiscordImageHandle.ByValue handle, DiscordImageDimensions dimensions); } + public GetDimensionsCallback GetDimensions; + + public interface GetDataCallback extends GameSDKCallback { EDiscordResult getData(IDiscordImageManager manager, DiscordImageHandle.ByValue handle, ByteBuffer data, UInt32 dataLength); } + public GetDataCallback GetData; + + + + public static class ByReference extends IDiscordImageManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordImageManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("Fetch", "GetDimensions", "GetData"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyEvents.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyEvents.java new file mode 100644 index 00000000..6d2babd5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyEvents.java @@ -0,0 +1,64 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import com.sun.jna.ptr.ByteByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt8; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.Int64; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordLobbyEvents extends DiscordStruct { public IDiscordLobbyEvents() {super();} public IDiscordLobbyEvents(Pointer pointer) {super(pointer);} + public interface OnLobbyUpdateCallback extends GameSDKCallback { void onLobbyUpdate(Pointer eventData, Int64 lobbyId); } + public OnLobbyUpdateCallback OnLobbyUpdate; + + public interface OnLobbyDeleteCallback extends GameSDKCallback { void onLobbyDelete(Pointer eventData, Int64 lobbyId, UInt32 reason); } + public OnLobbyDeleteCallback OnLobbyDelete; + + public interface OnMemberConnectCallback extends GameSDKCallback { void onMemberConnect(Pointer eventData, Int64 lobbyId, Int64 userId); } + public OnMemberConnectCallback OnMemberConnect; + + public interface OnMemberUpdateCallback extends GameSDKCallback { void onMemberUpdate(Pointer eventData, Int64 lobbyId, Int64 userId); } + public OnMemberUpdateCallback OnMemberUpdate; + + public interface OnMemberDisconnectCallback extends GameSDKCallback { void onMemberDisconnect(Pointer eventData, Int64 lobbyId, Int64 userId); } + public OnMemberDisconnectCallback OnMemberDisconnect; + + public interface OnLobbyMessageCallback extends GameSDKCallback { void onLobbyMessage(Pointer eventData, Int64 lobbyId, Int64 userId, ByteByReference data, UInt32 dataLength); } + public OnLobbyMessageCallback OnLobbyMessage; + + public interface OnSpeakingCallback extends GameSDKCallback { void onSpeaking(Pointer eventData, Int64 lobbyId, Int64 userId, boolean speaking); } + public OnSpeakingCallback OnSpeaking; + + public interface OnNetworkMessageCallback extends GameSDKCallback { void onNetworkMessage(Pointer eventData, Int64 lobbyId, Int64 userId, UInt8 channelId, ByteByReference data, UInt32 dataLength); } + public OnNetworkMessageCallback OnNetworkMessage; + + + + public static class ByReference extends IDiscordLobbyEvents implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordLobbyEvents implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + + @Override protected List getFieldOrder() { return Arrays.asList("OnLobbyUpdate", "OnLobbyDelete", "OnMemberConnect", "OnMemberUpdate", "OnMemberDisconnect", "OnLobbyMessage", "OnSpeaking", "OnNetworkMessage"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyManager.java new file mode 100644 index 00000000..f5ffcbd0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyManager.java @@ -0,0 +1,148 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import com.sun.jna.ptr.ByteByReference; +import com.sun.jna.ptr.IntByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordLobby; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.Int32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt8; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordUser; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordLobbyManager extends DiscordStruct { public IDiscordLobbyManager() {super();} public IDiscordLobbyManager(Pointer pointer) {super(pointer);} + public interface GetLobbyCreateTransactionCallback extends GameSDKCallback { EDiscordResult getLobbyCreateTransaction(IDiscordLobbyManager manager, IDiscordLobbyTransaction transaction); } + public GetLobbyCreateTransactionCallback GetLobbyCreateTransaction; + + public interface GetLobbyUpdateTransactionCallback extends GameSDKCallback { EDiscordResult getLobbyUpdateTransaction(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, IDiscordLobbyTransaction transaction); } + public GetLobbyUpdateTransactionCallback GetLobbyUpdateTransaction; + + public interface GetMemberUpdateTransactionCallback extends GameSDKCallback { EDiscordResult getMemberUpdateTransaction(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, DiscordSnowflake userId, IDiscordLobbyMemberTransaction transaction); } + public GetMemberUpdateTransactionCallback GetMemberUpdateTransaction; + + public interface DiscordLobbyManagerCallback extends GameSDKCallback { + void callback(Pointer callbackData, EDiscordResult result, DiscordLobby lobby); + } + + public interface CreateLobbyCallback extends GameSDKCallback { void createLobby(IDiscordLobbyManager manager, IDiscordLobbyTransaction transaction, Pointer callbackData,DiscordLobbyManagerCallback callback); } + public CreateLobbyCallback CreateLobby; + + public interface UpdateLobbyCallback extends GameSDKCallback { void updateLobby(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, IDiscordLobbyTransaction transaction, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public UpdateLobbyCallback UpdateLobby; + + public interface DeleteLobbyCallback extends GameSDKCallback { void deleteLobby(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public DeleteLobbyCallback DeleteLobby; + + public interface ConnectLobbyCallback extends GameSDKCallback { void connectLobby(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, Pointer secret, Pointer callbackData, DiscordLobbyManagerCallback callback); }// secret 128 byte long str + public ConnectLobbyCallback ConnectLobby; + + public interface ConnectLobbyWithActivitySecretCallback extends GameSDKCallback { void connectLobbyWithActivitySecret(IDiscordLobbyManager manager, Pointer activitySecret, Pointer callbackData, DiscordLobbyManagerCallback callback); } // secret 128 byte long str + public ConnectLobbyWithActivitySecretCallback ConnectLobbyWithActivitySecret; + + public interface DisconnectLobbyCallback extends GameSDKCallback { void disconnectLobby(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public DisconnectLobbyCallback DisconnectLobby; + + public interface GetLobbyCallback extends GameSDKCallback { EDiscordResult getLobby(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, DiscordLobby lobby); } + public GetLobbyCallback GetLobby; + + public interface GetLobbyActivitySecretCallback extends GameSDKCallback { EDiscordResult getLobbyActivitySecret(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, Pointer secret); } // pointer to char[128] + public GetLobbyActivitySecretCallback GetLobbyActivitySecret; + + public interface GetLobbyMetadataValueCallback extends GameSDKCallback { EDiscordResult getLobbyMetadataValue(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, Pointer key, Pointer value); } // key: char[256] value: pointer to char[4096] + public GetLobbyMetadataValueCallback GetLobbyMetadataValue; + + public interface GetLobbyMetadataKeyCallback extends GameSDKCallback { EDiscordResult getLobbyMetadataKey(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, Int32 index, Pointer key); }// key: pointer to char[256] + public GetLobbyMetadataKeyCallback GetLobbyMetadataKey; + + public interface LobbyMetadataCountCallback extends GameSDKCallback { EDiscordResult lobbyMetadataCount(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, IntByReference count); } + public LobbyMetadataCountCallback LobbyMetadataCount; + + public interface MemberCountCallback extends GameSDKCallback { EDiscordResult memberCount(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, IntByReference count); } + public MemberCountCallback MemberCount; + + public interface GetMemberUserIdCallback extends GameSDKCallback { EDiscordResult getMemberUserId(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, Int32 index, Pointer userId); } // userID: pointer to DiscordUserID + public GetMemberUserIdCallback GetMemberUserId; + + public interface GetMemberUserCallback extends GameSDKCallback { EDiscordResult getMemberUser(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, DiscordSnowflake userId, DiscordUser user); } + public GetMemberUserCallback GetMemberUser; + + public interface GetMemberMetadataValueCallback extends GameSDKCallback { EDiscordResult getMemberMetadataValue(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, DiscordSnowflake userId, Pointer key, Pointer value); }// key: char[256] value: pointer to char[4096] + public GetMemberMetadataValueCallback GetMemberMetadataValue; + + public interface GetMemberMetadataKeyCallback extends GameSDKCallback { EDiscordResult getMemberMetadataKey(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, DiscordSnowflake userId, Int32 index, Pointer key); }// key: pointer to char[256] + public GetMemberMetadataKeyCallback GetMemberMetadataKey; + + public interface MemberMetadataCountCallback extends GameSDKCallback { EDiscordResult memberMetadataCount(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, DiscordSnowflake userId, IntByReference count); } + public MemberMetadataCountCallback MemberMetadataCount; + + public interface UpdateMemberCallback extends GameSDKCallback { void updateMember(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, DiscordSnowflake userId, IDiscordLobbyMemberTransaction transaction, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public UpdateMemberCallback UpdateMember; + + public interface SendLobbyMessageCallback extends GameSDKCallback { void sendLobbyMessage(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, ByteByReference data, UInt32 dataLength, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public SendLobbyMessageCallback SendLobbyMessage; + + public interface GetSearchQueryCallback extends GameSDKCallback { EDiscordResult getSearchQuery(IDiscordLobbyManager manager, IDiscordLobbySearchQuery query); } + public GetSearchQueryCallback GetSearchQuery; + + public interface SearchCallback extends GameSDKCallback { void search(IDiscordLobbyManager manager, IDiscordLobbySearchQuery query, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public SearchCallback Search; + + public interface LobbyCountCallback extends GameSDKCallback { void lobbyCount(IDiscordLobbyManager manager, IntByReference count); } + public LobbyCountCallback LobbyCount; + + public interface GetLobbyIdCallback extends GameSDKCallback { EDiscordResult getLobbyId(IDiscordLobbyManager manager, Int32 index, Pointer lobbyId); } // lobbyID: Pointer to DiscordSnowflake + public GetLobbyIdCallback GetLobbyId; + + public interface ConnectVoiceCallback extends GameSDKCallback { void connectVoice(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public ConnectVoiceCallback ConnectVoice; + + public interface DisconnectVoiceCallback extends GameSDKCallback { void disconnectVoice(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public DisconnectVoiceCallback DisconnectVoice; + + public interface ConnectNetworkCallback extends GameSDKCallback { EDiscordResult connectNetwork(IDiscordLobbyManager manager, DiscordSnowflake lobbyId); } + public ConnectNetworkCallback ConnectNetwork; + + public interface DisconnectNetworkCallback extends GameSDKCallback { EDiscordResult disconnectNetwork(IDiscordLobbyManager manager, DiscordSnowflake lobbyId); } + public DisconnectNetworkCallback DisconnectNetwork; + + public interface FlushNetworkCallback extends GameSDKCallback { EDiscordResult flushNetwork(IDiscordLobbyManager manager); } + public FlushNetworkCallback FlushNetwork; + + public interface OpenNetworkChannelCallback extends GameSDKCallback { EDiscordResult openNetworkChannel(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, UInt8 channelId, boolean reliable); } + public OpenNetworkChannelCallback OpenNetworkChannel; + + public interface SendNetworkMessageCallback extends GameSDKCallback { EDiscordResult sendNetworkMessage(IDiscordLobbyManager manager, DiscordSnowflake lobbyId, DiscordSnowflake userId, UInt8 channelId, ByteByReference data, UInt32 dataLength); } + public SendNetworkMessageCallback SendNetworkMessage; + + + + public static class ByReference extends IDiscordLobbyManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordLobbyManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("GetLobbyCreateTransaction", "GetLobbyUpdateTransaction", "GetMemberUpdateTransaction", "CreateLobby", "UpdateLobby", "DeleteLobby", "ConnectLobby", "ConnectLobbyWithActivitySecret", "DisconnectLobby", "GetLobby", "GetLobbyActivitySecret", "GetLobbyMetadataValue", "GetLobbyMetadataKey", "LobbyMetadataCount", "MemberCount", "GetMemberUserId", "GetMemberUser", "GetMemberMetadataValue", "GetMemberMetadataKey", "MemberMetadataCount", "UpdateMember", "SendLobbyMessage", "GetSearchQuery", "Search", "LobbyCount", "GetLobbyId", "ConnectVoice", "DisconnectVoice", "ConnectNetwork", "DisconnectNetwork", "FlushNetwork", "OpenNetworkChannel", "SendNetworkMessage"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyMemberTransaction.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyMemberTransaction.java new file mode 100644 index 00000000..ccb80ecd --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyMemberTransaction.java @@ -0,0 +1,42 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordLobbyMemberTransaction extends DiscordStruct { public IDiscordLobbyMemberTransaction() {super();} public IDiscordLobbyMemberTransaction(Pointer pointer) {super(pointer);} + public interface SetMetadataCallback extends GameSDKCallback { EDiscordResult setMetadata(IDiscordLobbyMemberTransaction lobbyMemberTransaction, Pointer key, Pointer value); } // key is 256 bytes, value is 4096 + public SetMetadataCallback SetMetadata; + + public interface DeleteMetadataCallback extends GameSDKCallback { EDiscordResult deleteMetadata(IDiscordLobbyMemberTransaction lobbyMemberTransaction, Pointer key); } // key is 256 bytes, passed by reference + public DeleteMetadataCallback DeleteMetadata; + + + + public static class ByReference extends IDiscordLobbyMemberTransaction implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordLobbyMemberTransaction implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("SetMetadata", "DeleteMetadata"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbySearchQuery.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbySearchQuery.java new file mode 100644 index 00000000..371872ef --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbySearchQuery.java @@ -0,0 +1,52 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordLobbySearchComparison; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordLobbySearchDistance; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordLobbySearchCast; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordLobbySearchQuery extends DiscordStruct { public IDiscordLobbySearchQuery() {super();} public IDiscordLobbySearchQuery(Pointer pointer) {super(pointer);} + public interface FilterCallback extends GameSDKCallback { EDiscordResult filter(IDiscordLobbySearchQuery lobbySearchQuery, Pointer key, EDiscordLobbySearchComparison comparison, EDiscordLobbySearchCast cast, Pointer value); } + public FilterCallback Filter; + + public interface SortCallback extends GameSDKCallback { EDiscordResult sort(IDiscordLobbySearchQuery lobbySearchQuery, Pointer key, EDiscordLobbySearchCast cast, Pointer value); } + public SortCallback Sort; + + public interface LimitCallback extends GameSDKCallback { EDiscordResult limit(IDiscordLobbySearchQuery lobbySearchQuery, UInt32 limit); } + public LimitCallback Limit; + + public interface DistanceCallback extends GameSDKCallback { EDiscordResult distance(IDiscordLobbySearchQuery lobbySearchQuery, EDiscordLobbySearchDistance distance); } + public DistanceCallback Distance; + + + + public static class ByReference extends IDiscordLobbySearchQuery implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordLobbySearchQuery implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("Filter", "Sort", "Limit", "Distance"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyTransaction.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyTransaction.java new file mode 100644 index 00000000..2434e787 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordLobbyTransaction.java @@ -0,0 +1,57 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordLobbyType; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordLobbyTransaction extends DiscordStruct { public IDiscordLobbyTransaction() {super();} public IDiscordLobbyTransaction(Pointer pointer) {super(pointer);} + public interface SetTypeCallback extends GameSDKCallback { EDiscordResult setType(IDiscordLobbyTransaction lobbyTransaction, EDiscordLobbyType type); } + public SetTypeCallback SetType; + + public interface SetOwnerCallback extends GameSDKCallback { EDiscordResult setOwner(IDiscordLobbyTransaction lobbyTransaction, DiscordSnowflake ownerId); } + public SetOwnerCallback SetOwner; + + public interface SetCapacityCallback extends GameSDKCallback { EDiscordResult setCapacity(IDiscordLobbyTransaction lobbyTransaction, UInt32 capacity); } + public SetCapacityCallback SetCapacity; + + public interface SetMetadataCallback extends GameSDKCallback { EDiscordResult setMetadata(IDiscordLobbyTransaction lobbyTransaction, Pointer key, Pointer value); } + public SetMetadataCallback SetMetadata; + + public interface DeleteMetadataCallback extends GameSDKCallback { EDiscordResult deleteMetadata(IDiscordLobbyTransaction lobbyTransaction, Pointer key); } + public DeleteMetadataCallback DeleteMetadata; + + public interface SetLockedCallback extends GameSDKCallback { EDiscordResult setLocked(IDiscordLobbyTransaction lobbyTransaction, boolean locked); } + public SetLockedCallback SetLocked; + + + + public static class ByReference extends IDiscordLobbyTransaction implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordLobbyTransaction implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("SetType", "SetOwner", "SetCapacity", "SetMetadata", "DeleteMetadata", "SetLocked"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordNetworkEvents.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordNetworkEvents.java new file mode 100644 index 00000000..cafadcbd --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordNetworkEvents.java @@ -0,0 +1,45 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import com.sun.jna.ptr.ByteByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordNetworkChannelId; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordNetworkPeerId; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordNetworkEvents extends DiscordStruct { public IDiscordNetworkEvents() {super();} public IDiscordNetworkEvents(Pointer pointer) {super(pointer);} + public interface OnMessageCallback extends GameSDKCallback { void onMessage(Pointer eventData, DiscordNetworkPeerId peerId, DiscordNetworkChannelId channelId, ByteByReference data, UInt32 dataLength); } + public OnMessageCallback OnMessage; + + public interface OnRouteUpdateCallback extends GameSDKCallback { void onRouteUpdate(Pointer eventData, String route_data); } + public OnRouteUpdateCallback OnRouteUpdate; + + + + public static class ByReference extends IDiscordNetworkEvents implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordNetworkEvents implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("OnMessage", "OnRouteUpdate"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordNetworkManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordNetworkManager.java new file mode 100644 index 00000000..49296684 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordNetworkManager.java @@ -0,0 +1,65 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.ptr.ByteByReference; +import com.sun.jna.ptr.LongByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordNetworkChannelId; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordNetworkPeerId; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordNetworkManager extends DiscordStruct { public IDiscordNetworkManager() {super();} public IDiscordNetworkManager(Pointer pointer) {super(pointer);} + public interface GetPeerIdCallback extends GameSDKCallback { void getPeerId(IDiscordNetworkManager manager, LongByReference peerId); } + public GetPeerIdCallback GetPeerId; + + public interface FlushCallback extends GameSDKCallback { EDiscordResult flush(IDiscordNetworkManager manager); } + public FlushCallback Flush; + + public interface OpenPeerCallback extends GameSDKCallback { EDiscordResult openPeer(IDiscordNetworkManager manager, DiscordNetworkPeerId peerId, String routeData); } + public OpenPeerCallback OpenPeer; + + public interface UpdatePeerCallback extends GameSDKCallback { EDiscordResult updatePeer(IDiscordNetworkManager manager, DiscordNetworkPeerId peerId, String routeData); } + public UpdatePeerCallback UpdatePeer; + + public interface ClosePeerCallback extends GameSDKCallback { EDiscordResult closePeer(IDiscordNetworkManager manager, DiscordNetworkPeerId peerId); } + public ClosePeerCallback ClosePeer; + + public interface OpenChannelCallback extends GameSDKCallback { EDiscordResult openChannel(IDiscordNetworkManager manager, DiscordNetworkPeerId peerId, DiscordNetworkChannelId channelId, boolean reliable); } + public OpenChannelCallback OpenChannel; + + public interface CloseChannelCallback extends GameSDKCallback { EDiscordResult closeChannel(IDiscordNetworkManager manager, DiscordNetworkPeerId peerId, DiscordNetworkChannelId channelId); } + public CloseChannelCallback CloseChannel; + + public interface SendMessageCallback extends GameSDKCallback { EDiscordResult sendMessage(IDiscordNetworkManager manager, DiscordNetworkPeerId peerId, DiscordNetworkChannelId channelId, ByteByReference data, UInt32 dataLength); } + public SendMessageCallback SendMessage; + + + + public static class ByReference extends IDiscordNetworkManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordNetworkManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("GetPeerId", "Flush", "OpenPeer", "UpdatePeer", "ClosePeer", "OpenChannel", "CloseChannel", "SendMessage"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordOverlayEvents.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordOverlayEvents.java new file mode 100644 index 00000000..2c17e3f1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordOverlayEvents.java @@ -0,0 +1,38 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordOverlayEvents extends DiscordStruct { public IDiscordOverlayEvents() {super();} public IDiscordOverlayEvents(Pointer pointer) {super(pointer);} + public interface OnToggleCallback extends GameSDKCallback { void onToggle(Pointer eventData, boolean locked); } + public OnToggleCallback OnToggle; + + + + public static class ByReference extends IDiscordOverlayEvents implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordOverlayEvents implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("OnToggle"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordOverlayManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordOverlayManager.java new file mode 100644 index 00000000..76c33590 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordOverlayManager.java @@ -0,0 +1,56 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import com.sun.jna.ptr.ByteByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityActionType; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordOverlayManager extends DiscordStruct { public IDiscordOverlayManager() {super();} public IDiscordOverlayManager(Pointer pointer) {super(pointer);} + public interface IsEnabledCallback extends GameSDKCallback { void isEnabled(IDiscordOverlayManager manager, ByteByReference enabled); } + public IsEnabledCallback IsEnabled; + + public interface IsLockedCallback extends GameSDKCallback { void isLocked(IDiscordOverlayManager manager, ByteByReference locked); } + public IsLockedCallback IsLocked; + + public interface SetLockedCallback extends GameSDKCallback { void setLocked(IDiscordOverlayManager manager, boolean locked, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public SetLockedCallback SetLocked; + + public interface OpenActivityInviteCallback extends GameSDKCallback { void openActivityInvite(IDiscordOverlayManager manager, EDiscordActivityActionType type, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public OpenActivityInviteCallback OpenActivityInvite; + + public interface OpenGuildInviteCallback extends GameSDKCallback { void openGuildInvite(IDiscordOverlayManager manager, String code, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public OpenGuildInviteCallback OpenGuildInvite; + + public interface OpenVoiceSettingsCallback extends GameSDKCallback { void openVoiceSettings(IDiscordOverlayManager manager, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public OpenVoiceSettingsCallback OpenVoiceSettings; + + + + public static class ByReference extends IDiscordOverlayManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordOverlayManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("IsEnabled", "IsLocked", "SetLocked", "OpenActivityInvite", "OpenGuildInvite", "OpenVoiceSettings"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordRelationshipEvents.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordRelationshipEvents.java new file mode 100644 index 00000000..86d3c9a3 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordRelationshipEvents.java @@ -0,0 +1,42 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordRelationship; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordRelationshipEvents extends DiscordStruct { public IDiscordRelationshipEvents() {super();} public IDiscordRelationshipEvents(Pointer pointer) {super(pointer);} + public interface OnRefreshCallback extends GameSDKCallback { void onRefresh(Pointer eventData); } + public OnRefreshCallback OnRefresh; + + public interface OnRelationshipUpdateCallback extends GameSDKCallback { void onRelationshipUpdate(Pointer eventData, DiscordRelationship relationship); } + public OnRelationshipUpdateCallback OnRelationshipUpdate; + + + + public static class ByReference extends IDiscordRelationshipEvents implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordRelationshipEvents implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("OnRefresh", "OnRelationshipUpdate"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordRelationshipManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordRelationshipManager.java new file mode 100644 index 00000000..62422933 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordRelationshipManager.java @@ -0,0 +1,53 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import com.sun.jna.ptr.IntByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordRelationship; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordRelationshipManager extends DiscordStruct { public IDiscordRelationshipManager() {super();} public IDiscordRelationshipManager(Pointer pointer) {super(pointer);} + public interface FilterCallback extends GameSDKCallback { void filter(IDiscordRelationshipManager manager, Pointer filterData, FilterCallback_Callback filter); } + public interface FilterCallback_Callback extends GameSDKCallback { boolean filter(Pointer filterData, DiscordRelationship relationShip);} + public FilterCallback Filter; + + public interface CountCallback extends GameSDKCallback { EDiscordResult count(IDiscordRelationshipManager manager, IntByReference count); } + public CountCallback Count; + + public interface GetCallback extends GameSDKCallback { EDiscordResult get(IDiscordRelationshipManager manager, DiscordSnowflake userId, DiscordRelationship relationship); } + public GetCallback Get; + + public interface GetAtCallback extends GameSDKCallback { EDiscordResult getAt(IDiscordRelationshipManager manager, UInt32 index, DiscordRelationship relationship); } + public GetAtCallback GetAt; + + + + public static class ByReference extends IDiscordRelationshipManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordRelationshipManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("Filter", "Count", "Get", "GetAt"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordStorageManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordStorageManager.java new file mode 100644 index 00000000..8e610285 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordStorageManager.java @@ -0,0 +1,81 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import com.sun.jna.ptr.ByteByReference; +import com.sun.jna.ptr.IntByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.Int32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordFileStat; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt64; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordStorageManager extends DiscordStruct { public IDiscordStorageManager() {super();} public IDiscordStorageManager(Pointer pointer) {super(pointer);} + public interface ReadCallback extends GameSDKCallback { EDiscordResult read(IDiscordStorageManager manager, String name, ByteByReference data, UInt32 dataLength, IntByReference read); } + public ReadCallback Read; + + public interface DiscordStorageManagerCallback extends GameSDKCallback { + void callback(Pointer callbackData, EDiscordResult result, ByteByReference data, IntByReference data_length); + } + + public interface ReadAsyncCallback extends GameSDKCallback { void readAsync(IDiscordStorageManager manager, String name, Pointer callbackData, DiscordStorageManagerCallback callback); } + public ReadAsyncCallback ReadAsync; + + public interface ReadAsyncPartialCallback extends GameSDKCallback { void readAsyncPartial(IDiscordStorageManager manager, String name, UInt64 offset, UInt64 length, Pointer callbackData, DiscordStorageManagerCallback callback); } + public ReadAsyncPartialCallback ReadAsyncPartial; + + public interface WriteCallback extends GameSDKCallback { EDiscordResult write(IDiscordStorageManager manager, String name, ByteByReference data, UInt32 dataLength); } + public WriteCallback Write; + + public interface WriteAsyncCallback extends GameSDKCallback { void writeAsync(IDiscordStorageManager manager, String name, ByteByReference data, UInt32 dataLength, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public WriteAsyncCallback WriteAsync; + + public interface DeleteCallback extends GameSDKCallback { EDiscordResult delete(IDiscordStorageManager manager, String name); } + public DeleteCallback Delete; + + public interface ExistsCallback extends GameSDKCallback { EDiscordResult exists(IDiscordStorageManager manager, String name, ByteByReference exists); } // exists actually boolean + public ExistsCallback Exists; + + public interface CountCallback extends GameSDKCallback { void count(IDiscordStorageManager manager, IntByReference count); } + public CountCallback Count; + + public interface StatCallback extends GameSDKCallback { EDiscordResult stat(IDiscordStorageManager manager, String name, DiscordFileStat stat); } + public StatCallback Stat; + + public interface StatAtCallback extends GameSDKCallback { EDiscordResult statAt(IDiscordStorageManager manager, Int32 index, DiscordFileStat stat); } + public StatAtCallback StatAt; + + public interface GetPathCallback extends GameSDKCallback { EDiscordResult getPath(IDiscordStorageManager manager, Pointer path); } // path str len 4096 + public GetPathCallback GetPath; + + + + public static class ByReference extends IDiscordStorageManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordStorageManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + + @Override protected List getFieldOrder() { return Arrays.asList("Read", "ReadAsync", "ReadAsyncPartial", "Write", "WriteAsync", "Delete", "Exists", "Count", "Stat", "StatAt", "GetPath"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordStoreEvents.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordStoreEvents.java new file mode 100644 index 00000000..3b7cec62 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordStoreEvents.java @@ -0,0 +1,43 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordEntitlement; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordStoreEvents extends DiscordStruct { public IDiscordStoreEvents() {super();} public IDiscordStoreEvents(Pointer pointer) {super(pointer);} + public interface OnEntitlementCreateCallback extends GameSDKCallback { void onEntitlementCreate(Pointer eventData, DiscordEntitlement entitlement); } + public OnEntitlementCreateCallback OnEntitlementCreate; + + public interface OnEntitlementDeleteCallback extends GameSDKCallback { void onEntitlementDelete(Pointer eventData, DiscordEntitlement entitlement); } + public OnEntitlementDeleteCallback OnEntitlementDelete; + + + + public static class ByReference extends IDiscordStoreEvents implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordStoreEvents implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + + @Override protected List getFieldOrder() { return Arrays.asList("OnEntitlementCreate", "OnEntitlementDelete"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordStoreManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordStoreManager.java new file mode 100644 index 00000000..2e78e736 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordStoreManager.java @@ -0,0 +1,73 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import com.sun.jna.ptr.ByteByReference; +import com.sun.jna.ptr.IntByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordSku; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordEntitlement; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.Int32; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordStoreManager extends DiscordStruct { public IDiscordStoreManager() {super();} public IDiscordStoreManager(Pointer pointer) {super(pointer);} + public interface FetchSkusCallback extends GameSDKCallback { void fetchSkus(IDiscordStoreManager manager, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public FetchSkusCallback FetchSkus; + + public interface CountSkusCallback extends GameSDKCallback { void countSkus(IDiscordStoreManager manager, IntByReference count); } + public CountSkusCallback CountSkus; + + public interface GetSkuCallback extends GameSDKCallback { EDiscordResult getSku(IDiscordStoreManager manager, DiscordSnowflake skuId, DiscordSku sku); } + public GetSkuCallback GetSku; + + public interface GetSkuAtCallback extends GameSDKCallback { EDiscordResult getSkuAt(IDiscordStoreManager manager, Int32 index, DiscordSku sku); } + public GetSkuAtCallback GetSkuAt; + + public interface FetchEntitlementsCallback extends GameSDKCallback { void fetchEntitlements(IDiscordStoreManager manager, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public FetchEntitlementsCallback FetchEntitlements; + + public interface CountEntitlementsCallback extends GameSDKCallback { void countEntitlements(IDiscordStoreManager manager, IntByReference count); } + public CountEntitlementsCallback CountEntitlements; + + public interface GetEntitlementCallback extends GameSDKCallback { EDiscordResult getEntitlement(IDiscordStoreManager manager, DiscordSnowflake entitlementId, DiscordEntitlement entitlement); } + public GetEntitlementCallback GetEntitlement; + + public interface GetEntitlementAtCallback extends GameSDKCallback { EDiscordResult getEntitlementAt(IDiscordStoreManager manager, Int32 index, DiscordEntitlement entitlement); } + public GetEntitlementAtCallback GetEntitlementAt; + + public interface HasSkuEntitlementCallback extends GameSDKCallback { EDiscordResult hasSkuEntitlement(IDiscordStoreManager manager, DiscordSnowflake skuId, ByteByReference hasEntitlement); } // hasEntitlement bool ptr + public HasSkuEntitlementCallback HasSkuEntitlement; + + public interface StartPurchaseCallback extends GameSDKCallback { void startPurchase(IDiscordStoreManager manager, DiscordSnowflake skuId, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public StartPurchaseCallback StartPurchase; + + + + public static class ByReference extends IDiscordStoreManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordStoreManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("FetchSkus", "CountSkus", "GetSku", "GetSkuAt", "FetchEntitlements", "CountEntitlements", "GetEntitlement", "GetEntitlementAt", "HasSkuEntitlement", "StartPurchase"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordUserEvents.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordUserEvents.java new file mode 100644 index 00000000..260d8890 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordUserEvents.java @@ -0,0 +1,38 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordUserEvents extends DiscordStruct { public IDiscordUserEvents() {super();} public IDiscordUserEvents(Pointer pointer) {super(pointer);} + public interface OnCurrentUserUpdateCallback extends GameSDKCallback { void onCurrentUserUpdate(Pointer eventData); } + public OnCurrentUserUpdateCallback OnCurrentUserUpdate; + + + + public static class ByReference extends IDiscordUserEvents implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordUserEvents implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + @Override protected List getFieldOrder() { return Arrays.asList("OnCurrentUserUpdate"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordUserManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordUserManager.java new file mode 100644 index 00000000..cbdc780f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordUserManager.java @@ -0,0 +1,53 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import com.sun.jna.ptr.ByteByReference; +import com.sun.jna.ptr.IntByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordUserFlag; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordUser; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordUserManager extends DiscordStruct { public IDiscordUserManager() {super();} public IDiscordUserManager(Pointer pointer) {super(pointer);} + public interface GetCurrentUserCallback extends GameSDKCallback { EDiscordResult getCurrentUser(IDiscordUserManager manager, DiscordUser currentUser); } + public GetCurrentUserCallback GetCurrentUser; + + public interface GetUserCallback extends GameSDKCallback { void getUser(IDiscordUserManager manager, DiscordSnowflake userId, Pointer callbackData, GetUserCallback_Callback callback); } + public interface GetUserCallback_Callback extends GameSDKCallback { void callback(Pointer callbackData, EDiscordResult result, DiscordUser user);} + public GetUserCallback GetUser; + + public interface GetCurrentUserPremiumTypeCallback extends GameSDKCallback { EDiscordResult getCurrentUserPremiumType(IDiscordUserManager manager, IntByReference premiumType); } // EDiscordPremiumType ptr + public GetCurrentUserPremiumTypeCallback GetCurrentUserPremiumType; + + public interface CurrentUserHasFlagCallback extends GameSDKCallback { EDiscordResult currentUserHasFlag(IDiscordUserManager manager, EDiscordUserFlag flag, ByteByReference hasFlag); } // hasFlag bool ptr + public CurrentUserHasFlagCallback CurrentUserHasFlag; + + + + public static class ByReference extends IDiscordUserManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordUserManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + @Override protected List getFieldOrder() { return Arrays.asList("GetCurrentUser", "GetUser", "GetCurrentUserPremiumType", "CurrentUserHasFlag"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordVoiceEvents.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordVoiceEvents.java new file mode 100644 index 00000000..f9f59528 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordVoiceEvents.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordVoiceEvents extends DiscordStruct { public IDiscordVoiceEvents() {super();} public IDiscordVoiceEvents(Pointer pointer) {super(pointer);} + public interface OnSettingsUpdateCallback extends GameSDKCallback { void onSettingsUpdate(Pointer eventData); } + public OnSettingsUpdateCallback OnSettingsUpdate; + + + + public static class ByReference extends IDiscordVoiceEvents implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordVoiceEvents implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + + @Override protected List getFieldOrder() { return Arrays.asList("OnSettingsUpdate"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordVoiceManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordVoiceManager.java new file mode 100644 index 00000000..7e101640 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordVoiceManager.java @@ -0,0 +1,72 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct; + +import com.sun.jna.Structure; +import com.sun.jna.ptr.ByteByReference; +import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordStruct; +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.UInt8; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordInputMode; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordSnowflake; + +import java.util.Arrays; +import java.util.List; + +public class IDiscordVoiceManager extends DiscordStruct { public IDiscordVoiceManager() {super();} public IDiscordVoiceManager(Pointer pointer) {super(pointer);} + public interface GetInputModeCallback extends GameSDKCallback { EDiscordResult getInputMode(IDiscordVoiceManager manager, DiscordInputMode inputMode); } + public GetInputModeCallback GetInputMode; + + public interface SetInputModeCallback extends GameSDKCallback { void setInputMode(IDiscordVoiceManager manager, DiscordInputMode.ByValue inputMode, Pointer callbackData, NativeGameSDK.DiscordCallback callback); } + public SetInputModeCallback SetInputMode; + + public interface IsSelfMuteCallback extends GameSDKCallback { EDiscordResult isSelfMute(IDiscordVoiceManager manager, ByteByReference mute); } + public IsSelfMuteCallback IsSelfMute; + + public interface SetSelfMuteCallback extends GameSDKCallback { EDiscordResult setSelfMute(IDiscordVoiceManager manager, boolean mute); } + public SetSelfMuteCallback SetSelfMute; + + public interface IsSelfDeafCallback extends GameSDKCallback { EDiscordResult isSelfDeaf(IDiscordVoiceManager manager, ByteByReference deaf); } + public IsSelfDeafCallback IsSelfDeaf; + + public interface SetSelfDeafCallback extends GameSDKCallback { EDiscordResult setSelfDeaf(IDiscordVoiceManager manager, boolean deaf); } + public SetSelfDeafCallback SetSelfDeaf; + + public interface IsLocalMuteCallback extends GameSDKCallback { EDiscordResult isLocalMute(IDiscordVoiceManager manager, DiscordSnowflake userId, ByteByReference mute); } + public IsLocalMuteCallback IsLocalMute; + + public interface SetLocalMuteCallback extends GameSDKCallback { EDiscordResult setLocalMute(IDiscordVoiceManager manager, DiscordSnowflake userId, boolean mute); } + public SetLocalMuteCallback SetLocalMute; + + public interface GetLocalVolumeCallback extends GameSDKCallback { EDiscordResult getLocalVolume(IDiscordVoiceManager manager, DiscordSnowflake userId, ByteByReference volume); } + public GetLocalVolumeCallback GetLocalVolume; + + public interface SetLocalVolumeCallback extends GameSDKCallback { EDiscordResult setLocalVolume(IDiscordVoiceManager manager, DiscordSnowflake userId, UInt8 volume); } + public SetLocalVolumeCallback SetLocalVolume; + + + + public static class ByReference extends IDiscordVoiceManager implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}} + public static class ByValue extends IDiscordVoiceManager implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}} + + + @Override protected List getFieldOrder() { return Arrays.asList("GetInputMode", "SetInputMode", "IsSelfMute", "SetSelfMute", "IsSelfDeaf", "SetSelfDeaf", "IsLocalMute", "SetLocalMute", "GetLocalVolume", "SetLocalVolume"); } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordClientID.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordClientID.java new file mode 100644 index 00000000..0ada5f77 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordClientID.java @@ -0,0 +1,28 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.typedef; + +public class DiscordClientID extends Int64 { + public DiscordClientID() { + this(0); + } + public DiscordClientID(long value) { + super(value); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordNetworkChannelId.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordNetworkChannelId.java new file mode 100644 index 00000000..a8711776 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordNetworkChannelId.java @@ -0,0 +1,28 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.typedef; + +public class DiscordNetworkChannelId extends UInt8 { + public DiscordNetworkChannelId() { + this(0); + } + public DiscordNetworkChannelId(long value) { + super(value); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordNetworkPeerId.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordNetworkPeerId.java new file mode 100644 index 00000000..38632ee1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordNetworkPeerId.java @@ -0,0 +1,28 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.typedef; + +public class DiscordNetworkPeerId extends UInt64 { + public DiscordNetworkPeerId() { + this(0); + } + public DiscordNetworkPeerId(long value) { + super(value); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordSnowflake.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordSnowflake.java new file mode 100644 index 00000000..0d746919 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordSnowflake.java @@ -0,0 +1,28 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.typedef; + +public class DiscordSnowflake extends Int64 { + public DiscordSnowflake() { + this(0); + } + public DiscordSnowflake(long value) { + super(value); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordTimestamp.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordTimestamp.java new file mode 100644 index 00000000..de021e0b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordTimestamp.java @@ -0,0 +1,28 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.typedef; + +public class DiscordTimestamp extends Int64 { + public DiscordTimestamp() { + this(0); + } + public DiscordTimestamp(long value) { + super(value); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordVersion.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordVersion.java new file mode 100644 index 00000000..b38d99a6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/DiscordVersion.java @@ -0,0 +1,28 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.typedef; + +public class DiscordVersion extends Int32 { + public DiscordVersion() { + this(0); + } + public DiscordVersion(long value) { + super(value); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/Int32.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/Int32.java new file mode 100644 index 00000000..581aed96 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/Int32.java @@ -0,0 +1,31 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.typedef; + +import com.sun.jna.IntegerType; + +public class Int32 extends IntegerType { + public static final int SIZE = 4; + public Int32() { + this(0); + } + public Int32(long value) { + super(SIZE, value, false); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/Int64.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/Int64.java new file mode 100644 index 00000000..a8dff873 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/Int64.java @@ -0,0 +1,31 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.typedef; + +import com.sun.jna.IntegerType; + +public class Int64 extends IntegerType { + public static final int SIZE = 8; + public Int64() { + this(0); + } + public Int64(long value) { + super(SIZE, value, false); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/UInt32.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/UInt32.java new file mode 100644 index 00000000..98a903c6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/UInt32.java @@ -0,0 +1,31 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.typedef; + +import com.sun.jna.IntegerType; + +public class UInt32 extends IntegerType { + public static final int SIZE = 4; + public UInt32() { + this(0); + } + public UInt32(long value) { + super(SIZE, value, true); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/UInt64.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/UInt64.java new file mode 100644 index 00000000..a0265b34 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/UInt64.java @@ -0,0 +1,31 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.typedef; + +import com.sun.jna.IntegerType; + +public class UInt64 extends IntegerType { + public static final int SIZE = 8; + public UInt64() { + this(0); + } + public UInt64(long value) { + super(SIZE, value, true); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/UInt8.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/UInt8.java new file mode 100644 index 00000000..1b10c5a2 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/typedef/UInt8.java @@ -0,0 +1,31 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gamesdk.jna.typedef; + +import com.sun.jna.IntegerType; + +public class UInt8 extends IntegerType { + public static final int SIZE = 1; + public UInt8() { + this(0); + } + public UInt8(long value) { + super(SIZE, value, true); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/MGui.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/MGui.java new file mode 100644 index 00000000..8d444d39 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/MGui.java @@ -0,0 +1,258 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui; + +import kr.syeyoung.dungeonsguide.gui.elements.MRootPanel; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import kr.syeyoung.dungeonsguide.utils.cursor.GLCursors; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.LWJGLException; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.io.IOException; + +public class MGui extends GuiScreen { + + @Getter + private final MRootPanel mainPanel = new MRootPanel(); + private boolean isOpen = false; + + public MGui(){ + try { + Mouse.setNativeCursor(GLCursors.getCursor(EnumCursor.DEFAULT)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public void initGui() { + super.initGui(); + Keyboard.enableRepeatEvents(true); + isOpen = true; + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + mainPanel.setBounds(new Rectangle(0,0,Minecraft.getMinecraft().displayWidth,Minecraft.getMinecraft().displayHeight)); + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + try { + + int i = Mouse.getEventX(); + int j = this.mc.displayHeight - Mouse.getEventY(); + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + GlStateManager.pushMatrix(); + GlStateManager.disableDepth(); + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); + GlStateManager.color(1, 1, 1, 1); + GlStateManager.scale(1.0/scaledResolution.getScaleFactor(), 1.0/scaledResolution.getScaleFactor(), 1.0d); + mainPanel.render0(1, new Point(0,0), new Rectangle(0,0,Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight), i, j, i, j, partialTicks); + GlStateManager.popMatrix(); + GlStateManager.enableBlend(); + GlStateManager.enableDepth(); + } catch (Throwable e) { + e.printStackTrace(); + } + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } + + @Override + public void keyTyped(char typedChar, int keyCode) throws IOException { + try { + mainPanel.keyPressed0(typedChar, keyCode); + super.keyTyped(typedChar, keyCode); + } catch (Throwable e) { + if (e.getMessage() == null || !e.getMessage().contains("hack to stop")) + e.printStackTrace(); + } + } + public void keyHeld(int keyCode, char typedChar) throws IOException { + try { + mainPanel.keyHeld0(typedChar, keyCode); + } catch (Throwable e) { + if (e.getMessage() == null || !e.getMessage().contains("hack to stop")) + e.printStackTrace(); + } + } + public void keyReleased(int keyCode, char typedChar) throws IOException { + try { + mainPanel.keyReleased0(typedChar, keyCode); + } catch (Throwable e) { + if (e.getMessage() == null || !e.getMessage().contains("hack to stop")) + e.printStackTrace(); + } + } + + @Override + public void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + try { + super.mouseClicked(mouseX, mouseY, mouseButton); + mainPanel.mouseClicked0(mouseX, mouseY + ,mouseX, mouseY, mouseButton); + } catch (Throwable e) { + if (e.getMessage() == null || !e.getMessage().contains("hack to stop")) + e.printStackTrace(); + } + } + + @Override + public void onGuiClosed() { + super.onGuiClosed(); + Keyboard.enableRepeatEvents(false); + isOpen = false; + + try { + Mouse.setNativeCursor(null); + mainPanel.setCursor(EnumCursor.DEFAULT); + } catch (LWJGLException e) { + e.printStackTrace(); + } + } + + @Override + public void mouseReleased(int mouseX, int mouseY, int state) { + try { + mainPanel.mouseReleased0(mouseX, mouseY + ,mouseX,mouseY , state); + } catch (Throwable e) { + if (e.getMessage() == null || !e.getMessage().contains("hack to stop")) + e.printStackTrace(); + } + } + + @Override + public void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { + try { + mainPanel.mouseClickMove0(mouseX, mouseY + ,mouseX ,mouseY, clickedMouseButton, timeSinceLastClick); + } catch (Throwable e) { + if (e.getMessage() == null || !e.getMessage().contains("hack to stop")) + e.printStackTrace(); + } + } + + public void mouseMove(int mouseX, int mouseY) { + try { + mainPanel.mouseMoved0(mouseX, mouseY + ,mouseX ,mouseY); + } catch (Throwable e) { + if (e.getMessage() == null || !e.getMessage().contains("hack to stop")) + e.printStackTrace(); + } + } + + + private int touchValue; + private int eventButton; + private long lastMouseEvent; + + + private int lastX, lastY; + + + @Override + public void handleMouseInput() throws IOException { + if (!isOpen) return; + try { + int i = Mouse.getEventX(); + int j = this.mc.displayHeight - Mouse.getEventY(); + int k = Mouse.getEventButton(); + + if (Mouse.getEventButtonState()) + { + if (this.mc.gameSettings.touchscreen && this.touchValue++ > 0) + { + return; + } + + this.eventButton = k; + this.lastMouseEvent = Minecraft.getSystemTime(); + this.mouseClicked(i, j, this.eventButton); + } + else if (k != -1) + { + if (this.mc.gameSettings.touchscreen && --this.touchValue > 0) + { + return; + } + + this.eventButton = -1; + this.mouseReleased(i, j, k); + } + else if (this.eventButton != -1 && this.lastMouseEvent > 0L) + { + long l = Minecraft.getSystemTime() - this.lastMouseEvent; + this.mouseClickMove(i, j, this.eventButton, l); + } + if (lastX != i || lastY != j) { + try { + EnumCursor prevCursor = mainPanel.getCurrentCursor(); + mainPanel.setCursor(EnumCursor.DEFAULT); + this.mouseMove(i, j); + EnumCursor newCursor = mainPanel.getCurrentCursor(); + if (prevCursor != newCursor) Mouse.setNativeCursor(GLCursors.getCursor(newCursor)); + } catch (Throwable e) { + if (e.getMessage() == null || !e.getMessage().contains("hack to stop")) + e.printStackTrace(); + } + } + + + int wheel = Mouse.getEventDWheel(); + if (wheel != 0) { + mainPanel.mouseScrolled0(i, j,i,j, wheel); + } + lastX = i; + lastY = j; + } catch (Throwable e) { + e.printStackTrace(); + } + } + public void handleKeyboardInput() throws IOException + { + if (!isOpen) return; + + if (Keyboard.getEventKeyState()) + { + if (Keyboard.isRepeatEvent()) + this.keyHeld(Keyboard.getEventKey(), Keyboard.getEventCharacter()); + else + this.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey()); + } else { + this.keyReleased(Keyboard.getEventKey(), Keyboard.getEventCharacter()); + } + + this.mc.dispatchKeypresses(); + } + + @Override + public void handleInput() throws IOException { +// Keyboard.enableRepeatEvents(true); // i hope it's temproary solution + super.handleInput(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/MPanel.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/MPanel.java new file mode 100644 index 00000000..c61235a3 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/MPanel.java @@ -0,0 +1,296 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui; + +import kr.syeyoung.dungeonsguide.gui.elements.MTooltip; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +@Getter +public class MPanel { + protected Rectangle bounds = new Rectangle(0,0,0,0); // relative to parent + + protected List<MPanel> childComponents = new CopyOnWriteArrayList<MPanel>(); + + protected Color backgroundColor = new Color(0,0,0,0); + + protected Rectangle lastAbsClip = new Rectangle(0,0,0,0); + + @Getter(AccessLevel.PUBLIC) + @Setter + protected boolean isFocused; + + @Getter + @Setter + protected MPanel parent; + + private boolean debug; + + public void setBackgroundColor(Color c) { + if (c == null) return; + this.backgroundColor = c; + } + + public void setPosition(Point pt) { + this.setBounds(new Rectangle(pt.x, pt.y, getBounds().width, getBounds().height)); + } + + public void setSize(Dimension dim) { + this.setBounds(new Rectangle(getBounds().x, getBounds().y, dim.width, dim.height)); + } + + public Dimension getSize() { + return getBounds().getSize(); + } + + public Dimension getPreferredSize() { return getSize(); } + + public void setBounds(Rectangle bounds) { + if (bounds == null) return; + this.bounds.x = bounds.x; + this.bounds.y = bounds.y; + this.bounds.width = bounds.width; + this.bounds.height = bounds.height; + + for (MPanel childComponent : childComponents) { + childComponent.resize0(getBounds().width, getBounds().height); + } + onBoundsUpdate(); + } + + public void onBoundsUpdate() { + + } + + public void add(MPanel child) { + if (child.parent != null) throw new IllegalArgumentException("What have you done"); + this.childComponents.add(child); + child.setParent(this); + } + + public void openTooltip(MTooltip mPanel) { + parent.openTooltip(mPanel); + } + public int getTooltipsOpen() { + return parent.getTooltipsOpen(); + } + + public void remove(MPanel panel) { + if (panel != null) + panel.setParent(null); + this.childComponents.remove(panel); + } + + protected Point lastParentPoint; + + @Getter + @Setter + private boolean ignoreBoundOnClip; + + public void render0(double scale, Point parentPoint, Rectangle parentClip, int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks) { // 0,0 - a a + + lastParentPoint = parentPoint; + int relMousex = relMousex0 - getBounds().x; + int relMousey = relMousey0 - getBounds().y; + + GlStateManager.translate(getBounds().x, getBounds().y, 5); + GlStateManager.color(1,1,1,1); + + + Rectangle absBound = getBounds().getBounds(); + absBound.setLocation(absBound.x + parentPoint.x, absBound.y + parentPoint.y); + Rectangle clip; + if (ignoreBoundOnClip) clip = parentClip; + else clip = determineClip(parentClip, absBound); + lastAbsClip = clip; + if (clip.getSize().height * clip.getSize().width == 0) return; + + this.scale = scale; + clip(clip.x, clip.y, clip.width, clip.height); + + GL11.glEnable(GL11.GL_SCISSOR_TEST); + + GuiScreen.drawRect(0,0, getBounds().width, getBounds().height, backgroundColor.getRGB()); + GlStateManager.enableBlend(); + + GlStateManager.pushMatrix(); + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); + + render(absMousex, absMousey, relMousex, relMousey, partialTicks, clip); + GlStateManager.popMatrix(); + if (debug && lastAbsClip.contains(absMousex, absMousey)) { + GL11.glDisable(GL11.GL_SCISSOR_TEST); + Gui.drawRect(0, 0, getBounds().width, getBounds().height, 0x2200FF00); + Gui.drawRect(0, 0, getPreferredSize().width, getPreferredSize().height, 0x220000FF); + } + + GL11.glDisable(GL11.GL_SCISSOR_TEST); + + Point newPt = new Point(parentPoint.x + getBounds().x, parentPoint.y + getBounds().y); + + for (MPanel mPanel : getChildComponents()){ + GlStateManager.pushMatrix(); + mPanel.render0(scale, newPt, clip, absMousex, absMousey, relMousex, relMousey, partialTicks); + GlStateManager.popMatrix(); + } + } + protected double scale; + public void clip(int x, int y, int width, int height) { + if (width < 0 || height < 0) return; + + GL11.glScissor((int) (x * scale), Minecraft.getMinecraft().displayHeight - (int) ((y + height) * scale), (int)(width* scale + scale) - 1, (int) (height * scale + scale) - 1); + } + + protected Rectangle determineClip(Rectangle rect1, Rectangle rect2) { + int minX = Math.max(rect1.x, rect2.x); + int minY = Math.max(rect1.y, rect2.y); + int maxX = Math.min(rect1.x + rect1.width, rect2.x + rect2.width); + int maxY = Math.min(rect1.y + rect1.height, rect2.y +rect2.height); + if (minX > maxX) return new Rectangle(0,0,0,0); + if (minY > maxY) return new Rectangle(0,0,0,0); + return new Rectangle(minX, minY, maxX - minX, maxY - minY); + } + + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {} + + public void resize0(int parentWidth, int parentHeight) { + resize(parentWidth, parentHeight); + } + + public void resize(int parentWidth, int parentHeight) {} + + + public void keyPressed0(char typedChar, int keyCode) { + for (MPanel childComponent : getChildComponents()) { + childComponent.keyPressed0(typedChar, keyCode); + } + + if (isFocused) + keyPressed(typedChar, keyCode); + } + public void keyPressed(char typedChar, int keyCode) {} + public void keyHeld0(char typedChar, int keyCode) { + for (MPanel childComponent : getChildComponents()) { + childComponent.keyHeld0(typedChar, keyCode); + } + + if (isFocused) + keyHeld(typedChar, keyCode); + } + public void keyHeld(char typedChar, int keyCode) {} + public void keyReleased0(char typedChar, int keyCode) { + for (MPanel childComponent : getChildComponents()) { + childComponent.keyReleased0(typedChar, keyCode); + } + + if (isFocused) + keyReleased(typedChar, keyCode); + } + public void keyReleased(char typedChar, int keyCode) {} + + + public boolean mouseClicked0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int mouseButton) { + int relMousex = relMouseX0 - getBounds().x; + int relMousey = relMouseY0 - getBounds().y; + + boolean noClip = true; + boolean focusedOverall = false; + for (MPanel childComponent : getChildComponents()) { + if (childComponent.mouseClicked0(absMouseX, absMouseY, relMousex, relMousey, mouseButton)) { + noClip = false; + focusedOverall = true; + } + } + + if (getBounds().contains(relMouseX0, relMouseY0) && noClip) { + isFocused = true; + focusedOverall = true; + } else { + isFocused = false; + } + + mouseClicked(absMouseX, absMouseY, relMousex, relMousey, mouseButton); + return focusedOverall; + } + + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {} + + public void mouseReleased0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int state) { + int relMousex = relMouseX0 - getBounds().x; + int relMousey = relMouseY0 - getBounds().y; + + for (MPanel childComponent : getChildComponents()) { + childComponent.mouseReleased0(absMouseX, absMouseY, relMousex, relMousey, state); + } + mouseReleased(absMouseX, absMouseY, relMousex, relMousey, state); + } + public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) {} + + public void mouseClickMove0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int clickedMouseButton, long timeSinceLastClick) { + int relMousex = relMouseX0 - getBounds().x; + int relMousey = relMouseY0 - getBounds().y; + + for (MPanel childComponent : getChildComponents()) { + childComponent.mouseClickMove0(absMouseX, absMouseY, relMousex, relMousey, clickedMouseButton, timeSinceLastClick); + } + mouseClickMove(absMouseX, absMouseY, relMousex, relMousey, clickedMouseButton, timeSinceLastClick); + } + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) {} + + public void mouseScrolled0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + int relMousex = relMouseX0 - getBounds().x; + int relMousey = relMouseY0 - getBounds().y; + + for (MPanel childComponent : getChildComponents()) { + childComponent.mouseScrolled0(absMouseX, absMouseY, relMousex, relMousey, scrollAmount); + } + mouseScrolled(absMouseX, absMouseY, relMousex, relMousey, scrollAmount); + } + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) {} + + public void mouseMoved0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + int relMousex = relMouseX0 - getBounds().x; + int relMousey = relMouseY0 - getBounds().y; + + mouseMoved(absMouseX, absMouseY, relMousex, relMousey); + for (MPanel childComponent : getChildComponents()) { + childComponent.mouseMoved0(absMouseX, absMouseY, relMousex, relMousey); + } + } + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {} + + public void setCursor(EnumCursor enumCursor) { + parent.setCursor(enumCursor); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MButton.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MButton.java new file mode 100755 index 00000000..d95e4f33 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MButton.java @@ -0,0 +1,117 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; + +@Getter +@Setter +public class MButton extends MPanel { + private String text; + + private Color foreground = Color.white; + private int background = RenderUtils.blendAlpha(0xFF141414, 0.08f); + private int hover = RenderUtils.blendAlpha(0xFF141414, 0.14f); + private int clicked = RenderUtils.blendAlpha(0xFF141414, 0.16f); + private int border = 0x0; + private int disabled =0xFF141414; + private int roundness = 0; + + private boolean enabled = true; + + private Runnable onActionPerformed; + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + Dimension bounds = getSize(); + + int bg = background; + if (!enabled) { + bg = disabled; + } else if (getTooltipsOpen() > 0) { + } else if (isclicked) { + bg = clicked; + } else if (new Rectangle(new Point(0,0),bounds).contains(relMousex0, relMousey0)) { + bg = hover; + } + if (roundness == 0) { + if (((border >> 24) & 0xFF) == 0) + Gui.drawRect(0, 0, getBounds().width, getBounds().height, bg); + else { + Gui.drawRect(0, 0, getBounds().width, getBounds().height, border); + Gui.drawRect(1, 1, getBounds().width - 1, getBounds().height - 1, bg); + } + } else { + if (((border >> 24) & 0xFF) == 0) + RenderUtils.drawRoundedRectangle(0, 0, getBounds().width, getBounds().height, roundness, Math.PI/8, bg); + else { + RenderUtils.drawRoundedRectangle(0, 0, getBounds().width, getBounds().height, roundness, Math.PI/8, border); + RenderUtils.drawRoundedRectangle(1, 1, getBounds().width-2, getBounds().height-2, roundness, Math.PI/8, bg); + } + GlStateManager.enableTexture2D(); + } + FontRenderer renderer = Minecraft.getMinecraft().fontRendererObj; + int width = renderer.getStringWidth(getText()); + int x = (getBounds().width - width) / 2; + int y = (getBounds().height - renderer.FONT_HEIGHT) / 2 + 1; + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + renderer.drawString(getText(), x,y, foreground.getRGB()); + } + + boolean isclicked = false; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (lastAbsClip.contains(absMouseX, absMouseY) && getTooltipsOpen() == 0) { + isclicked = true; + if (onActionPerformed != null) + onActionPerformed.run(); + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + } + } + + @Override + public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) { + isclicked = false; + } + + + @Override + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + if (lastAbsClip.contains(absMouseX, absMouseY) && enabled) + setCursor(EnumCursor.POINTING_HAND); + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MCollapsable.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MCollapsable.java new file mode 100644 index 00000000..99d0405d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MCollapsable.java @@ -0,0 +1,137 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + +/** + * Note it is passive. + */ +public class MCollapsable extends MPanel { + @Getter + @Setter + private boolean collapsed = true; + + private MPanel representing; + @Getter + private MList lowerElements; + + @Getter @Setter + private int leftPad = 0, leftPadElements = 13; + + private Runnable onPreferedSizeChange; + + public MCollapsable(MPanel representing, Runnable onPreferedSizeChange) { + this.representing = representing; + super.add(representing); + lowerElements = new MList(); + lowerElements.setGap(0); + super.add(lowerElements); + + this.onPreferedSizeChange = onPreferedSizeChange; + } + + @Override + public Dimension getPreferredSize() { + Dimension rep = representing.getPreferredSize(); + if (collapsed) { + return new Dimension(rep.width+leftPad+10, rep.height); + } else { + Dimension lowerElem = lowerElements.getPreferredSize(); + return new Dimension(Math.max(rep.width+leftPad+10, leftPadElements + lowerElem.width), rep.height+lowerElem.height+lowerElements.getGap()); + } + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + Dimension representingSize =this.representing.getPreferredSize(); + Dimension lowerSize = lowerElements.getPreferredSize(); + + representing.setBounds(new Rectangle(new Point(leftPad+10, 0), new Dimension(bounds.width - (leftPad+10), representingSize.height))); + lowerElements.setBounds(new Rectangle(new Point(leftPadElements, representingSize.height+lowerElements.getGap()), new Dimension(bounds.width - (leftPadElements), lowerSize.height))); + lowerElements.realignChildren(); + } + + @Override + public void render0(double scale, Point parentPoint, Rectangle parentClip, int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks) { + super.render0(scale, parentPoint, parentClip, absMousex, absMousey, relMousex0, relMousey0, partialTicks); + + clip(lastAbsClip.x, lastAbsClip.y, lastAbsClip.width, lastAbsClip.height); + GL11.glEnable(GL11.GL_SCISSOR_TEST); + + + GlStateManager.pushMatrix(); + + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + if (collapsed) { + GlStateManager.translate(leftPad + 10 - fr.getStringWidth(">"),(bounds.height - fr.FONT_HEIGHT)/2,0); + } else { + GlStateManager.translate(leftPad + fr.FONT_HEIGHT,(representing.getPreferredSize().height - fr.getStringWidth(">"))/2,0); + GlStateManager.rotate(90, 0,0,1); + } + + fr.drawString(">", 0,0, -1); + + + GlStateManager.popMatrix(); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } + + @Override + public void add(MPanel child) { + lowerElements.add(child); + if (onPreferedSizeChange != null) onPreferedSizeChange.run(); + } + + @Override + public void remove(MPanel panel) { + lowerElements.remove(panel); + if (onPreferedSizeChange != null) onPreferedSizeChange.run(); + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (relMouseX >= leftPad && relMouseY >= 0 && relMouseX <= leftPad + 10 && relMouseY <= representing.getPreferredSize().height) { + collapsed = !collapsed; + if (onPreferedSizeChange != null) onPreferedSizeChange.run(); + } + } + + @Override + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX, int relMouseY) { + if (relMouseX >= leftPad && relMouseY >= 0 && relMouseX <= leftPad + 10 && relMouseY <= representing.getPreferredSize().height) + setCursor(EnumCursor.POINTING_HAND); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MColor.java new file mode 100644 index 00000000..91369048 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MColor.java @@ -0,0 +1,48 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.minecraft.client.gui.Gui; + +import java.awt.*; + +@AllArgsConstructor +@NoArgsConstructor +public class MColor extends MPanel { + @Getter + @Setter + private Color color = Color.white; + @Getter + @Setter + private Dimension size = new Dimension(20,15); + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + Rectangle rectangle = getBounds(); + + int x = (rectangle.width - getSize().width) / 2; + int y = (rectangle.height - getSize().height) / 2; + + Gui.drawRect(x,y,x+getSize().width,y+getSize().height, getColor().getRGB()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MEditableAColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MEditableAColor.java new file mode 100644 index 00000000..3dcfa6d4 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MEditableAColor.java @@ -0,0 +1,107 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; + +@AllArgsConstructor +@NoArgsConstructor +public class MEditableAColor extends MPanel { + @Getter + @Setter + private AColor color = new AColor(0xffffffff, true); + @Getter + @Setter + private Dimension size = new Dimension(20,15); + + @Getter + @Setter + private boolean enableEdit = false; + + @Getter + @Setter + private Runnable onUpdate; + + public void setEnableEdit(boolean enableEdit) { + this.enableEdit = enableEdit; + if (portable != null && !enableEdit) { + remove(portable); + portable = null; + } + } + + private MPortableColorEdit portable = null; + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + Rectangle rectangle = getBounds(); + + int x = (rectangle.width - getSize().width) / 2; + int y = (rectangle.height - getSize().height) / 2; + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + Gui.drawRect(x,y,x+getSize().width,y+getSize().height, RenderUtils.getColorAt(absMousex - relMousex0, absMousey - relMousey0, color)); + + Gui.drawRect(x,y,x+getSize().width,y+1, 0xff333333); + Gui.drawRect(x,y,x+1,y+getSize().height, 0xff333333); + Gui.drawRect(x+getSize().width-1,y,x+getSize().width,y+getSize().height, 0xff333333); + Gui.drawRect(x,y+getSize().height-1,x+getSize().width,y+getSize().height, 0xff333333); + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (!enableEdit) return; + if (lastAbsClip.contains(absMouseX, absMouseY) && getTooltipsOpen() == 0) { + portable = new MPortableColorEdit() { + @Override + public void update2() { + super.update2(); + MEditableAColor.this.color = portable.getColor(); + if (onUpdate != null) + onUpdate.run(); + } + }; + portable.setColor(color); + Rectangle startWith = new Rectangle((int)(absMouseX * getScale()), (int) (absMouseY* getScale()), (int) (100 * getScale()), (int) (90 * getScale())); + if (startWith.x < 10) startWith.x = 10; + if (startWith.y < 10) startWith.y = 10; + if (startWith.x + startWith.width > Minecraft.getMinecraft().displayWidth - 10) startWith.x = Minecraft.getMinecraft().displayWidth - 10 - startWith.width; + if (startWith.y + startWith.height > Minecraft.getMinecraft().displayHeight - 10) startWith.y = Minecraft.getMinecraft().displayHeight - 10 - startWith.height; + portable.setBounds(startWith); + + + portable.setScale(2.0f); + portable.open(this); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MFloatSelectionButton.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MFloatSelectionButton.java new file mode 100755 index 00000000..081dc0e2 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MFloatSelectionButton.java @@ -0,0 +1,97 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.Setter; + +import java.awt.*; + +@Getter +@Setter +public class MFloatSelectionButton extends MPanel { + + private float data; + + private MButton dec; + private MButton inc; + private MTextField selected; + + @Getter + @Setter + private Runnable onUpdate; + + public MFloatSelectionButton(float data2) { + this.data = data2; + + dec = new MButton(); dec.setText("<"); add(dec); + inc = new MButton(); inc.setText(">"); add(inc); + selected = new MTextField() { + @Override + public String getText() { + return data +""; + } + @Override + public void edit(String str) { + try { + data = Float.parseFloat(str); + onUpdate.run(); + } catch (Exception e) {} + } + }; updateSelected(); add(selected); + + dec.setOnActionPerformed(new Runnable() { + @Override + public void run() { + data--; + updateSelected(); + onUpdate.run(); + } + }); + inc.setOnActionPerformed(new Runnable() { + @Override + public void run() { + data ++; + updateSelected(); + onUpdate.run(); + } + }); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(-1,15); + } + + public float getSelected() { + return data; + } + + public void updateSelected() { + selected.setText(data+""); + } + + @Override + public void onBoundsUpdate() { + dec.setBounds(new Rectangle(0,0,getBounds().height, getBounds().height)); + inc.setBounds(new Rectangle(getBounds().width - getBounds().height, 0, getBounds().height, getBounds().height)); + selected.setBounds(new Rectangle(getBounds().height, 0, getBounds().width - getBounds().height - getBounds().height, getBounds().height)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MIntegerSelectionButton.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MIntegerSelectionButton.java new file mode 100755 index 00000000..9e72d0a7 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MIntegerSelectionButton.java @@ -0,0 +1,95 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.Setter; +import org.lwjgl.input.Keyboard; + +import java.awt.*; + +@Getter +@Setter +public class MIntegerSelectionButton extends MPanel { + + private int data; + + private MButton dec; + private MButton inc; + private MTextField selected; + + @Getter + @Setter + private Runnable onUpdate; + + public MIntegerSelectionButton(int data2) { + this.data = data2; + + dec = new MButton(); dec.setText("<"); add(dec); + inc = new MButton(); inc.setText(">"); add(inc); + selected = new MTextField() { + @Override + public void edit(String str) { + try { + data = Integer.parseInt(str); + onUpdate.run(); + } catch (Exception e) {} + } + }; updateSelected(); add(selected); + + dec.setOnActionPerformed(new Runnable() { + @Override + public void run() { + data -= (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) ? 5 : 1); + updateSelected(); + onUpdate.run(); + } + }); + inc.setOnActionPerformed(new Runnable() { + @Override + public void run() { + data += (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) ? 5 : 1); + updateSelected(); + onUpdate.run(); + } + }); + } + + + @Override + public Dimension getPreferredSize() { + return new Dimension(-1,15); + } + + public int getSelected() { + return data; + } + + private void updateSelected() { + selected.setText(data+""); + } + + @Override + public void onBoundsUpdate() { + dec.setBounds(new Rectangle(0,0,getBounds().height, getBounds().height)); + inc.setBounds(new Rectangle(getBounds().width - getBounds().height, 0, getBounds().height, getBounds().height)); + selected.setBounds(new Rectangle(getBounds().height, 0, getBounds().width - getBounds().height - getBounds().height, getBounds().height)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MKeyEditButton.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MKeyEditButton.java new file mode 100755 index 00000000..20d5fb7f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MKeyEditButton.java @@ -0,0 +1,147 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; + +@Getter +@Setter +public class MKeyEditButton extends MPanel { + private int key; + private Runnable onKeyEdit; + + private Color foreground = Color.white; + private int background = RenderUtils.blendAlpha(0xFF141414, 0.08f); + private int hover = RenderUtils.blendAlpha(0xFF141414, 0.14f); + private int clicked = RenderUtils.blendAlpha(0xFF141414, 0.16f); + private int border = 0x0; + private int disabled =0xFF141414; + private int roundness = 0; + + private boolean enabled = true; + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + Dimension bounds = getSize(); + + int bg = background; + if (!enabled) { + bg = disabled; + } else if (getTooltipsOpen() > 0) { + } else if (selected) { + bg = clicked; + } else if (new Rectangle(new Point(0,0),bounds).contains(relMousex0, relMousey0)) { + bg = hover; + } + if (roundness == 0) { + if (((border >> 24) & 0xFF) == 0) + Gui.drawRect(0, 0, getBounds().width, getBounds().height, bg); + else { + Gui.drawRect(0, 0, getBounds().width, getBounds().height, border); + Gui.drawRect(1, 1, getBounds().width - 1, getBounds().height - 1, bg); + } + } else { + if (((border >> 24) & 0xFF) == 0) + RenderUtils.drawRoundedRectangle(0, 0, getBounds().width, getBounds().height, roundness, Math.PI/8, bg); + else { + RenderUtils.drawRoundedRectangle(0, 0, getBounds().width, getBounds().height, roundness, Math.PI/8, border); + RenderUtils.drawRoundedRectangle(1, 1, getBounds().width-2, getBounds().height-2, roundness, Math.PI/8, bg); + } + GlStateManager.enableTexture2D(); + } + + String str = GameSettings.getKeyDisplayString(key); + if (selected) str = "> "+str+" <"; + FontRenderer renderer = Minecraft.getMinecraft().fontRendererObj; + int width = renderer.getStringWidth(str); + int x = (getBounds().width - width) / 2; + int y = (getBounds().height - renderer.FONT_HEIGHT) / 2 + 1; + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + renderer.drawString(str, x,y, foreground.getRGB()); + } + + private boolean selected; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (lastAbsClip.contains(absMouseX, absMouseY) && getTooltipsOpen() == 0) { + if (selected) { + key = -100 + mouseButton; + selected = false; + if (onKeyEdit != null) + onKeyEdit.run(); + } else { + selected = true; + } + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + } else { + selected = false; + } + } + + @Override + public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) { + + } + + + @Override + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + if (lastAbsClip.contains(absMouseX, absMouseY) && enabled) + setCursor(EnumCursor.POINTING_HAND); + } + + @Override + public void keyPressed(char typedChar, int keyCode) { + if (!selected) return; + if (keyCode == 1) { + key = 0; + } else if (keyCode != 0) { + key = keyCode; + } else if (typedChar > 0) { + key = typedChar + 256; + } + selected = false; + if (onKeyEdit != null) + onKeyEdit.run(); + throw new RuntimeException("hack to stop event propagation"); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(80, 15); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MLabel.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MLabel.java new file mode 100755 index 00000000..6b82b90b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MLabel.java @@ -0,0 +1,72 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; + +public class MLabel extends MPanel { + @Getter + @Setter + private String text; + + @Getter + @Setter + private Color foreground = Color.white; + + public enum Alignment { + LEFT, CENTER, RIGHT + } + @Getter + @Setter + private Alignment alignment= Alignment.LEFT; + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + Dimension bounds = getSize(); + + FontRenderer renderer = Minecraft.getMinecraft().fontRendererObj; + int width = renderer.getStringWidth(getText()); + int x,y; + if (alignment == Alignment.CENTER) { + x = (getBounds().width - width) / 2; + y = (getBounds().height - renderer.FONT_HEIGHT) / 2; + } else if (alignment == Alignment.LEFT) { + x = 0; + y = (getBounds().height - renderer.FONT_HEIGHT) / 2; + } else if (alignment == Alignment.RIGHT) { + x = getBounds().width - width; + y = (getBounds().height - renderer.FONT_HEIGHT) / 2; + } else{ + return; + } + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + renderer.drawString(getText(), x,y, 0xffffffff); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MLabelAndElement.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MLabelAndElement.java new file mode 100755 index 00000000..19326543 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MLabelAndElement.java @@ -0,0 +1,75 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.gui.Gui; + +import java.awt.*; + +public class MLabelAndElement extends MPanel { + private final MLabel label; + private final MPanel element; + + @Getter @Setter + private Color hover; + @Getter @Setter + private Runnable onClick; + + public MLabelAndElement(String label, MPanel element) { + this.add(this.label = new MLabel()); + this.label.setText(label); + this.add(element); + this.element = element; + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 30); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + if (hover != null && new Rectangle(new Point(0,0),getBounds().getSize()).contains(relMousex0, relMousey0)) { + Gui.drawRect(0,0,getBounds().width, getBounds().height, hover.getRGB()); + } + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (onClick!= null && lastAbsClip.contains(absMouseX, absMouseY)) { + onClick.run(); + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setSize(new Dimension(parentWidth, getBounds().height)); + label.setBounds(new Rectangle(0,0,parentHeight / 3, getBounds().height)); + element.setBounds(new Rectangle(parentWidth / 3,0,parentWidth / 3 * 2, getBounds().height)); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width / 3, getBounds().height)); + element.setBounds(new Rectangle(getBounds().width / 3,0,getBounds().width / 3 * 2, getBounds().height)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MList.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MList.java new file mode 100644 index 00000000..cb755963 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MList.java @@ -0,0 +1,93 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.gui.Gui; + +import java.awt.*; + +public class MList extends MPanel { + @Getter + private int gap = 5; + + @Getter @Setter + private boolean drawLine = true; + + public void setGap(int gap) { + this.gap = gap; + realignChildren(); + } + + @Getter @Setter + private int gapLineColor = 0xFFFFFFFF; + + public void realignChildren() { + int y = 0; + for (MPanel childComponent : getChildComponents()) { + Dimension preferedSize = childComponent.getPreferredSize(); + int height = Math.max(10, preferedSize.height); + childComponent.setBounds(new Rectangle(0, y, bounds.width, height)); + y += height; + if (gap > 0) + y += gap; + } + setSize(new Dimension(getSize().width, Math.max(0, y-gap))); + } + + @Override + public Dimension getPreferredSize() { + int maxW = 0; + int h = 0; + for (MPanel childComponent : getChildComponents()) { + Dimension preferedSize = childComponent.getPreferredSize(); + int height = Math.max(10, preferedSize.height); + if (preferedSize.width > maxW) maxW = preferedSize.width; + h += height; + if (gap > 0) h += gap; + } + return new Dimension(maxW, Math.max(0, h-gap)); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + if (gap <= 0) return; + if (!drawLine) return; + for (int i = 1; i < getChildComponents().size(); i++) { + MPanel panel = getChildComponents().get(i); + Rectangle bound = panel.getBounds(); + int top = bound.y - (int)Math.ceil(gap/2.0); + Gui.drawRect(0, top, getBounds().width, top + 1, gapLineColor); + } + } + + @Override + public void add(MPanel child) { + super.add(child); + realignChildren(); + } + + @Override + public void remove(MPanel panel) { + super.remove(panel); + realignChildren(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MModal.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MModal.java new file mode 100644 index 00000000..be2c64d6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MModal.java @@ -0,0 +1,92 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; + +import java.awt.*; + +public class MModal extends MTooltip { + @Getter + private MPanel modalContent = new MPanel(); + + @Getter @Setter + private String title = "Default Title"; + + public MModal() { + super.add(modalContent); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + super.resize(parentWidth, parentHeight); + setBounds(new Rectangle(0,0, parentWidth, parentHeight)); + } + + @Getter @Setter + private Dimension modalSize = new Dimension(300,200); + + + @Override + public void onBoundsUpdate() { + super.onBoundsUpdate(); + Dimension effDim = getEffectiveDimension(); + + modalContent.setBounds(new Rectangle((effDim.width - modalSize.width)/2, (effDim.height - modalSize.height)/2 + 16, modalSize.width, modalSize.height-16)); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + RenderUtils.drawGradientRect(0, 0, bounds.width, bounds.height, -1072689136, -804253680); + Dimension effDim = getEffectiveDimension(); + int x = (effDim.width-modalSize.width)/2; + int y = (effDim.height - modalSize.height)/2; + GlStateManager.translate(x,y, 0); + RenderUtils.drawRoundedRectangle(0,0,modalSize.width, modalSize.height, 3, Math.PI/8, RenderUtils.blendAlpha(0x141414, 0.20f)); + Gui.drawRect(0,15, modalSize.width, 16, 0xFF02EE67); + Gui.drawRect(0,16,modalSize.width, 26, RenderUtils.blendAlpha(0x141414, 0.1f)); + RenderUtils.drawRoundedRectangle(0,16,modalSize.width, modalSize.height-16, 3, Math.PI/8, RenderUtils.blendAlpha(0x141414, 0.1f)); + + GlStateManager.enableTexture2D(); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + fr.drawString(title, 5,(16-fr.FONT_HEIGHT)/2, -1); + } + + @Override + public void add(MPanel child) { + modalContent.add(child); + } + + protected void addSuper(MPanel child) { + super.add(child); + } + + @Override + public void remove(MPanel panel) { + modalContent.remove(panel); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MModalConfirmation.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MModalConfirmation.java new file mode 100644 index 00000000..92f3b258 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MModalConfirmation.java @@ -0,0 +1,87 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + +public class MModalConfirmation extends MModal { + private String content; + private Runnable callBackYes; + private Runnable callBackNo; + @Getter + private MButton yes, no; + public MModalConfirmation(String title, String content, Runnable callBackYes, Runnable callBackNo) { + super(); + setTitle(title); + this.content = content; + this.callBackYes = callBackYes; + this.callBackNo = callBackNo; + this.yes = new MButton(); + this.no = new MButton(); + yes.setText("Yes"); no.setText("No"); + no.setBackground(RenderUtils.blendAlpha(0x141414, 0.15f)); + no.setHover(RenderUtils.blendAlpha(0x141414, 0.17f)); + yes.setOnActionPerformed(() -> { + close(); + if (callBackYes != null) callBackYes.run(); + }); + no.setOnActionPerformed(() -> { + close(); + if (callBackNo != null) callBackNo.run(); + }); + yes.setBackground(RenderUtils.blendAlpha(0x141414, 0.15f)); + yes.setHover(RenderUtils.blendAlpha(0x141414, 0.17f)); + + add(new ConfirmationContent()); + } + + public class ConfirmationContent extends MPanel { + public ConfirmationContent() { + add(yes); add(no); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + GlStateManager.translate(5,5,0); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GL11.glDisable(GL11.GL_SCISSOR_TEST); + fr.drawSplitString(content, 0,0, ConfirmationContent.this.bounds.width-10, -1); + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + yes.setBounds(new Rectangle(10,bounds.height-25,(bounds.width-30)/2, 15)); + no.setBounds(new Rectangle(yes.getBounds().x + yes.getBounds().width + 10,bounds.height-25,(bounds.width-30)/2, 15)); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MModalMessage.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MModalMessage.java new file mode 100644 index 00000000..28d23d48 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MModalMessage.java @@ -0,0 +1,77 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + +public class MModalMessage extends MModal { + private String content; + private Runnable callBackOk; + @Getter + private MButton yes; + public MModalMessage(String title, String content, Runnable callBackOk) { + super(); + setTitle(title); + this.content = content; + this.callBackOk = callBackOk; + this.yes = new MButton(); + yes.setText("Ok"); + yes.setOnActionPerformed(() -> { + close(); + if (callBackOk != null) callBackOk.run(); + }); + yes.setBackground(RenderUtils.blendAlpha(0x141414, 0.15f)); + yes.setHover(RenderUtils.blendAlpha(0x141414, 0.17f)); + + add(new MessageContent()); + } + + public class MessageContent extends MPanel { + public MessageContent() { + add(yes); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + GlStateManager.translate(5,5,0); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GL11.glDisable(GL11.GL_SCISSOR_TEST); + fr.drawSplitString(content, 0,0, MModalMessage.MessageContent.this.bounds.width-10, -1); + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + yes.setBounds(new Rectangle(10,bounds.height-25,(bounds.width-20), 15)); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MNavigatingPane.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MNavigatingPane.java new file mode 100755 index 00000000..2f5f68de --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MNavigatingPane.java @@ -0,0 +1,213 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import com.google.common.base.Function; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class MNavigatingPane extends MPanel { + + private final Map<String, MPanel> pages = new HashMap<String, MPanel>(); + private final List<MTabButton> bookMarks = new ArrayList<MTabButton>(); + + @Getter + @Setter + private Function<String, MPanel> pageGenerator; + + @Getter + private String currentPage = ""; + + public void setCurrentPage(String currentPage) { + this.history.push(this.currentPage); + this.currentPage = currentPage; + } + + @Getter + private Color background2; + + private final Stack<String> history = new Stack<String>(); + + private final MButton back = new MButton(); + + public MNavigatingPane() { + back.setText("<"); + back.setOnActionPerformed(new Runnable() { + @Override + public void run() { + if (history.size() > 0) + currentPage = history.pop(); + } + }); + back.setBackgroundColor(Color.darkGray); + back.setBounds(new Rectangle(3,18,12,12)); + add(back); + } + + public void setBackground2(Color background2) { + this.background2 = background2; + for (MPanel value : pages.values()) { + value.setBackgroundColor(background2); + } + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + + Gui.drawRect(0, 15, getBounds().width, getBounds().height, 0xFF444444); + Gui.drawRect(1, 16, getBounds().width-1, getBounds().height-1, background2 != null ? background2.getRGB() : 0); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(currentPage.replace(".", " > "), 20, 20, 0xFFFFFFFF); + + } + + public void addBookmark(String name, String addr) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + MTabButton button = new MTabButton(this, name, addr); + int totalX = 0; + for (MTabButton button1:bookMarks) + totalX += button1.getBounds().width; + button.setBounds(new Rectangle(totalX, 0, Math.max(25, fr.getStringWidth(name) + 6), 15)); + bookMarks.add(button); + if (currentPage.isEmpty()) + currentPage = addr; + } + public void addBookmarkRunnable(String name, final Runnable toRun) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + MTabButton button = new MTabButton(this, name, null) { + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (lastAbsClip.contains(absMouseX, absMouseY)) { + toRun.run(); + } + } + }; + int totalX = 0; + for (MTabButton button1:bookMarks) + totalX += button1.getBounds().width; + button.setBounds(new Rectangle(totalX, 0, Math.max(25, fr.getStringWidth(name) + 6), 15)); + bookMarks.add(button); + } + + @Override + public List<MPanel> getChildComponents() { + ArrayList<MPanel> dynamic = new ArrayList<MPanel>(bookMarks); + if (!pages.containsKey(currentPage)) { + MPanel panel = pageGenerator.apply(currentPage); + MPanel panel2 = new MPanel() ; + if (panel != null) + panel2.add(panel); + panel2.setBackgroundColor(background2); + pages.put(currentPage, panel2); + panel2.setBounds(new Rectangle(1,30,getBounds().width-2, getBounds().height-31)); + panel2.setParent(this); + } + dynamic.add(pages.get(currentPage)); + dynamic.add(back); + return dynamic; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + for (MPanel ma:pages.values()) + ma.setBounds(new Rectangle(1,30,getBounds().width-2, getBounds().height-31)); + } + + @Override + public void setBounds(Rectangle bounds) { + if (bounds == null) return; + this.bounds.x = bounds.x; + this.bounds.y = bounds.y; + this.bounds.width = bounds.width; + this.bounds.height = bounds.height; + } + + @Getter + @Setter + public static class MTabButton extends MPanel { + private String text; + private String address; + + private Color foreground = Color.white; + private Color hover = new Color(154, 154, 154, 255); + private Color clicked = new Color(88, 88, 88,255); + private Color selected = new Color(111, 111, 111,255); + private Color disabled = new Color(0,0,0); + + private boolean enabled = true; + + private MNavigatingPane tabbedPane; + + public MTabButton(MNavigatingPane tabbedPane, String key, String address) { + this.tabbedPane = tabbedPane; + this.text = key; + this.address = address; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + Dimension bounds = getSize(); + + Color bg = null; + if (!enabled) { + bg = disabled; + } else if (tabbedPane.getCurrentPage().equals(address)) { + bg = selected; + } else if (new Rectangle(new Point(0,0),bounds).contains(relMousex0, relMousey0)) { + bg = hover; + } + Gui.drawRect(0, tabbedPane.getCurrentPage().equals(address) ? 0 : 2, getBounds().width, getBounds().height, 0xFF444444); + if (bg != null) + Gui.drawRect(1,tabbedPane.getCurrentPage().equals(address) ? 1 : 3,getBounds().width - 1, getBounds().height, bg.getRGB()); + + FontRenderer renderer = Minecraft.getMinecraft().fontRendererObj; + int width = renderer.getStringWidth(text); + int x = (getBounds().width - width) / 2; + int y = (getBounds().height - 3 - renderer.FONT_HEIGHT) / 2 + 3; + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + renderer.drawString(text, x,y, foreground.getRGB()); + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (lastAbsClip.contains(absMouseX, absMouseY)) { + tabbedPane.setCurrentPage(address); + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPanelScaledGUI.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPanelScaledGUI.java new file mode 100644 index 00000000..9d13e5d9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPanelScaledGUI.java @@ -0,0 +1,213 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + +public class MPanelScaledGUI extends MPanel { + @Getter + protected double scale = 1.0; + @Getter + protected double relativeScale; + + public void setScale(double scale) { + this.scale = scale; + for (MPanel childComponent : childComponents) { + childComponent.resize0((int) (getBounds().width/scale), (int) (getBounds().height/scale)); + } + onBoundsUpdate(); + } + + @Override + public void setBounds(Rectangle bounds) { + if (bounds == null) return; + this.bounds.x = bounds.x; + this.bounds.y = bounds.y; + this.bounds.width = bounds.width; + this.bounds.height = bounds.height; + + for (MPanel childComponent : childComponents) { + childComponent.resize0((int) (getBounds().width/scale), (int) (getBounds().height/scale)); + } + onBoundsUpdate(); + } + + public Dimension getEffectiveDimension() { + return new Dimension((int)(getBounds().width / scale), (int)(getBounds().height / scale)); + } + + @Override + public void render0(double parentScale, Point parentPoint, Rectangle parentClip, int absMousex0, int absMousey0, int relMousex0, int relMousey0, float partialTicks) { + lastParentPoint = parentPoint; + + GlStateManager.translate(getBounds().x, getBounds().y, 5); + GlStateManager.color(1,1,1,1); + + Rectangle absBound = getBounds().getBounds(); + absBound.setLocation(absBound.x + parentPoint.x, absBound.y + parentPoint.y); + + Rectangle clip; + if (isIgnoreBoundOnClip()) clip = parentClip; + else clip = determineClip(parentClip, absBound); + lastAbsClip = clip; + + if (clip.getSize().height * clip.getSize().width == 0) return; + + int absMousex = (int) (absMousex0 / scale), absMousey = (int) (absMousey0 / scale); + int relMousex = (int) ((relMousex0 - getBounds().x) / scale); + int relMousey = (int) ((relMousey0 - getBounds().y) /scale); + + // FROM HERE, IT IS SCALED + + GlStateManager.scale(this.scale, this.scale, 1); + clip = new Rectangle((int) (clip.x / scale), (int) (clip.y / scale), (int) (clip.width / scale), (int) (clip.height / scale)); + lastAbsClip = clip; + + + this.relativeScale = parentScale * this.scale; + clip(clip.x, clip.y, clip.width, clip.height); + + + + GL11.glEnable(GL11.GL_SCISSOR_TEST); + + + GuiScreen.drawRect(0,0, (int) (getBounds().width / scale), (int) (getBounds().height / scale), backgroundColor.getRGB()); + GlStateManager.enableBlend(); + + + GlStateManager.pushMatrix(); + + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); + + render(absMousex, absMousey, relMousex, relMousey, partialTicks, clip); + + GlStateManager.popMatrix(); + + GL11.glDisable(GL11.GL_SCISSOR_TEST); + + + + Point newPt = new Point((int) ((parentPoint.x + getBounds().x) / scale), (int) ((parentPoint.y + getBounds().y) / scale)); + + for (MPanel mPanel : getChildComponents()){ + GlStateManager.pushMatrix(); + + mPanel.render0(relativeScale, newPt,clip,absMousex, absMousey, relMousex, relMousey, partialTicks); + + GlStateManager.popMatrix(); + } + } + + @Override + public void clip(int x, int y, int width, int height) { + if (width < 0 || height < 0) return; + + GL11.glScissor((int) (x * relativeScale), Minecraft.getMinecraft().displayHeight - (int) ((y + height+1) * relativeScale), (int)((width+1)* relativeScale), (int) ((height+1) * relativeScale)); + } + + @Override + public void resize0(int parentWidth, int parentHeight) { + super.resize0(parentWidth, parentHeight); + } + + + public boolean mouseClicked0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int mouseButton) { + int relMousex = (int) ((relMouseX0 - getBounds().x) / scale); + int relMousey = (int) ((relMouseY0 - getBounds().y) / scale); + absMouseX = (int) (absMouseX / scale); + absMouseY = (int) (absMouseY / scale); + + boolean noClip = true; + boolean focusedOverall = false; + for (MPanel childComponent : getChildComponents()) { + if (childComponent.mouseClicked0(absMouseX, absMouseY,relMousex, relMousey, mouseButton)) { + noClip = false; + focusedOverall = true; + } + } + + if (getBounds().contains(relMouseX0, relMouseY0) && noClip) { + isFocused = true; + focusedOverall = true; + } else { + isFocused = false; + } + mouseClicked(absMouseX, absMouseY, relMousex, relMousey, mouseButton); + + return focusedOverall; + } + public void mouseReleased0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int state) { + int relMousex = (int) ((relMouseX0 - getBounds().x) / scale); + int relMousey = (int) ((relMouseY0 - getBounds().y) / scale); + absMouseX = (int) (absMouseX / scale); + absMouseY = (int) (absMouseY / scale); + + for (MPanel childComponent : getChildComponents()) { + childComponent.mouseReleased0(absMouseX, absMouseY, relMousex, relMousey, state); + } + mouseReleased(absMouseX, absMouseY, relMousex, relMousey, state); + } + public void mouseClickMove0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int clickedMouseButton, long timeSinceLastClick) { + int relMousex = (int) ((relMouseX0 - getBounds().x) / scale); + int relMousey = (int) ((relMouseY0 - getBounds().y) / scale); + absMouseX = (int) (absMouseX / scale); + absMouseY = (int) (absMouseY / scale); + + for (MPanel childComponent : getChildComponents()) { + childComponent.mouseClickMove0(absMouseX, absMouseY, relMousex, relMousey, clickedMouseButton, timeSinceLastClick); + } + mouseClickMove(absMouseX, absMouseY, relMousex, relMousey, clickedMouseButton, timeSinceLastClick); + } + public void mouseScrolled0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + int relMousex = (int) ((relMouseX0 - getBounds().x) / scale); + int relMousey = (int) ((relMouseY0 - getBounds().y) / scale); + absMouseX = (int) (absMouseX / scale); + absMouseY = (int) (absMouseY / scale); + + for (MPanel childComponent : getChildComponents()) { + childComponent.mouseScrolled0(absMouseX, absMouseY, relMousex, relMousey, scrollAmount); + } + mouseScrolled(absMouseX, absMouseY, relMousex, relMousey, scrollAmount); + } + + @Override + public void mouseMoved0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + int relMousex = (int) ((relMouseX0 - getBounds().x) / scale); + int relMousey = (int) ((relMouseY0 - getBounds().y) / scale); + absMouseX = (int) (absMouseX / scale); + absMouseY = (int) (absMouseY / scale); + + mouseMoved(absMouseX, absMouseY, relMousex, relMousey); + for (MPanel childComponent : getChildComponents()) { + childComponent.mouseMoved0(absMouseX, absMouseY, relMousex, relMousey); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MParameter.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MParameter.java new file mode 100755 index 00000000..cd9a89e1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MParameter.java @@ -0,0 +1,90 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonParameterEdit; +import kr.syeyoung.dungeonsguide.roomedit.panes.DynamicEditor; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.gui.Gui; + +import java.awt.*; + +public class MParameter extends MPanel { + private final MLabel label; + private final MLabel data; + + @Getter @Setter + private Color hover = Color.gray; + + @Getter @Setter + private Parameter parameter; + private final DynamicEditor processorParameterEditPane; + + public MParameter(final Parameter parameter, DynamicEditor processorParameterEditPane) { + this.processorParameterEditPane = processorParameterEditPane; + this.add(this.label = new MLabel() { + @Override + public String getText() { + return parameter.getName(); + } + }); + this.add(this.data = new MLabel() { + @Override + public String getText() { + return parameter.getNewData() != null ?parameter.getNewData().toString() :"-empty-"; + } + }); + this.label.setAlignment(MLabel.Alignment.LEFT); + this.data.setAlignment(MLabel.Alignment.RIGHT); + + this.parameter = parameter; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + if (hover != null && new Rectangle(new Point(0,0),getBounds().getSize()).contains(relMousex0, relMousey0)) { + Gui.drawRect(0,0,getBounds().width, getBounds().height, hover.getRGB()); + } + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (this.getBounds().x > -20 && lastAbsClip.contains(absMouseX, absMouseY)) { + // open new gui; + EditingContext.getEditingContext().openGui(new GuiDungeonParameterEdit(this, processorParameterEditPane)); + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setSize(new Dimension(parentWidth, getBounds().height)); + label.setBounds(new Rectangle(0,0,parentHeight / 3, getBounds().height)); + data.setBounds(new Rectangle(parentWidth / 3,0,parentWidth / 3 * 2, getBounds().height)); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width / 3, getBounds().height)); + data.setBounds(new Rectangle(getBounds().width / 3,0,getBounds().width / 3 * 2, getBounds().height)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPassiveLabelAndElement.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPassiveLabelAndElement.java new file mode 100755 index 00000000..a1d6334b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPassiveLabelAndElement.java @@ -0,0 +1,71 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.gui.Gui; + +import java.awt.*; + +public class MPassiveLabelAndElement extends MPanel { + private final MLabel label; + private final MPanel element; + + @Getter @Setter + private Color hover; + @Getter @Setter + private Runnable onClick; + + @Getter @Setter + private double divideRatio = 1/3.0; + + public MPassiveLabelAndElement(String label, MPanel element) { + this.add(this.label = new MLabel()); + this.label.setText(label); + this.add(element); + this.element = element; + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(100, 20); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + if (hover != null && new Rectangle(new Point(0,0),getBounds().getSize()).contains(relMousex0, relMousey0)) { + Gui.drawRect(0,0,getBounds().width, getBounds().height, hover.getRGB()); + } + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (onClick!= null && lastAbsClip.contains(absMouseX, absMouseY)) { + onClick.run(); + } + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0, (int) (getBounds().width * divideRatio), getBounds().height)); + element.setBounds(new Rectangle((int) (getBounds().width * divideRatio),0, (int) (getBounds().width * (1-divideRatio)), getBounds().height)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPopupMenu.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPopupMenu.java new file mode 100644 index 00000000..7b728958 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPopupMenu.java @@ -0,0 +1,97 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; + +import java.awt.*; +import java.util.List; + +public class MPopupMenu extends MTooltip { + private int x, y; + public MPopupMenu(int x, int y, List<MPanel> popupMenuElementList) { + this.x = x; this.y = y; + int maxWidth = 150; + for (MPanel mPanel : popupMenuElementList) { + Dimension dimension = mPanel.getPreferredSize(); + if (dimension.width > maxWidth) maxWidth = dimension.width; + } + int h1 = 7; + for (MPanel mPanel : popupMenuElementList) { + Dimension dimension = mPanel.getPreferredSize(); + mPanel.setBounds(new Rectangle(7,h1, maxWidth-13, dimension.height)); + h1 += dimension.height + 7; + add(mPanel); + } + + if (y + h1 > Minecraft.getMinecraft().displayHeight) + y = Minecraft.getMinecraft().displayHeight - h1; + if (x + maxWidth+ 2 > Minecraft.getMinecraft().displayWidth) + x = Minecraft.getMinecraft().displayWidth - maxWidth-2; + setBounds(new Rectangle(x,y,maxWidth+2, h1)); + } + + @Override + public void setScale(double scale) { + super.setScale(scale); + + int maxWidth = 150; + for (MPanel mPanel : getChildComponents()) { + Dimension dimension = mPanel.getPreferredSize(); + if (dimension.width > maxWidth) maxWidth = dimension.width; + } + int h1 = 7; + for (MPanel mPanel : getChildComponents()) { + Dimension dimension = mPanel.getPreferredSize(); + mPanel.setBounds(new Rectangle(7,h1, maxWidth-13, dimension.height)); + h1 += dimension.height + 7; + } + maxWidth += 2; + maxWidth *= scale; h1 *= scale; + + if (y + h1 > Minecraft.getMinecraft().displayHeight) + y = Minecraft.getMinecraft().displayHeight - h1; + if (x + maxWidth > Minecraft.getMinecraft().displayWidth) + x = Minecraft.getMinecraft().displayWidth - maxWidth; + setBounds(new Rectangle(x,y,maxWidth, h1)); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + super.render(absMousex, absMousey, relMousex0, relMousey0, partialTicks, scissor); + int radius = 7; + double deltaDegree = Math.PI/6; + Dimension effectiveDim = getEffectiveDimension(); + RenderUtils.drawRoundedRectangle(0,0,effectiveDim.width,effectiveDim.height,radius,deltaDegree, RenderUtils.blendAlpha(0x121212, 0.0f)); + for (int i = 1; i < getChildComponents().size(); i++) { + MPanel childComponent = getChildComponents().get(i); + Gui.drawRect(7,childComponent.getBounds().y - 4, effectiveDim.width-7, childComponent.getBounds().y - 3, RenderUtils.blendAlpha(0x121212, 0.10f)); + } + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (!lastAbsClip.contains(absMouseX, absMouseY)) { + close(); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPortableColorEdit.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPortableColorEdit.java new file mode 100644 index 00000000..4e382d58 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MPortableColorEdit.java @@ -0,0 +1,292 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.MathHelper; +import org.apache.commons.lang3.StringUtils; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + +public class MPortableColorEdit extends MTooltip { + + private final float[] hsv = new float[3]; + private float alpha = 0; + private float chromaSpeed = 0; + + @Getter + private AColor color; + + private final MTextField textField; + + public MPortableColorEdit() { + textField = new MTextField() { + @Override + public void edit(String str) { + if (str.length() >= 7 && str.startsWith("#")) { + String color = str.substring(1); + try { + long colorInt = Long.parseLong(color, 16); + + Color.RGBtoHSB((int) (colorInt >> 16) & 0xFF, (int) (colorInt >> 8) & 0xFF, (int) colorInt & 0xFF, hsv); + if (color.length() >= 8) + alpha = ((int) ((colorInt >> 24) & 0xFF)) / 255.0f; + update2(); + } catch (Exception e) {} + } + } + }; + add(textField); + } + + @Override + public void onBoundsUpdate() { + super.onBoundsUpdate(); + + textField.setBounds(new Rectangle(5, getEffectiveDimension().height - 25, getEffectiveDimension().width - 10, 20)); + } + + public void setColor(AColor color) { + this.color = color; + + alpha = color.getAlpha() / 255.0f; + chromaSpeed = color.isChroma() ? color.getChromaSpeed() : 0; + Color.RGBtoHSB(color.getRed(), color.getBlue(), color.getGreen(), hsv); + + int rgb = Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]); + rgb = (rgb & 0xFFFFFF) | ((int)(alpha * 255) << 24); + textField.setText("#" + StringUtils.leftPad(Integer.toHexString(rgb).toUpperCase(), 8, '0')); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + Dimension size = getEffectiveDimension(); + + Gui.drawRect(0,0,size.width,size.height, 0xff333333); + Gui.drawRect(1,1,size.width-1,size.height-1, 0xffa1a1a1); + + int width = size.height- 35; + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + int shademodel = GL11.glGetInteger(GL11.GL_SHADE_MODEL); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + GlStateManager.enableBlend(); + GlStateManager.disableDepth(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + // worldrenderer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR); + + int rgb = Color.HSBtoRGB(hsv[0], hsv[1], 1); + float r = (rgb >> 16 & 255) / 255.0f; + float g = (rgb >> 8 & 255) / 255.0f; + float b = (rgb & 255) / 255.0f; + GL11.glBegin(GL11.GL_TRIANGLES); + GlStateManager.color(0,0,0,alpha);GL11.glVertex3i(15+width ,5, 0); + GlStateManager.color(0,0,0,alpha);GL11.glVertex3i(10+width , 5, 0); + GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(15+width , 5+width, 0); + + GlStateManager.color(0,0,0,alpha); GL11.glVertex3i(10+width , 5, 0); + GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(10+width , 5 + width, 0); + GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(15+width , 5+width, 0); + GL11.glEnd(); + rgb = Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]); + r = (rgb >> 16 & 255) / 255.0f; + g = (rgb >> 8 & 255) / 255.0f; + b = (rgb & 255) / 255.0f; + GL11.glBegin(GL11.GL_TRIANGLES); + GlStateManager.color(r,g,b,0);GL11.glVertex3i(25+width ,5, 0); + GlStateManager.color(r,g,b,0);GL11.glVertex3i(20+width , 5, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(25+width , 5+width, 0); + + GlStateManager.color(r,g,b,0); GL11.glVertex3i(20+width , 5, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(20+width , 5+ width, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(25+width , 5+width, 0); + GL11.glEnd(); + + + GL11.glBegin(GL11.GL_TRIANGLES); + rgb = RenderUtils.getChromaColorAt(0,0, chromaSpeed, hsv[1], hsv[2], alpha); + r = (rgb >> 16 & 255) / 255.0f; + g = (rgb >> 8 & 255) / 255.0f; + b = (rgb & 255) / 255.0f; + GlStateManager.color(r,g,b,1);GL11.glVertex3i(35+width ,5, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(30+width , 5, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(35+width , 5+width, 0); + + GlStateManager.color(r,g,b,1); GL11.glVertex3i(30+width , 5, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(30+width , 5+ width, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(35+width , 5+width, 0); + GL11.glEnd(); + + + + float radius = width/2f; + float cx = 5 + radius; + float cy = 5 + radius; + + GL11.glBegin(GL11.GL_TRIANGLE_FAN); + GlStateManager.color(1,1,1,alpha); + GL11.glVertex3f(cx,cy,0); + for (int i = 0; i <= 360; i++) { + float rad = 3.141592653f * i / 180; + int rgb2 = Color.HSBtoRGB(i / 360f, 1, hsv[2]); + float r2 = (rgb2 >> 16 & 255) / 255.0f; + float g2 = (rgb2 >> 8 & 255) / 255.0f; + float b2 = (rgb2 & 255) / 255.0f; + GlStateManager.color(r2,g2,b2, alpha); + GL11.glVertex3f(MathHelper.sin(rad) * radius + cx, MathHelper.cos(rad) * radius + cy, 0); + } + GL11.glEnd(); + GlStateManager.shadeModel(shademodel); + + GlStateManager.color(1,1,1,1); + worldrenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION); + float rad2 = 2 * 3.141592653f * hsv[0] ; + float x = 5 + radius + (MathHelper.sin(rad2)) * hsv[1] * radius; + float y = 5 + radius + (MathHelper.cos(rad2))* hsv[1] * radius; + for (int i = 0; i < 100; i++) { + float rad = 2 * 3.141592653f * (i / 100f); + worldrenderer.pos(MathHelper.sin(rad) * 2 + x, MathHelper.cos(rad) * 2 + y, 0).endVertex(); + } + tessellator.draw(); + + worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + worldrenderer.pos(8+width, 5 + (hsv[2]) * width, 0.5).endVertex(); + worldrenderer.pos(17+width, 5 + (hsv[2]) * width, 0.5).endVertex(); + tessellator.draw(); + + worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + worldrenderer.pos(18+width, 5 + (alpha) * width, 0.5).endVertex(); + worldrenderer.pos(27+width, 5 + (alpha) * width, 0.5).endVertex(); + tessellator.draw(); + + worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + worldrenderer.pos(28+width, 5 + (chromaSpeed) * width, 0.5).endVertex(); + worldrenderer.pos(37+width, 5 + (chromaSpeed) * width, 0.5).endVertex(); + tessellator.draw(); + + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + GlStateManager.color(1,1,1,1); + GlStateManager.color(1,1,1,1); + } + + private int selected = 0; + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + int width = getEffectiveDimension().height- 35; + float radius = width / 2f; + float circleX = 5 + radius; + float circleY = 5 + radius; + + selected = 0; + if (!lastAbsClip.contains(absMouseX, absMouseY)) { + close(); + return; + } + + { + // check circle + float dx = relMouseX - circleX; + float dy = circleY - relMouseY; + if (dx * dx + dy * dy <= radius * radius) { + double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180+90) % 360; + hsv[0] = (float) theta / 360f; + hsv[1] = MathHelper.sqrt_float(dx * dx + dy * dy) / radius; + selected = 1; + } + } + { + if (10+width <= relMouseX && relMouseX <= 15 + width && + 5 <= relMouseY && relMouseY <= 5 + width) { + hsv[2] = (relMouseY - 5) / (float)width; + selected = 2; + } + } + { + if (20+width <= relMouseX && relMouseX <= 25 + width && + 5 <= relMouseY && relMouseY <= 5 + width) { + alpha = (relMouseY - 5) / (float)width; + selected = 3; + } + } + { + if (30+width <= relMouseX && relMouseX <= 35 + width && + 5 <= relMouseY && relMouseY <= 5 + width) { + chromaSpeed = (relMouseY - 5) / (float)width; + selected = 4; + } + } + update(); + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + int width = getEffectiveDimension().height- 35; + float radius = width / 2f; + float circleX = 5 + radius; + float circleY = 5 + radius; + { + // check circle + float dx = relMouseX - circleX; // sin theta + float dy = circleY - relMouseY; // cos theta + if (selected == 1) { + double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180+90) % 360; + hsv[0] = (float) theta / 360f; + hsv[1] = MathHelper.clamp_float(MathHelper.sqrt_float(dx * dx + dy * dy) / radius, 0, 1); + } + } + { + if (selected == 2) { + hsv[2] = MathHelper.clamp_float((relMouseY - 5) / (float)width, 0, 1); + } + if (selected == 3) { + alpha = MathHelper.clamp_float((relMouseY - 5) / (float)width, 0, 1); + } + if (selected == 4) { + chromaSpeed = MathHelper.clamp_float((relMouseY - 5) / (float)width, 0, 1); + } + } + update(); + } + + + public void update() { + int rgb = Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]); + rgb = (rgb & 0xFFFFFF) | ((int)(alpha * 255) << 24); + textField.setText("#" + StringUtils.leftPad(Integer.toHexString(rgb).toUpperCase(), 8, '0')); + update2(); + } + + public void update2() { + color = new AColor(Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0xffffff | (MathHelper.clamp_int((int)(alpha * 255), 0, 255) << 24), true); + color.setChromaSpeed(chromaSpeed); + color.setChroma(chromaSpeed != 0); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MRootPanel.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MRootPanel.java new file mode 100644 index 00000000..ec8bcf70 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MRootPanel.java @@ -0,0 +1,60 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +@Getter +public class MRootPanel extends MPanel { + @Getter + private List<MTooltip> tooltips = new CopyOnWriteArrayList<>(); + + + @Override + public void openTooltip(MTooltip mPanel) { + mPanel.setRoot(this); + tooltips.add(mPanel); + mPanel.resize(getBounds().width, getBounds().height); + add(mPanel); + } + + @Override + public int getTooltipsOpen() { + return tooltips.size(); + } + + public void removeTooltip(MTooltip mTooltip) { + mTooltip.setRoot(null); + tooltips.remove(mTooltip); + remove(mTooltip); + } + + @Getter @Setter + private EnumCursor currentCursor = EnumCursor.DEFAULT; + @Override + public void setCursor(EnumCursor enumCursor) { + currentCursor = enumCursor; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollBar.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollBar.java new file mode 100644 index 00000000..6cb3b16d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollBar.java @@ -0,0 +1,209 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.gui.Gui; +import net.minecraft.util.MathHelper; + +import java.awt.*; + +public class MScrollBar extends MPanel { + private final Axis axis; + @Setter + @Getter + private int thumbSize, max, min; + @Setter + @Getter + private int current; + + @Getter + @Setter + private int width = 10; + + public void setMax(int max) { + if (max < min) max = min; + this.max = max; + + current = MathHelper.clamp_int(current, min, max); + if (onUpdate != null) onUpdate.run(); + } + + public void setMin(int min) { + if (max < min) max = min; + this.min = min; + + current = MathHelper.clamp_int(current, min, max); + if (onUpdate != null) onUpdate.run(); + } + + public void setThumbSize(int thumbSize) { + this.thumbSize = thumbSize; + + current = MathHelper.clamp_int(current, min, max); + if (onUpdate != null) onUpdate.run(); + } + + public void addToCurrent(int dv) { + int current2 = current + dv; + + current = MathHelper.clamp_int(current2, min, max); + + if (onUpdate != null) onUpdate.run(); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(axis == Axis.X ? -1 : width, axis == Axis.Y ? -1 : width); + } + + @Getter + @Setter + private int background = RenderUtils.blendAlpha(0xFF141414, 0.04f), + thumb = RenderUtils.blendAlpha(0xFF141414, 0.14f), + thumbHover = RenderUtils.blendAlpha(0xFF141414, 0.15f), + thumbClick = RenderUtils.blendAlpha(0xFF141414, 0.20f); + + private Runnable onUpdate; + + public MScrollBar(int min, int max, int thumbSize, int current, Axis axis, Runnable onUpdate) { + if (max < min) max = min; + this.min = min; this.min = max; this.thumbSize = thumbSize; this.current = current; this.axis = axis; + this.current = MathHelper.clamp_int(current, min, max); + this.onUpdate = onUpdate; + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + lastThumbRect.width = 0; lastThumbRect.height = 0; + } + + private Rectangle lastThumbRect = new Rectangle(); + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + // RENDER SUPER NICE SCROLL BAR + int minimalThumbLen = 20; + + Gui.drawRect(0,0,getBounds().width, getBounds().height, background); + int length = axis == Axis.X ? bounds.width :bounds.height; + int totalUnscaledLength = max-min + thumbSize; + double subPoint = ((double)max-min) * length / totalUnscaledLength; + if (length - subPoint < minimalThumbLen) { + subPoint = length - minimalThumbLen; + } + double thumbSize = length - subPoint; + + double startPt; + if (max - min == 0) { + startPt =0; + } else { + startPt = subPoint * (current - min)/((double)max - min); + } + + int color = thumbHover; + if (getBounds().contains(relMousex0, relMousey0)) color = thumbHover; + if (grabbed) color = thumbClick; + + if (axis == Axis.X) { + int startX = (int) startPt; + int endX = (int) (startPt + thumbSize); + + Gui.drawRect(startX,0,endX,getBounds().height, color); + lastThumbRect.x = startX; lastThumbRect.y = 0; lastThumbRect.width = endX - startX; lastThumbRect.height = getBounds().height; + } else if (axis == Axis.Y) { + int startY = (int) startPt; + int endY = (int) (startPt + thumbSize); + + Gui.drawRect(0,startY,getBounds().width,endY, color); + lastThumbRect.x = 0; lastThumbRect.y = startY; lastThumbRect.width = getBounds().width; lastThumbRect.height = endY - startY; + } + } + + private int lastX; + private int lastY; + private int actualValue; + private boolean grabbed; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (!lastAbsClip.contains(absMouseX, absMouseY)) return; + if (getTooltipsOpen() > 0) return; + grabbed = true; + actualValue = current; + lastX = absMouseX; + lastY = absMouseY; + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + if (!grabbed) return; + + int minimalThumbLen = 20; + + Gui.drawRect(0,0,getBounds().width, getBounds().height, background); + int length = axis == Axis.X ? bounds.width :bounds.height; + int totalUnscaledLength = max-min + thumbSize; + double subPoint = ((double)max-min) * length / totalUnscaledLength; + if (length - subPoint < minimalThumbLen) { + subPoint = length - minimalThumbLen; + } + double thumbSize = length - subPoint; + + + + int dx = absMouseX - lastX, dy = absMouseY - lastY; + + lastX = absMouseX; + lastY = absMouseY; + + int prevVal = current; + if (axis == Axis.Y) { + actualValue += dy * (max - min) / subPoint; + } else if (axis == Axis.X) { + actualValue += dx * (max - min) / subPoint; + } + + current = MathHelper.clamp_int(actualValue, min, max); + + if (onUpdate != null && prevVal != current) onUpdate.run(); + } + + @Override + public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) { + grabbed= false; + } + + public static enum Axis { + X, Y + } + + + @Override + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + if (grabbed) + setCursor(EnumCursor.CLOSED_HAND); + else if (lastThumbRect.contains(relMouseX0, relMouseY0)) { + setCursor(EnumCursor.OPEN_HAND); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollablePanel.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollablePanel.java new file mode 100644 index 00000000..64898fd9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MScrollablePanel.java @@ -0,0 +1,185 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import net.minecraft.client.gui.Gui; +import net.minecraft.util.MathHelper; + +import java.awt.*; + +public class MScrollablePanel extends MPanel { + @Getter + private boolean hideScrollBarWhenNotNecessary = false; + + public void setHideScrollBarWhenNotNecessary(boolean hideScrollBarWhenNotNecessary) { + this.hideScrollBarWhenNotNecessary = hideScrollBarWhenNotNecessary; + setBounds(getBounds()); + } + + private final int axis; // 1: Y 2: X 3: both. + + + private MPanel viewPort; + @Getter + private MPanel contentArea; + @Getter + private MScrollBar scrollBarX, scrollBarY; + + private Rectangle contentAreaDim; + + public MScrollablePanel(int axis) { + this.axis = axis; + viewPort = new MPanel(); + scrollBarX = new MScrollBar(0, 1, 1, 0, MScrollBar.Axis.X, this::onScrollBarUpdate); + scrollBarY = new MScrollBar(0, 1, 1, 0, MScrollBar.Axis.Y, this::onScrollBarUpdate); + + if ((axis & 1) > 0) + super.add(scrollBarY); + if ((axis & 2) > 0) + super.add(scrollBarX); + super.add(viewPort); + + + contentArea = new MPanel() { + @Override + public void add(MPanel child) { + super.add(child); + evalulateContentArea(); + } + + @Override + public void remove(MPanel panel) { + super.remove(panel); + evalulateContentArea(); + } + + @Override + public void setBounds(Rectangle bounds) { + if (bounds == null) return; + this.bounds.x = bounds.x; + this.bounds.y = bounds.y; + this.bounds.width = bounds.width; + this.bounds.height = bounds.height; + + onBoundsUpdate(); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + for (MPanel childComponent : childComponents) { + childComponent.resize0(parentWidth, parentHeight); + } + evalulateContentArea(); + } + }; + viewPort.add(contentArea); + contentArea.setIgnoreBoundOnClip(true); + evalulateContentArea(); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + super.render(absMousex, absMousey, relMousex0, relMousey0, partialTicks, scissor); + + boolean hideX = (axis & 2) == 0, hideY = (axis & 1) == 0; + if (bounds.width >= contentAreaDim.width && hideScrollBarWhenNotNecessary) hideX = true; + if (bounds.height >= contentAreaDim.height && hideScrollBarWhenNotNecessary) hideY = true; + if (axis == 3 && !(hideX && hideY)) { + Gui.drawRect(scrollBarX.getBounds().width, scrollBarY.getBounds().height, getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.03f)); + } + } + + public void evalulateContentArea() { + if (contentArea.getChildComponents().size() == 0) { + contentAreaDim= new Rectangle(0,0,0,0); + return; + } + int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE; + for (MPanel childComponent : contentArea.getChildComponents()) { + Rectangle bounds = childComponent.getBounds(); + if (bounds.x < minX) minX = bounds.x; + if (bounds.x + bounds.width > maxX) maxX = bounds.x + bounds.width; + if (bounds.y < minY) minY = bounds.y; + if (bounds.y + bounds.height > maxY) maxY = bounds.y + bounds.height; + } + contentAreaDim = new Rectangle(minX, minY, maxX - minX, maxY - minY); + scrollBarX.setMin(contentAreaDim.x); + scrollBarX.setMax(contentAreaDim.x + contentAreaDim.width-scrollBarX.getThumbSize()); + scrollBarY.setMin(contentAreaDim.y); + scrollBarY.setMax(contentAreaDim.y + contentAreaDim.height-scrollBarY.getThumbSize()); + } + + @Override + public void setBounds(Rectangle bounds) { + super.setBounds(bounds); + boolean hideX = (axis & 2) == 0, hideY = (axis & 1) == 0; + viewPort.setBounds(new Rectangle(0,0,bounds.width, bounds.height)); + evalulateContentArea(); + if (bounds.width >= contentAreaDim.width && hideScrollBarWhenNotNecessary) hideX = true; + if (bounds.height >= contentAreaDim.height && hideScrollBarWhenNotNecessary) hideY = true; + + if (!(hideX || hideY)) { + Dimension preferedX = scrollBarX.getPreferredSize(); + Dimension preferedY = scrollBarY.getPreferredSize(); + scrollBarY.setBounds(new Rectangle(bounds.width - preferedY.width, 0, preferedY.width, bounds.height - preferedX.height)); + scrollBarX.setBounds(new Rectangle(0, bounds.height - preferedX.height, bounds.width - preferedY.width, preferedX.height)); + } else if ((hideY && !hideX)) { + Dimension preferedX = scrollBarX.getPreferredSize(); + scrollBarY.setBounds(new Rectangle(0,0,0,0)); + scrollBarX.setBounds(new Rectangle(0, bounds.height - preferedX.height, bounds.width, preferedX.height)); + } else if ((hideX && !hideY)) { + Dimension preferedY = scrollBarY.getPreferredSize(); + scrollBarX.setBounds(new Rectangle(0,0,0,0)); + scrollBarY.setBounds(new Rectangle(bounds.width - preferedY.width, 0, preferedY.width, bounds.height)); + } else if (hideX && hideY){ + scrollBarY.setBounds(new Rectangle(0,0,0,0)); + scrollBarX.setBounds(new Rectangle(0,0,0,0)); + } + + viewPort.setBounds(new Rectangle(0,0,bounds.width-scrollBarY.getBounds().width, bounds.height - scrollBarX.getBounds().height)); + + scrollBarX.setThumbSize(viewPort.getBounds().width); + scrollBarY.setThumbSize(viewPort.getBounds().height); + scrollBarX.setMax(contentAreaDim.x + contentAreaDim.width-scrollBarX.getThumbSize()); + scrollBarY.setMax(contentAreaDim.y + contentAreaDim.height-scrollBarY.getThumbSize()); + evalulateContentArea(); + } + + + private void onScrollBarUpdate() { + contentArea.setPosition(new Point(-scrollBarX.getCurrent(), -scrollBarY.getCurrent())); + } + + + @Override + public void add(MPanel child) { contentArea.add(child); } + + @Override + public void remove(MPanel panel) { contentArea.remove(panel); } + + @Override + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (lastAbsClip.contains(absMouseX, absMouseY) && (axis == 1 || axis == 3)) { + scrollBarY.addToCurrent(MathHelper.clamp_int(scrollAmount, -1, 1) * -30); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MSpacer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MSpacer.java new file mode 100644 index 00000000..11336a7c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MSpacer.java @@ -0,0 +1,36 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; + +import java.awt.*; + +public class MSpacer extends MPanel { + + int width, height; + public MSpacer(int x, int y, int width, int height) { + setBounds(new Rectangle(x,y,width,height)); + this.width = width; this.height = height; + } + @Override + public Dimension getPreferredSize() { + return new Dimension(width, height); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MStringSelectionButton.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MStringSelectionButton.java new file mode 100755 index 00000000..407db0df --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MStringSelectionButton.java @@ -0,0 +1,94 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.Setter; + +import java.awt.*; +import java.util.List; + +@Getter +@Setter +public class MStringSelectionButton extends MPanel { + + private List<String> possible; + private int selectedIndex; + + private MButton dec; + private MButton inc; + private MLabel selected; + + @Getter + @Setter + private Runnable onUpdate; + + public MStringSelectionButton(final List<String> possible, String defaultValue) { + this.possible = possible; + selectedIndex = possible.indexOf(defaultValue); + if (selectedIndex == -1) selectedIndex = 0; + + dec = new MButton(); dec.setText("<"); add(dec); + inc = new MButton(); inc.setText(">"); add(inc); + selected = new MLabel(); updateSelected(); add(selected); + selected.setBackgroundColor(Color.black); + selected.setAlignment(MLabel.Alignment.CENTER); + + dec.setOnActionPerformed(new Runnable() { + @Override + public void run() { + selectedIndex --; + if (selectedIndex < 0) selectedIndex = possible.size() - 1; + updateSelected(); + onUpdate.run(); + } + }); + inc.setOnActionPerformed(new Runnable() { + @Override + public void run() { + selectedIndex++; + if (selectedIndex >= possible.size()) selectedIndex = 0; + updateSelected(); + onUpdate.run(); + } + }); + } + + public String selectionToDisplay(String selection) { + return selection; + } + + public String getSelected() { + if (possible.size() == 0) return null; + return possible.get(selectedIndex); + } + + private void updateSelected() { + if (possible.size() == 0) selected.setText("-Empty-"); + else selected.setText(selectionToDisplay(possible.get(selectedIndex))); + } + + @Override + public void onBoundsUpdate() { + dec.setBounds(new Rectangle(0,0,getBounds().height, getBounds().height)); + inc.setBounds(new Rectangle(getBounds().width - getBounds().height, 0, getBounds().height, getBounds().height)); + selected.setBounds(new Rectangle(getBounds().height, 0, getBounds().width - getBounds().height - getBounds().height, getBounds().height)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTabbedPane.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTabbedPane.java new file mode 100755 index 00000000..715b6720 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTabbedPane.java @@ -0,0 +1,160 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MTabbedPane extends MPanel { + + private final Map<String, MPanel> tabs = new HashMap<String, MPanel>(); + private final Map<String, MTabButton> buttons = new HashMap<String, MTabButton>(); + + @Getter + @Setter + private String selectedKey = ""; + + @Getter + private Color background2; + + public void setBackground2(Color background2) { + this.background2 = background2; + for (MPanel value : tabs.values()) { + value.setBackgroundColor(background2); + } + for (MTabButton value : buttons.values()) { + value.setBackgroundColor(background2.brighter()); + } + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + Gui.drawRect(0, 15, getBounds().width, getBounds().height, 0xFF444444); + } + + public void addTab(String tab, MPanel panel) { + MPanel panel2 = new MPanel() ; + panel2.add(panel); + panel2.setBackgroundColor(background2); + tabs.put(tab, panel2); + panel2.setParent(this); + panel2.setBounds(new Rectangle(1,16,getBounds().width-2, getBounds().height-17)); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + MTabButton button = new MTabButton(this, tab); + int totalX = 0; + for (MTabButton button1:buttons.values()) + totalX += button1.getBounds().width; + button.setBounds(new Rectangle(totalX, 0, Math.max(25, fr.getStringWidth(tab) + 6), 15)); + buttons.put(tab, button); + if (tabs.size() == 1) + selectedKey = tab; + } + + @Override + public List<MPanel> getChildComponents() { + ArrayList<MPanel> dynamic = new ArrayList<MPanel>(buttons.values()); + dynamic.add(tabs.get(selectedKey)); + return dynamic; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + for (MPanel ma:tabs.values()) + ma.setBounds(new Rectangle(1,16,getBounds().width-2, getBounds().height-17)); + } + + @Override + public void setBounds(Rectangle bounds) { + if (bounds == null) return; + this.bounds.x = bounds.x; + this.bounds.y = bounds.y; + this.bounds.width = bounds.width; + this.bounds.height = bounds.height; + } + + @Getter + @Setter + public static class MTabButton extends MPanel { + private String text; + + private Color foreground = Color.white; + private Color hover = new Color(154, 154, 154, 255); + private Color clicked = new Color(88, 88, 88,255); + private Color selected = new Color(111, 111, 111,255); + private Color disabled = new Color(0,0,0); + + private boolean enabled = true; + + private MTabbedPane tabbedPane; + + public MTabButton(MTabbedPane tabbedPane, String key) { + this.tabbedPane = tabbedPane; + this.text = key; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + Dimension bounds = getSize(); + + Color bg = null; + if (!enabled) { + bg = disabled; + } else if (tabbedPane.getSelectedKey().equals(text)) { + bg = selected; + } else if (new Rectangle(new Point(0,0),bounds).contains(relMousex0, relMousey0)) { + bg = hover; + } + Gui.drawRect(0, tabbedPane.getSelectedKey().equals(text) ? 0 : 2, getBounds().width, getBounds().height, 0xFF444444); + if (bg != null) + Gui.drawRect(1,tabbedPane.getSelectedKey().equals(text) ? 1 : 3,getBounds().width - 1, getBounds().height, bg.getRGB()); + + FontRenderer renderer = Minecraft.getMinecraft().fontRendererObj; + int width = renderer.getStringWidth(text); + int x = (getBounds().width - width) / 2; + int y = (getBounds().height - 3 - renderer.FONT_HEIGHT) / 2 + 3; + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + renderer.drawString(text, x,y, foreground.getRGB()); + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (lastAbsClip.contains(absMouseX, absMouseY)) { + tabbedPane.setSelectedKey(text); + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTextField.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTextField.java new file mode 100755 index 00000000..3238191f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTextField.java @@ -0,0 +1,418 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.MathHelper; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.awt.datatransfer.*; +import java.awt.event.KeyEvent; +import java.io.IOException; + +@Getter +public class MTextField extends MPanel { + private final Color foreground = Color.white; + private final Color placeHolderColor = Color.lightGray; + + private String text = ""; + @Setter + private String placeHolder = ""; + private int cursorBlickTicker = 0; + + private int selectionStart = 0; + private int selectionEnd = 0; + + private int cursor = 0; + + private int xOffset = 0; + + public void edit(String str) { + + } + + + @Override + public Dimension getPreferredSize() { + return new Dimension(-1,15); + } + + public void setText(String text) { + this.text = text; + } + private void setText0(String text) { + this.text = text; + edit(text); + } + + private void setCursor0(int cursor) { + if (cursor > text.length()) cursor = text.length(); + if (cursor < 0) cursor = 0; + this.cursor = cursor; + + + int width = Minecraft.getMinecraft().fontRendererObj.getStringWidth(text.substring(0, cursor)); + int cursorX = width + 3- xOffset; + cursorX = MathHelper.clamp_int(cursorX,10, getBounds().width - 10); + xOffset = width+ 3 - cursorX; + xOffset = MathHelper.clamp_int(xOffset, 0,Math.max(0, Minecraft.getMinecraft().fontRendererObj.getStringWidth(text) - getBounds().width+10)); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + clip(clip.x - 1, clip.y - 1, clip.width +2, clip.height + 2); + Gui.drawRect(0,0,getBounds().width, getBounds().height, isFocused ? Color.white.getRGB() : Color.gray.getRGB()); + Gui.drawRect(1,1,getBounds().width - 1, getBounds().height - 1, Color.black.getRGB()); + + Minecraft mc = Minecraft.getMinecraft(); + clip(clip.x + 1, clip.y + 1, clip.width - 2, clip.height - 2); + FontRenderer fr = mc.fontRendererObj; + int y = (getBounds().height - fr.FONT_HEIGHT) / 2; + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(text, 3 - xOffset, y, foreground.getRGB()); + if (text.isEmpty()) + fr.drawString(placeHolder, 3, y, placeHolderColor.getRGB()); + // draw selection + if (isFocused) { + if (selectionStart != -1) { + int startX = fr.getStringWidth(text.substring(0, selectionStart)) - xOffset; + int endX = fr.getStringWidth(text.substring(0, selectionEnd)) - xOffset; + Gui.drawRect(3 + startX, y, 3 + endX, y + fr.FONT_HEIGHT, 0xFF00FF00); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(text.substring(selectionStart, selectionEnd), 3 + startX, y, foreground.getRGB()); + } + + // draw cursor + if (cursor != -1) { + if (cursor > text.length()) setCursor0(text.length()); + int x = fr.getStringWidth(text.substring(0, cursor)) - xOffset; + cursorBlickTicker++; + if (cursorBlickTicker < 10) + Gui.drawRect(3 + x, y, 4 + x, y + fr.FONT_HEIGHT, 0xFFFFFFFF); + if (cursorBlickTicker == 20) cursorBlickTicker = 0; + } + } + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + Rectangle actualField = new Rectangle(1, 3,getBounds().width - 2, getBounds().height - 6); + if (!actualField.contains(relMouseX, relMouseY)) return; + if (!lastAbsClip.contains(absMouseX, absMouseY)) return; + if (getTooltipsOpen() > 0) return; + + + + int relStartT = relMouseX-3; + int offseted = relStartT + xOffset; + + selectionStart = -1; + + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + for (int i = 0; i < text.length(); i++) { + int totalWidth = fr.getStringWidth(text.substring(0, i)); + if (offseted < totalWidth) { + setCursor0(i); + return; + } + } + setCursor0(text.length()); + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + if (!isFocused) return; + selectionStart = cursor; + selectionEnd = cursor; + + int relStartT = relMouseX-3; + int offseted = relStartT + xOffset; + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + for (int i = 0; i < text.length(); i++) { + int totalWidth = fr.getStringWidth(text.substring(0, i)); + if (offseted < totalWidth) { + if (i < cursor) { + selectionStart = i; + selectionEnd = cursor; + } else { + selectionStart = cursor; + selectionEnd = i; + } + return; + } + } + selectionEnd = text.length(); + if (selectionStart == selectionEnd) { + selectionStart = -1; + } + } + + @Override + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (!isFocused) return; + if (scrollAmount > 0) { + xOffset += 5; + } else if (scrollAmount < 0){ + xOffset -= 5; + } + if (xOffset < 0) { + xOffset = 0; + } + int width = Minecraft.getMinecraft().fontRendererObj.getStringWidth(text); + int overflow = getBounds().width - 3 - width; + if (overflow >= 0) { + xOffset = 0; + } else if (width - xOffset + 10 < getBounds().width) { + xOffset = width - getBounds().width+10; + } + } + + @Override + public void keyHeld(char typedChar, int keyCode) { + if (!isFocused) return; + this.keyPressed(typedChar, keyCode); + } + + @Override + public void keyPressed(char typedChar, int keycode) { + if (!isFocused) return; + + if (selectionStart == -1) { + if (keycode == 199) { // home + setCursor0(0); + xOffset = 0; + return; + } + + if (keycode == 207) { // end + setCursor0(text.length()); + + int width = Minecraft.getMinecraft().fontRendererObj.getStringWidth(text); + xOffset = Integer.max(0, width - getBounds().width+10); + return; + } + + if (keycode == 203) { // left + setCursor0(this.cursor-1);; + if (cursor < 0) setCursor0(0); + return; + } + + if (keycode == 205) { // right + setCursor0(this.cursor+1); + if (cursor > text.length()) setCursor0(text.length()); + return; + } + + // backspace + if (keycode == 14 && cursor > 0) { + setText0(this.text.substring(0, cursor-1) + this.text.substring(cursor)); + setCursor0(this.cursor-1); + return; + } + + //del + if (keycode == 211 && cursor < text.length()) { + setText0(this.text.substring(0, cursor) + this.text.substring(cursor+1)); + return; + } + + // paste + boolean shouldPaste = false; + if (keycode == 47) { + if (Minecraft.isRunningOnMac) { // mac + if (Keyboard.isKeyDown(219) || Keyboard.isKeyDown(220)) { + shouldPaste = true; + } + } else { // literally everything else + if (Keyboard.isKeyDown(29) || Keyboard.isKeyDown(157)) { + shouldPaste = true; + } + } + } + if (shouldPaste) { + Transferable transferable = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null); + if (transferable != null && transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) { + try { + Object theText = transferable.getTransferData(DataFlavor.stringFlavor); + setText0( + this.text.substring(0, this.cursor) + + theText + + this.text.substring(this.cursor)); + + cursor += theText.toString().length(); + } catch (UnsupportedFlavorException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return; + } + + // text + if (isPrintableChar(typedChar)) { + setText0( + this.text.substring(0, this.cursor) + + typedChar + + this.text.substring(this.cursor)); + this.setCursor0(this.cursor+1);; + return; + } + } else { + if (keycode == 199) { // home + setCursor0(0); + selectionStart = -1; + xOffset =0; + return; + } + + if (keycode == 207) { // end + selectionStart = -1; + setCursor0(text.length()); + int width = Minecraft.getMinecraft().fontRendererObj.getStringWidth(text); + xOffset = Integer.max(0, width - getBounds().width+10); + return; + } + + if (keycode == 203) { // left + setCursor0(selectionStart); + selectionStart = -1; + return; + } + + if (keycode == 205) { // right + setCursor0(selectionEnd); + selectionStart = -1; + return; + } + + // backspace + if (keycode == 14 && cursor > 0) { + setText0(this.text.substring(0, selectionStart) + this.text.substring(selectionEnd)); + setCursor0(selectionStart); + selectionStart = -1; + return; + } + + //del + if (keycode == 211 && cursor < text.length()) { + setText0(this.text.substring(0, selectionStart) + this.text.substring(selectionEnd)); + setCursor0(selectionStart); + selectionStart = -1; + return; + } + + // paste + boolean shouldPaste = false; + if (keycode == 47) { + if (Minecraft.isRunningOnMac) { // mac + if (Keyboard.isKeyDown(219) || Keyboard.isKeyDown(220)) { + shouldPaste = true; + } + } else { // literally everything else + if (Keyboard.isKeyDown(29) || Keyboard.isKeyDown(157)) { + shouldPaste = true; + } + } + } + if (shouldPaste) { + Transferable transferable = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null); + if (transferable != null && transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) { + try { + Object theText = transferable.getTransferData(DataFlavor.stringFlavor); + setText0( + this.text.substring(0, this.selectionStart) + + theText + + this.text.substring(this.selectionEnd)); + setCursor0(this.selectionStart + theText.toString().length()); + } catch (UnsupportedFlavorException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + selectionStart = -1; + } + return; + } + boolean shouldCopy = false; + if (keycode == 46) { + if (Minecraft.isRunningOnMac) { // mac + if (Keyboard.isKeyDown(219) || Keyboard.isKeyDown(220)) { + shouldCopy = true; + } + } else { // literally everything else + if (Keyboard.isKeyDown(29) || Keyboard.isKeyDown(157)) { + shouldCopy = true; + } + } + } + if (shouldCopy) { + StringSelection selection = new StringSelection(text.substring(selectionStart, selectionEnd)); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(selection, selection); + return; + } + + // text + if (isPrintableChar(typedChar)) { + setText0( + this.text.substring(0, this.selectionStart) + + typedChar + + this.text.substring(this.selectionEnd)); + this.setCursor0(this.selectionStart + 1); + selectionStart = -1; + return; + } + } + } + public boolean isPrintableChar( char c ) { + Character.UnicodeBlock block = Character.UnicodeBlock.of( c ); + return (!Character.isISOControl(c)) && + c != KeyEvent.CHAR_UNDEFINED && + block != null && + block != Character.UnicodeBlock.SPECIALS; + } + + + @Override + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + if (lastAbsClip.contains(absMouseX, absMouseY)) + setCursor(EnumCursor.BEAM_CURSOR); + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MToggleButton.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MToggleButton.java new file mode 100755 index 00000000..efd473c1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MToggleButton.java @@ -0,0 +1,96 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.utils.cursor.EnumCursor; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; + +@Getter +@Setter +public class MToggleButton extends MPanel { + private boolean enabled = true; + private Runnable onToggle; + + private int border = 0xFF333333, background = 0xFF171717; + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + Dimension bounds = getSize(); + + int gap = 1; + + Gui.drawRect(0, 0, bounds.width, bounds.height, border); + Gui.drawRect(gap, gap, bounds.width-gap, bounds.height-gap, background); + + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + double scale = 1; + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + if (enabled) { + int x = (int) ((scale * bounds.height - fr.FONT_HEIGHT)/2 + gap); + GlStateManager.pushMatrix(); + GlStateManager.scale(1.0/scale,1.0/scale,0); + fr.drawString("ON", x, x, 0xFF9B9B9B); + GlStateManager.popMatrix(); + Gui.drawRect(bounds.width - bounds.height+gap,gap, bounds.width - gap, bounds.height - gap, 0xFF00B200); + } else { + GlStateManager.pushMatrix(); + GlStateManager.scale(1.0/scale,1.0/scale,0); + int x = (int) ((scale * bounds.height - fr.FONT_HEIGHT)/2 + gap); + fr.drawString("OFF", (int) (scale * bounds.width - x - fr.getStringWidth("OFF")), x, 0xFF9B9B9B); + GlStateManager.popMatrix(); + Gui.drawRect(gap,gap, bounds.height - gap, bounds.height - gap, 0xFFCD4000); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(40,15); + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (onToggle != null && lastAbsClip.contains(absMouseX, absMouseY) && getTooltipsOpen() == 0) { + enabled = !enabled; + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + onToggle.run(); + } + } + + + @Override + public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) { + if (lastAbsClip.contains(absMouseX, absMouseY)) + setCursor(EnumCursor.POINTING_HAND); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTooltip.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTooltip.java new file mode 100644 index 00000000..8e1a9022 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTooltip.java @@ -0,0 +1,107 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + +public class MTooltip extends MPanelScaledGUI { + @Getter @Setter + private MRootPanel root; + + public void open(MPanel component) { + if (root == null) + component.openTooltip(this); + } + public void close() { + if (root != null) + root.removeTooltip(this); + } + + + public boolean isOpen() { + return root != null; + } + + @Override + public int getTooltipsOpen() { + return super.getTooltipsOpen() - 1; + } + + @Override + public void render0(double parentScale, Point parentPoint, Rectangle parentClip, int absMousex0, int absMousey0, int relMousex0, int relMousey0, float partialTicks) { + lastParentPoint = parentPoint; + + GlStateManager.translate(getBounds().x, getBounds().y, 300); + GlStateManager.color(1,1,1,1); + + Rectangle absBound = getBounds().getBounds(); + absBound.setLocation(absBound.x + parentPoint.x, absBound.y + parentPoint.y); + + Rectangle clip = absBound; + lastAbsClip = clip; + + if (clip.getSize().height * clip.getSize().width == 0) return; + + int absMousex = (int) (absMousex0 / scale), absMousey = (int) (absMousey0 / scale); + int relMousex = (int) ((relMousex0 - getBounds().x) / scale); + int relMousey = (int) ((relMousey0 - getBounds().y) /scale); + + // FROM HERE, IT IS SCALED + + GlStateManager.scale(this.scale, this.scale, 1); + clip = new Rectangle((int) (clip.x / scale), (int) (clip.y / scale), (int) (clip.width / scale), (int) (clip.height / scale)); + lastAbsClip = clip; + + GL11.glEnable(GL11.GL_SCISSOR_TEST); + this.relativeScale = parentScale * this.scale; + clip(clip.x, clip.y, clip.width, clip.height); + + + GuiScreen.drawRect(0,0, (int) (getBounds().width / scale), (int) (getBounds().height / scale), backgroundColor.getRGB()); + GlStateManager.enableBlend(); + + + GlStateManager.pushMatrix(); + + render(absMousex, absMousey, relMousex, relMousey, partialTicks, clip); + + GlStateManager.popMatrix(); + + GL11.glDisable(GL11.GL_SCISSOR_TEST); + + + + Point newPt = new Point((int) ((parentPoint.x + getBounds().x) / scale), (int) ((parentPoint.y + getBounds().y) / scale)); + + for (MPanel mPanel : getChildComponents()){ + GlStateManager.pushMatrix(); + + mPanel.render0(relativeScale, newPt,clip,absMousex, absMousey, relMousex, relMousey, partialTicks); + + GlStateManager.popMatrix(); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTooltipText.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTooltipText.java new file mode 100644 index 00000000..8280546a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MTooltipText.java @@ -0,0 +1,44 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.client.config.GuiUtils; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +@AllArgsConstructor +public class MTooltipText extends MTooltip { + @Getter @Setter + private List<String> tooltipText = new ArrayList<>(); + @Override + public Rectangle getBounds() { + return new Rectangle(0,0, Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight); + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + GuiUtils.drawHoveringText(tooltipText, relMousex0, relMousey0, (int) (Minecraft.getMinecraft().displayWidth/getRelativeScale()), (int) (Minecraft.getMinecraft().displayHeight/getRelativeScale()), -1, Minecraft.getMinecraft().fontRendererObj); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MValue.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MValue.java new file mode 100755 index 00000000..82e60109 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/gui/elements/MValue.java @@ -0,0 +1,79 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.gui.elements; + +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditOffsetPointSet; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.gui.Gui; + +import java.awt.*; +import java.util.List; +public class MValue<T> extends MPanel { + @Getter + private final T data; + private ValueEditOffsetPointSet valueEditOffsetPointSet; + private final MLabel dataLab; + + @Getter @Setter + private Color hover = Color.gray; + + private final List<MPanel> addons; + + public MValue(final T parameter, List<MPanel> addons) { + this.addons = addons; + this.add(this.dataLab = new MLabel() { + @Override + public String getText() { + return data != null ?data.toString() :"-empty-"; + } + }); + this.dataLab.setAlignment(MLabel.Alignment.RIGHT); + + this.data = parameter; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + if (hover != null && new Rectangle(new Point(0,0),getBounds().getSize()).contains(relMousex0, relMousey0)) { + Gui.drawRect(0,0,getBounds().width, getBounds().height, hover.getRGB()); + } + } + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + if (this.getBounds().x > -20 && lastAbsClip.contains(absMouseX, absMouseY)) { + EditingContext.getEditingContext().openGui(new GuiDungeonValueEdit(data, addons)); + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setSize(new Dimension(parentWidth, getBounds().height)); + dataLab.setBounds(new Rectangle(0,0,parentWidth, getBounds().height)); + } + + @Override + public void onBoundsUpdate() { + dataLab.setBounds(new Rectangle(0,0,getBounds().width, getBounds().height)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/AStarCornerCut.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/AStarCornerCut.java new file mode 100644 index 00000000..ee71f90b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/AStarCornerCut.java @@ -0,0 +1,189 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.pathfinding; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraft.util.*; +import net.minecraft.world.World; + +import java.util.*; + +public class AStarCornerCut { + private final BlockPos min, max; + private final World world; + + int lastSx, lastSy, lastSz; + final int dx, dy, dz; + private DungeonRoom dungeonRoom; + + @Getter + private AxisAlignedBB destinationBB; + + public AStarCornerCut(DungeonRoom dungeonRoom, Vec3 destination) { + this.min = new BlockPos(dungeonRoom.getMinx(), 0, dungeonRoom.getMinz()); + this.max = new BlockPos(dungeonRoom.getMaxx(), 255, dungeonRoom.getMaxz()); + + this.world = dungeonRoom.getCachedWorld(); + this.dungeonRoom = dungeonRoom; + + this.dx = (int) (destination.xCoord * 2); + this.dy = (int) (destination.yCoord * 2); + this.dz = (int) (destination.zCoord * 2); + destinationBB = AxisAlignedBB.fromBounds(dx-2, dy-2, dz-2, dx+2, dy+2, dz+2); + } + + private Map<Node.Coordinate, Node> nodeMap = new HashMap<>(); + + private Node openNode(int x, int y, int z) + { + Node.Coordinate coordinate = new Node.Coordinate(x,y,z); + Node node = this.nodeMap.get(coordinate); + + if (node == null) + { + node = new Node(coordinate); + this.nodeMap.put(coordinate, node); + } + + return node; + } + + @Getter + private LinkedList<Vec3> route = new LinkedList<>(); + + @Getter + private PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparing((Node a) -> a == null ? Float.MAX_VALUE : a.f).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.x).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.y).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.z)); + + private int pfindIdx = 0; + + public boolean pathfind(Vec3 from, long timeout) { + pfindIdx ++; + if (lastSx != (int)Math.round(from.xCoord * 2) || lastSy != (int)Math.round(from.yCoord*2) || lastSz != (int)Math.round(from.zCoord * 2)) + open.clear(); + + this.lastSx = (int) Math.round(from.xCoord * 2); + this.lastSy = (int) Math.round(from.yCoord * 2); + this.lastSz = (int) Math.round(from.zCoord * 2); + + Node startNode = openNode(dx, dy, dz); + Node goalNode = openNode(lastSx, lastSy, lastSz); + + if (goalNode.parent != null) { + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + + startNode.g = 0; + startNode.f = 0; + goalNode.g = Integer.MAX_VALUE; goalNode.f = Integer.MAX_VALUE; + + + open.add(startNode); + + long end = System.currentTimeMillis() + timeout; + + while (!open.isEmpty()) { + if (System.currentTimeMillis() > end) { + return false; + } + + Node n = open.poll(); + if (n.lastVisited == pfindIdx) continue; + n.lastVisited = pfindIdx; + + if (n == goalNode) { + // route = reconstructPath(startNode) + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + + for (int z = -1; z <= 1; z++) {for (int y = -1; y <= 1; y ++) { for(int x = -1; x <= 1; x++) { + if (x == 0 && y == 0 && z == 0) continue; + Node neighbor = openNode(n.coordinate.x +x, n.coordinate.y +y, n.coordinate.z + z); + + // check blocked. + if (!((destinationBB.minX <= neighbor.coordinate.x && neighbor.coordinate.x <= destinationBB.maxX && + destinationBB.minY <= neighbor.coordinate.y && neighbor.coordinate.y <= destinationBB.maxY && + destinationBB.minZ <= neighbor.coordinate.z && neighbor.coordinate.z <= destinationBB.maxZ) // near destination + || !dungeonRoom.isBlocked(neighbor.coordinate.x, neighbor.coordinate.y, neighbor.coordinate.z))) { // not blocked + continue; + } + if (neighbor.lastVisited == pfindIdx) continue; + + + float gScore = n.g + MathHelper.sqrt_float(x*x + y*y + z*z); // altho it's sq, it should be fine + if (gScore < neighbor.g ) { + neighbor.parent = n; + neighbor.g = gScore; + neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } else if (neighbor.lastVisited != pfindIdx) { + neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } + }}} + } + return true; + } + + private int manhatten(int x, int y, int z) {return Math.abs(x)+ Math.abs(y)+ Math.abs(z);} + private float distSq(float x, float y, float z) { + return MathHelper.sqrt_float(x * x + y * y + z * z); + } + + @RequiredArgsConstructor + @Data + public static final class Node { + @Data + @RequiredArgsConstructor + public static final class Coordinate { + private final int x, y, z; + } + private final Coordinate coordinate; + + private float f = Float.MAX_VALUE, g = Float.MAX_VALUE; + private int lastVisited; + + @EqualsAndHashCode.Exclude + private Node parent; + + public static long makeHash(int x, int y, int z) + { + return y & 32767L | ((short)x & 32767L) << 16 | ((short)z & 32767L) << 32; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/AStarFineGrid.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/AStarFineGrid.java new file mode 100644 index 00000000..94fa8a87 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/AStarFineGrid.java @@ -0,0 +1,182 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.pathfinding; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraft.util.*; +import net.minecraft.world.World; + +import java.util.*; + +public class AStarFineGrid { + private final BlockPos min, max; + private final World world; + + int lastSx, lastSy, lastSz; + final int dx, dy, dz; + private DungeonRoom dungeonRoom; + + @Getter + private AxisAlignedBB destinationBB; + + public AStarFineGrid(DungeonRoom dungeonRoom, Vec3 destination) { + this.min = new BlockPos(dungeonRoom.getMinx(), 0, dungeonRoom.getMinz()); + this.max = new BlockPos(dungeonRoom.getMaxx(), 255, dungeonRoom.getMaxz()); + + this.world = dungeonRoom.getCachedWorld(); + this.dungeonRoom = dungeonRoom; + + this.dx = (int) (destination.xCoord * 2); + this.dy = (int) (destination.yCoord * 2); + this.dz = (int) (destination.zCoord * 2); + destinationBB = AxisAlignedBB.fromBounds(dx-2, dy-2, dz-2, dx+2, dy+2, dz+2); + } + + private Map<Node.Coordinate, Node> nodeMap = new HashMap<>(); + + private Node openNode(int x, int y, int z) + { + Node.Coordinate coordinate = new Node.Coordinate(x,y,z); + Node node = this.nodeMap.get(coordinate); + + if (node == null) + { + node = new Node(coordinate); + this.nodeMap.put(coordinate, node); + } + + return node; + } + + @Getter + private LinkedList<Vec3> route = new LinkedList<>(); + + @Getter + private PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparing((Node a) -> a == null ? Float.MAX_VALUE : a.f).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.x).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.y).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.z)); + + private int pfindIdx = 0; + + public boolean pathfind(Vec3 from, long timeout) { + pfindIdx ++; + if (lastSx != (int)Math.round(from.xCoord * 2) || lastSy != (int)Math.round(from.yCoord*2) || lastSz != (int)Math.round(from.zCoord * 2)) + open.clear(); + + this.lastSx = (int) Math.round(from.xCoord * 2); + this.lastSy = (int) Math.round(from.yCoord * 2); + this.lastSz = (int) Math.round(from.zCoord * 2); + + Node startNode = openNode(dx, dy, dz); + Node goalNode = openNode(lastSx, lastSy, lastSz); + startNode.g = 0; + startNode.f = 0; + goalNode.g = Integer.MAX_VALUE; goalNode.f = Integer.MAX_VALUE; + if (goalNode.parent != null) { + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + open.add(startNode); + + long end = System.currentTimeMillis() + timeout; + + while (!open.isEmpty()) { + if (System.currentTimeMillis() > end) { + return false; + } + + Node n = open.poll(); + if (n.lastVisited == pfindIdx) continue; + n.lastVisited = pfindIdx; + + if (n == goalNode) { + // route = reconstructPath(startNode) + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + + for (EnumFacing value : EnumFacing.VALUES) { + Node neighbor = openNode(n.coordinate.x + value.getFrontOffsetX(), n.coordinate.y + value.getFrontOffsetY(), n.coordinate.z + value.getFrontOffsetZ()); + + // check blocked. + if (!((destinationBB.minX <= neighbor.coordinate.x && neighbor.coordinate.x <= destinationBB.maxX && + destinationBB.minY <= neighbor.coordinate.y && neighbor.coordinate.y <= destinationBB.maxY && + destinationBB.minZ <= neighbor.coordinate.z && neighbor.coordinate.z <= destinationBB.maxZ) // near destination + || !dungeonRoom.isBlocked(neighbor.coordinate.x, neighbor.coordinate.y, neighbor.coordinate.z))) { // not blocked + continue; + } + + float gScore = n.g + 1; // altho it's sq, it should be fine + if (gScore < neighbor.g) { + neighbor.parent = n; + neighbor.g = gScore; + neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } else if (neighbor.lastVisited != pfindIdx) { + neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } + } + } + return true; + } + + private int manhatten(int x, int y, int z) {return Math.abs(x)+ Math.abs(y)+ Math.abs(z);} + private float distSq(float x, float y, float z) { + return MathHelper.sqrt_float(x * x + y * y + z * z); + } + + @RequiredArgsConstructor + @Data + public static final class Node { + @Data + @RequiredArgsConstructor + public static final class Coordinate { + private final int x, y, z; + } + private final Coordinate coordinate; + + private float f = Float.MAX_VALUE, g = Float.MAX_VALUE; + private int lastVisited; + + @EqualsAndHashCode.Exclude + private Node parent; + + public static long makeHash(int x, int y, int z) + { + return y & 32767L | ((short)x & 32767L) << 16 | ((short)z & 32767L) << 32; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/CachedWorld.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/CachedWorld.java new file mode 100644 index 00000000..1291f794 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/CachedWorld.java @@ -0,0 +1,85 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.pathfinding; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.*; +import net.minecraft.world.chunk.IChunkProvider; + +public class CachedWorld extends World { + private ChunkCache chunkCache; + + public CachedWorld(ChunkCache chunkCache) { + super(null, null, new WorldProviderSurface(), null, true); + this.chunkCache = chunkCache; + } + + @Override + protected IChunkProvider createChunkProvider() { + return null; + } + + @Override + protected int getRenderDistanceChunks() { + return 999; + } + + @Override + public boolean extendedLevelsInChunkCache() { + return chunkCache.extendedLevelsInChunkCache(); + } + + @Override + public TileEntity getTileEntity(BlockPos pos) { + return chunkCache.getTileEntity(pos); + } + + @Override + public int getCombinedLight(BlockPos pos, int lightValue) { + return chunkCache.getCombinedLight(pos, lightValue); + } + + @Override + public IBlockState getBlockState(BlockPos pos) { + return chunkCache.getBlockState(pos); + } + + @Override + public int getLightFor(EnumSkyBlock type, BlockPos pos) { + return chunkCache.getLightFor(type, pos); + } + + @Override + public boolean isAirBlock(BlockPos pos) { + return chunkCache.isAirBlock(pos); + } + + @Override + public int getStrongPower(BlockPos pos, EnumFacing direction) { + return chunkCache.getStrongPower(pos, direction); + } + + @Override + public boolean isSideSolid(BlockPos pos, EnumFacing side, boolean _default) { + return chunkCache.isSideSolid(pos, side, _default); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/JPSPathfinder.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/JPSPathfinder.java new file mode 100644 index 00000000..12aa1828 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/JPSPathfinder.java @@ -0,0 +1,306 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.pathfinding; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraft.util.*; +import net.minecraft.world.World; + +import java.util.*; + +public class JPSPathfinder { + private final BlockPos min, max; + private final World world; + + private Vec3 start; + private Vec3 destination; + private DungeonRoom dungeonRoom; + + @Getter + private AxisAlignedBB destinationBB; + + public JPSPathfinder(DungeonRoom dungeonRoom){ + this.min = new BlockPos(dungeonRoom.getMinx(), 0, dungeonRoom.getMinz()); + this.max = new BlockPos(dungeonRoom.getMaxx(), 255, dungeonRoom.getMaxz()); + + this.world = dungeonRoom.getCachedWorld(); + this.dungeonRoom = dungeonRoom; + } + + private IntHashMap<Node> nodeMap = new IntHashMap(); + + private Node openNode(int x, int y, int z) + { + int i = Node.makeHash(x, y, z); + Node node = this.nodeMap.lookup(i); + + if (node == null) + { + node = new Node(x, y, z); + this.nodeMap.addKey(i, node); + } + + return node; + } + + @Getter + private LinkedList<Vec3> route = new LinkedList<>(); + + @Getter + private PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparing((Node a) -> a == null ? Float.MAX_VALUE : a.f).thenComparing(a -> a == null ? Float.MAX_VALUE : a.x).thenComparing(a -> a == null ? Float.MAX_VALUE : a.y).thenComparing(a -> a == null ? Float.MAX_VALUE : a.z)); + + private int tx, ty, tz; + + private Node addNode(Node parent, Node jumpPt, boolean addToOpen) { + float ng = parent.g + distSq(jumpPt.x - parent.x, jumpPt.y - parent.y, jumpPt.z - parent.z); + + if (ng < jumpPt.g) { + if (addToOpen) + open.remove(jumpPt); + jumpPt.g = ng; + jumpPt.h = jumpPt.h == -1 ? distSq(tx - jumpPt.x, ty - jumpPt.y, tz - jumpPt.z) : jumpPt.h; + jumpPt.f = jumpPt.h + jumpPt.g; + jumpPt.parent = parent; + if (addToOpen) + open.add(jumpPt); + } + return jumpPt; + } + + + long arr[]; + + public boolean pathfind(Vec3 from, Vec3 to, float within, long timeout) { + route.clear(); nodeMap.clearMap(); + + { + from = new Vec3(((int)(from.xCoord * 2)) / 2.0, ((int)(from.yCoord * 2)) / 2.0, ((int)(from.zCoord* 2)) / 2.0); + to = new Vec3(((int)(to.xCoord * 2)) / 2.0, ((int)(to.yCoord * 2)) / 2.0, ((int)(to.zCoord* 2)) / 2.0); + } + + this.start = from; this.destination = to; + tx = (int)(to.xCoord * 2); + ty = (int)(to.yCoord * 2); + tz = (int)(to.zCoord * 2); + + destinationBB = AxisAlignedBB.fromBounds((to.xCoord - within)* 2, (to.yCoord - within) * 2, (to.zCoord - within) * 2, (to.xCoord + within) * 2, (to.yCoord + within)* 2, (to.zCoord + within) *2); + open.clear(); + Node start; + open.add(start = openNode((int)from.xCoord * 2 + 1, (int)from.yCoord * 2, (int)from.zCoord * 2+1)); + start.g = 0; start.f = 0; start.h = (float) from.squareDistanceTo(to); + + Node end = null; float minDist = Float.MAX_VALUE; + long forceEnd = System.currentTimeMillis() + timeout + 999999999L; + while(!open.isEmpty()) { + if (forceEnd < System.currentTimeMillis() && timeout != -1) break; + Node n = open.poll(); + n.closed= true; + if (minDist > n.h) { + minDist = n.h; + end = n; + } + if (n.x > destinationBB.minX && n.x < destinationBB.maxX && n.y > destinationBB.minY && n.y < destinationBB.maxY && n.z > destinationBB.minZ && n.z < destinationBB.maxZ) { + break; + } + + for (Node neighbor : getNeighbors(n.parent == null ? n : n.parent, n)) { + Node jumpPT = expand(n.x, n.y, n.z, neighbor.x - n.x, neighbor.y - n.y, neighbor.z - n.z); + if (jumpPT == null || jumpPT.closed) continue; + + addNode(n, jumpPT, true); + } + } + + if (end == null) return false; + Node p = end; + while (p != null) { + route.addLast(new Vec3(p.x / 2.0f, p.y / 2.0f + 0.1, p.z / 2.0f)); + p = p.parent; + } + + + return true; + } + + private float distSq(float x, float y, float z) { + return MathHelper.sqrt_float(x * x + y * y + z * z); + } + + public Set<Node> getNeighbors(Node prevN, Node n) { +// if (true) throw new RuntimeException("ah"); + int dx = MathHelper.clamp_int(n.x - prevN.x, -1, 1); + int dy = MathHelper.clamp_int(n.y - prevN.y, -1, 1); + int dz = MathHelper.clamp_int(n.z - prevN.z, -1, 1); + int x = n.x, y = n.y, z = n.z; + int nx = n.x + dx, ny = n.y + dy, nz = n.z + dz; + + Set<Node> nexts = new HashSet<>(); + int determinant = Math.abs(dx) + Math.abs(dy) + Math.abs(dz); + if (determinant == 0) { + for (int i = -1; i <= 1; i++) + for (int j = -1; j <= 1; j++) + for (int k = -1; k <= 1; k++) { + if (i == 0 && j == 0 && k == 0) continue; + nexts.add(openNode(x+i, y+j, z+k)); + } + } else if (determinant == 1) { + nexts.add(openNode(nx,ny,nz)); + for (int i = -1; i<=1; i++) { + for (int j = - 1; j<=1; j++) { + if (i == 0 && j == 0) continue; + if (dx != 0 && dungeonRoom.isBlocked(x, y + i, z + j)) nexts.add(openNode(nx,y+i,z+j)); + if (dy != 0 && dungeonRoom.isBlocked(x + i, y, z + j)) nexts.add(openNode(x+i,ny,z+j)); + if (dz != 0 && dungeonRoom.isBlocked(x + i, y + j, z)) nexts.add(openNode(x+i,y+j,nz)); + } + } + } else if (determinant == 2) { + if (dz != 0) nexts.add(openNode(x,y,nz)); + if (dy != 0) nexts.add(openNode(x,ny,z)); + if (dx != 0) nexts.add(openNode(nx,y,z)); + nexts.add(openNode(nx,ny,nz)); + if (dx == 0) { + if (dungeonRoom.isBlocked(x, y, z-dz)) { + nexts.add(openNode(x, ny, z-dz)); + if (dungeonRoom.isBlocked(x+1, y, z-dz)) nexts.add(openNode(x+1, ny, z-dz)); + if (dungeonRoom.isBlocked(x-1, y, z-dz)) nexts.add(openNode(x-1, ny, z-dz)); + } + if (dungeonRoom.isBlocked(x, y-dy, z)) { + nexts.add(openNode(x, y-dy, nz)); + if (dungeonRoom.isBlocked(x+1, y-dy, z)) nexts.add(openNode(x+1, y-dy, nz)); + if (dungeonRoom.isBlocked(x-1, y-dy, z)) nexts.add(openNode(x+1, y-dy, nz)); + } + } else if (dy == 0) { + if (dungeonRoom.isBlocked(x, y, z-dz)) { + nexts.add(openNode(nx, y, z-dz)); + if (dungeonRoom.isBlocked(x, y+1, z-dz)) nexts.add(openNode(nx, y+1, z-dz)); + if (dungeonRoom.isBlocked(x, y-1, z-dz)) nexts.add(openNode(nx, y-1, z-dz)); + } + if (dungeonRoom.isBlocked(x-dx, y, z)) { + nexts.add(openNode(x-dx, y, nz)); + if (dungeonRoom.isBlocked(x-dx, y+1, z)) nexts.add(openNode(x-dx, y+1, nz)); + if (dungeonRoom.isBlocked(x-dx, y-1, z)) nexts.add(openNode(x-dx, y-1, nz)); + } + } else if (dz == 0) { + if (dungeonRoom.isBlocked(x, y-dy, z)) { + nexts.add(openNode(nx, y-dy, z)); + if (dungeonRoom.isBlocked(x, y-dy, z+1)) nexts.add(openNode(nx, y-dy, z+1)); + if (dungeonRoom.isBlocked(x, y-dy, z-1)) nexts.add(openNode(nx, y-dy, z-1)); + } + if (dungeonRoom.isBlocked(x-dx, y, z)) { + nexts.add(openNode(x-dx, ny, z)); + if (dungeonRoom.isBlocked(x-dx, y, z+1)) nexts.add(openNode(x-dx, ny, z+1)); + if (dungeonRoom.isBlocked(x-dx, y, z-1)) nexts.add(openNode(x-dx, ny, z-1)); + } + } + } else if (determinant == 3) { + nexts.add(openNode(x,y,nz)); + nexts.add(openNode(x,ny,z)); + nexts.add(openNode(nx,y,z)); + nexts.add(openNode(nx,y,nz)); + nexts.add(openNode(x,ny,nz)); + nexts.add(openNode(nx,ny,z)); + nexts.add(openNode(nx,ny,nz)); + + if (dungeonRoom.isBlocked(x,y,z-dz)) { + nexts.add(openNode(x,ny,z-dz)); + nexts.add(openNode(nx,ny,z-dz)); + nexts.add(openNode(nx,y,z-dz)); + } + if (dungeonRoom.isBlocked(x-dx,y,z)) { + nexts.add(openNode(x-dx,ny,nz)); + nexts.add(openNode(x-dx,ny,z)); + nexts.add(openNode(x-dx,y,nz)); + } + if (dungeonRoom.isBlocked(x,y-dy,z)) { + nexts.add(openNode(x,y-dy,nz)); + nexts.add(openNode(nx,y-dy,z)); + nexts.add(openNode(nx,y-dy,nz)); + } + } + return nexts; + } + + public Node expand(int x, int y, int z, int dx, int dy, int dz) { + while(true) { + int nx = x + dx, ny = y + dy, nz = z + dz; + if (dungeonRoom.isBlocked(nx, ny, nz)) return null; + + if (nx > destinationBB.minX && nx < destinationBB.maxX && ny > destinationBB.minY && ny < destinationBB.maxY && nz > destinationBB.minZ && nz < destinationBB.maxZ) return openNode(nx,ny,nz); + + int determinant = Math.abs(dx) + Math.abs(dy) + Math.abs(dz); + if (determinant == 1) { + for (int i = -1; i<=1; i++) { + for (int j = - 1; j<=1; j++) { + if (i == 0 && j == 0) continue; + if (dx != 0 && dungeonRoom.isBlocked(nx, ny + i, nz + j) && !dungeonRoom.isBlocked(nx+dx, ny + i, nz + j)) return openNode(nx,ny,nz); + if (dy != 0 && dungeonRoom.isBlocked(nx + i, ny, nz + j) && !dungeonRoom.isBlocked(nx + i, ny+dy, nz + j)) return openNode(nx,ny,nz); + if (dz != 0 && dungeonRoom.isBlocked(nx + i, ny + j , nz) && !dungeonRoom.isBlocked(nx + i, ny + j , nz+dz)) return openNode(nx,ny,nz); + } + } + } else if (determinant == 2) { + for (EnumFacing value : EnumFacing.VALUES) { + if (value.getFrontOffsetX() == dx || value.getFrontOffsetY() == dy || value.getFrontOffsetZ() == dz) continue; + int tx = nx + value.getFrontOffsetX(); + int ty = ny + value.getFrontOffsetY(); + int tz = nz + value.getFrontOffsetZ(); + if (dungeonRoom.isBlocked(tx, ty, tz)) return openNode(nx, ny, nz); + } + if (dx != 0 && expand(nx, ny, nz, dx, 0,0) != null) return openNode(nx,ny,nz); + if (dy != 0 && expand(nx, ny, nz, 0, dy,0) != null) return openNode(nx,ny,nz); + if (dz != 0 && expand(nx, ny, nz, 0, 0,dz) != null) return openNode(nx,ny,nz); + } else if (determinant == 3) { + if (dungeonRoom.isBlocked(x, ny, nz ) || dungeonRoom.isBlocked(nx, y , nz) || dungeonRoom.isBlocked(nx, ny, z)) return openNode(nx,ny,nz); + if (expand(nx, ny, nz, dx, 0, 0) != null || + expand(nx, ny, nz, dx, dy, 0) != null || + expand(nx, ny, nz, dx, 0, dz) != null || + expand(nx, ny, nz, 0, dy, 0) != null || + expand(nx, ny, nz, 0, dy, dz) != null || + expand(nx, ny, nz, 0, 0, dz) != null) return openNode(nx,ny,nz); + } + x = nx; y = ny; z = nz; + } + } + + @RequiredArgsConstructor + @Data + public static final class Node { + private final int x, y, z; + + private float f, g = Float.MAX_VALUE, h = -1; + private boolean closed; + + @EqualsAndHashCode.Exclude + private Node parent; + + public static int makeHash(int x, int y, int z) + { + return y & 255 | (x & 32767) << 8 | (z & 32767) << 24 | (x < 0 ? Integer.MIN_VALUE : 0) | (z < 0 ? 32768 : 0); + } + + public Node close() { + this.closed = true; + return this; + } + + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/NodeProcessorDungeonRoom.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/NodeProcessorDungeonRoom.java new file mode 100644 index 00000000..d037c3a6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/NodeProcessorDungeonRoom.java @@ -0,0 +1,141 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.pathfinding; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Vec3i; +import net.minecraft.world.pathfinder.NodeProcessor; + +import java.util.Set; + +public class NodeProcessorDungeonRoom extends NodeProcessor { + private final DungeonRoom dungeonRoom; + private final BlockPos sub; + public NodeProcessorDungeonRoom(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + sub = dungeonRoom.getMax().subtract(dungeonRoom.getMin()); + } + + @Override + public PathPoint getPathPointTo(Entity entityIn) { + return openPoint((int)entityIn.posX - dungeonRoom.getMin().getX(), (int)entityIn.posY - dungeonRoom.getMin().getY(), + (int)entityIn.posZ - dungeonRoom.getMin().getZ()); + } + + @Override + public PathPoint getPathPointToCoords(Entity entityIn, double x, double y, double z) { + return openPoint((int)x- dungeonRoom.getMin().getX(), (int)y - dungeonRoom.getMin().getY(), + (int)z - dungeonRoom.getMin().getZ()); + } + + private static final EnumFacing[] values2 = new EnumFacing[6]; + static { + values2[0] = EnumFacing.DOWN; + values2[1] = EnumFacing.NORTH; + values2[2] = EnumFacing.SOUTH; + values2[3] = EnumFacing.EAST; + values2[4] = EnumFacing.WEST; + values2[5] = EnumFacing.UP; + } + + @Override + public int findPathOptions(PathPoint[] pathOptions, Entity entityIn, PathPoint currentPoint, PathPoint targetPoint, float maxDistance) { + + int i = 0; + for (EnumFacing ef:values2) { + Vec3i dir = ef.getDirectionVec(); + int newX = currentPoint.xCoord + dir.getX(); + int newY = currentPoint.yCoord + dir.getY(); + int newZ = currentPoint.zCoord + dir.getZ(); + if (newX < 0 || newZ < 0) continue; + if (newX > sub.getX()|| newZ > sub.getZ()) continue; + IBlockState curr = entityIn.getEntityWorld().getBlockState(dungeonRoom.getMin().add(newX, newY, newZ)); + IBlockState up = entityIn.getEntityWorld().getBlockState(dungeonRoom.getMin().add(newX, newY + 1, newZ)); + if (isValidBlock(curr) + && isValidBlock(up )) { + PathPoint pt = openPoint(newX, newY, newZ); + if (pt.visited) continue; + pathOptions[i++] = pt; + continue; + } + + if (curr.getBlock() == Blocks.air) { + if (up.getBlock() == Blocks.stone_slab + || up.getBlock() == Blocks.wooden_slab + || up.getBlock() == Blocks.stone_slab2) { + IBlockState up2 = entityIn.getEntityWorld().getBlockState(dungeonRoom.getMin().add(newX, newY -1, newZ)); + if (up2.getBlock() == Blocks.stone_slab + || up2.getBlock() == Blocks.wooden_slab + || up2.getBlock() == Blocks.stone_slab2) { + PathPoint pt = openPoint(newX, newY, newZ); + if (pt.visited) continue; + pathOptions[i++] = pt; + continue; + } + } + } + + if (dir.getY() == 0 && curr.getBlock() == Blocks.iron_bars && up.getBlock() == Blocks.air && + entityIn.getEntityWorld().getBlockState(new BlockPos(currentPoint.xCoord, currentPoint.yCoord, currentPoint.zCoord)).getBlock() != Blocks.iron_bars) { + boolean theFlag = false; + if (dir.getZ() == 0) { + if (entityIn.getEntityWorld().getBlockState(dungeonRoom.getMin().add(newX, newY, newZ) + .add(0,0,1)).getBlock() == Blocks.air) { + theFlag = true; + } else if (entityIn.getEntityWorld().getBlockState(dungeonRoom.getMin().add(newX, newY, newZ) + .add(0,0,-1)).getBlock() == Blocks.air) { + theFlag = true; + } + } else if (dir.getX() == 0) { + if (entityIn.getEntityWorld().getBlockState(dungeonRoom.getMin().add(newX, newY, newZ) + .add(-1,0,0)).getBlock() == Blocks.air) { + theFlag = true; + } else if (entityIn.getEntityWorld().getBlockState(dungeonRoom.getMin().add(newX, newY, newZ) + .add(1,0,0)).getBlock() == Blocks.air) { + theFlag = true; + } + } + if (theFlag) { + PathPoint pt = openPoint(newX, newY, newZ); + if (pt.visited) continue; + pathOptions[i++] = pt; + continue; + } + } + } + return i; + } + + public static final Set<Block> allowed = Sets.newHashSet(Blocks.air, Blocks.water, Blocks.lava, Blocks.flowing_water, Blocks.flowing_lava, Blocks.vine, Blocks.ladder + , Blocks.standing_sign, Blocks.wall_sign, Blocks.trapdoor, Blocks.iron_trapdoor, Blocks.wooden_button, Blocks.stone_button, Blocks.fire, + Blocks.torch, Blocks.rail, Blocks.golden_rail, Blocks.activator_rail, Blocks.detector_rail, Blocks.carpet, Blocks.redstone_torch); + public static final IBlockState preBuilt = Blocks.stone.getStateFromMeta(2); + public static boolean isValidBlock(IBlockState state) { + Block b = state.getBlock(); + return state.equals(preBuilt) || allowed.contains(b); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/ThetaStar.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/ThetaStar.java new file mode 100644 index 00000000..032223f0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/pathfinding/ThetaStar.java @@ -0,0 +1,211 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.pathfinding; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import lombok.*; +import net.minecraft.util.*; +import net.minecraft.world.World; + +import java.util.*; + +public class ThetaStar { + private final BlockPos min, max; + private final World world; + + int lastSx, lastSy, lastSz; + final int dx, dy, dz; + private DungeonRoom dungeonRoom; + + @Getter + private AxisAlignedBB destinationBB; + + public ThetaStar(DungeonRoom dungeonRoom, Vec3 destination) { + this.min = new BlockPos(dungeonRoom.getMinx(), 0, dungeonRoom.getMinz()); + this.max = new BlockPos(dungeonRoom.getMaxx(), 255, dungeonRoom.getMaxz()); + + this.world = dungeonRoom.getCachedWorld(); + this.dungeonRoom = dungeonRoom; + + this.dx = (int) (destination.xCoord * 2); + this.dy = (int) (destination.yCoord * 2); + this.dz = (int) (destination.zCoord * 2); + destinationBB = AxisAlignedBB.fromBounds(dx-2, dy-2, dz-2, dx+2, dy+2, dz+2); + } + + private Map<Node.Coordinate, Node> nodeMap = new HashMap<>(); + + private Node openNode(int x, int y, int z) + { + Node.Coordinate coordinate = new Node.Coordinate(x,y,z); + Node node = this.nodeMap.get(coordinate); + + if (node == null) + { + node = new Node(coordinate); + this.nodeMap.put(coordinate, node); + } + + return node; + } + + @Getter + private LinkedList<Vec3> route = new LinkedList<>(); + + @Getter + private PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparing((Node a) -> a == null ? Float.MAX_VALUE : a.f).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.x).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.y).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.z)); + + private int pfindIdx = 0; + + public boolean pathfind(Vec3 from, long timeout) { + + pfindIdx ++; + if (lastSx != (int)Math.round(from.xCoord * 2) || lastSy != (int)Math.round(from.yCoord*2) || lastSz != (int)Math.round(from.zCoord * 2)) + open.clear(); + + this.lastSx = (int) Math.round(from.xCoord * 2); + this.lastSy = (int) Math.round(from.yCoord * 2); + this.lastSz = (int) Math.round(from.zCoord * 2); + if (dungeonRoom.isBlocked(lastSx, lastSy, lastSz)) return false; + + Node startNode = openNode(dx, dy, dz); + Node goalNode = openNode(lastSx, lastSy, lastSz); + startNode.g = 0; + startNode.f = 0; + goalNode.g = Integer.MAX_VALUE; goalNode.f = Integer.MAX_VALUE; + if (goalNode.parent != null) { + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + open.add(startNode); + + long end = System.currentTimeMillis() + timeout; + + while (!open.isEmpty()) { + if (System.currentTimeMillis() > end) { + return false; + } + Node n = open.poll(); + if (n.lastVisited == pfindIdx) continue; + n.lastVisited = pfindIdx; + + if (n == goalNode) { + // route = reconstructPath(startNode) + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + + for (EnumFacing value : EnumFacing.VALUES) { + Node neighbor = openNode(n.coordinate.x + value.getFrontOffsetX(), n.coordinate.y + value.getFrontOffsetY(), n.coordinate.z + value.getFrontOffsetZ()); + + // check blocked. + if (!((destinationBB.minX <= neighbor.coordinate.x && neighbor.coordinate.x <= destinationBB.maxX && + destinationBB.minY <= neighbor.coordinate.y && neighbor.coordinate.y <= destinationBB.maxY && + destinationBB.minZ <= neighbor.coordinate.z && neighbor.coordinate.z <= destinationBB.maxZ) // near destination + || !dungeonRoom.isBlocked(neighbor.coordinate.x, neighbor.coordinate.y, neighbor.coordinate.z))) { // not blocked + continue; + } + if (neighbor.lastVisited == pfindIdx) continue; + + boolean flag = false; + if (n. parent != null) { + float tempGScore = n.parent.g + distSq(n.parent.coordinate.x - neighbor.coordinate.x, n.parent.coordinate.y - neighbor.coordinate.y, n.parent.coordinate.z - neighbor.coordinate.z); + if (tempGScore < neighbor.g && lineofsight(n.parent, neighbor)) { + neighbor.parent = n.parent; + neighbor.g = tempGScore; + neighbor.f = tempGScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + flag = true; + } + } + if (!flag) { + float gScore = n.g + 1; // altho it's sq, it should be fine + if (gScore < neighbor.g) { + neighbor.parent = n; + neighbor.g = gScore; + neighbor.f = gScore +distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } else if (neighbor.lastVisited != pfindIdx) { + neighbor.f = neighbor.g + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } + } + } + } + return true; + } + + private boolean lineofsight(Node a, Node b) { + if (a == null || b == null) return false; + float sx = a.coordinate.x, sy = a.coordinate.y, sz = a.coordinate.z; + int ex = b.coordinate.x, ey = b.coordinate.y, ez = b.coordinate.z; + + float dx = ex - sx, dy = ey - sy, dz = ez - sz; + float len = distSq(dx, dy, dz); + dx /= len; dy /= len; dz /= len; + + for (int d = 0; d <= len; d += 1) { + if (dungeonRoom.isBlocked(Math.round(sx), (int) Math.ceil(sy), Math.round(sz))) return false; + if (dungeonRoom.isBlocked(Math.round(sx)+1, (int) Math.ceil(sy), Math.round(sz)+1)) return false; + if (dungeonRoom.isBlocked(Math.round(sx)-1, (int) Math.ceil(sy), Math.round(sz)-1)) return false; + if (dungeonRoom.isBlocked(Math.round(sx)+1, (int) Math.ceil(sy), Math.round(sz)-1)) return false; + if (dungeonRoom.isBlocked(Math.round(sx)-1, (int) Math.ceil(sy), Math.round(sz)+1)) return false; + sx += dx; sy += dy; sz += dz; + } + return true; + } + + private int manhatten(int x, int y, int z) {return Math.abs(x)+ Math.abs(y)+ Math.abs(z);} + private float distSq(float x, float y, float z) { + return MathHelper.sqrt_float(x * x + y * y + z * z); + } + + @RequiredArgsConstructor + @Data + public static final class Node { + @Data + @RequiredArgsConstructor + public static final class Coordinate { + private final int x, y, z; + } + + private final Coordinate coordinate; + + private float f = Float.MAX_VALUE, g = Float.MAX_VALUE; + private int lastVisited; + + @EqualsAndHashCode.Exclude + @ToString.Exclude + private Node parent; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/resources/DGTexturePack.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/resources/DGTexturePack.java new file mode 100644 index 00000000..f8c15871 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/resources/DGTexturePack.java @@ -0,0 +1,72 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.resources; + +import kr.syeyoung.dungeonsguide.launcher.authentication.Authenticator; +import lombok.AllArgsConstructor; +import net.minecraft.client.resources.IResourcePack; +import net.minecraft.client.resources.data.IMetadataSection; +import net.minecraft.client.resources.data.IMetadataSerializer; +import net.minecraft.util.ResourceLocation; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.Set; + +@AllArgsConstructor +public class DGTexturePack implements IResourcePack { + + private final Authenticator authenticator; + + @Override + public InputStream getInputStream(ResourceLocation location) throws IOException { + InputStream inputStream = this.getClass().getResourceAsStream("/assets/dg/"+location.getResourcePath()); + if (inputStream != null) return inputStream; + return new ByteArrayInputStream(authenticator.getResources().get("assets/dg/"+location.getResourcePath())); + } + + @Override + public boolean resourceExists(ResourceLocation location) { + return authenticator.getResources().containsKey("assets/dg/"+location.getResourcePath()) + || this.getClass().getResourceAsStream("/assets/dg/"+location.getResourcePath()) != null; + } + + @Override + public Set<String> getResourceDomains() { + return Collections.singleton("dungeonsguide"); + } + + @Override + public <T extends IMetadataSection> T getPackMetadata(IMetadataSerializer p_135058_1_, String p_135058_2_) throws IOException { + return null; + } + + @Override + public BufferedImage getPackImage() throws IOException { + return new BufferedImage(512,512, BufferedImage.TYPE_INT_RGB); + } + + @Override + public String getPackName() { + return "Dungeons Guide Default Pack"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/EditingContext.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/EditingContext.java new file mode 100755 index 00000000..59a5d880 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/EditingContext.java @@ -0,0 +1,83 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonRoomEdit; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; + +import java.util.Stack; + +public class EditingContext { + + private static EditingContext editingContext; + + public static void createEditingContext(DungeonRoom dungeonRoom) { + editingContext = new EditingContext(dungeonRoom); + } + + public static EditingContext getEditingContext() { + return editingContext; + } + + public static void endEditingSession() { + editingContext = null; + Minecraft.getMinecraft().displayGuiScreen(null); + } + + + private EditingContext(DungeonRoom dungeonRoom) { + this.room = dungeonRoom; + } + + @Getter + private final DungeonRoom room; + + @Getter + private final Stack<GuiScreen> guiStack = new Stack<GuiScreen>(); + + public boolean isEditingSecrets() { + return guiDungeonRoomEdit.isEditingSelected(); + } + public void endEditing() { + guiDungeonRoomEdit.endEditing(); + } + + private GuiDungeonRoomEdit guiDungeonRoomEdit; + @Getter + private GuiScreen current; + + public void openGui(GuiScreen gui) { + if (gui instanceof GuiDungeonRoomEdit) guiDungeonRoomEdit = (GuiDungeonRoomEdit) gui; + guiStack.push(current); + this.current = gui; + Minecraft.getMinecraft().displayGuiScreen(gui); + } + + public void goBack() { + current = guiStack.pop(); + Minecraft.getMinecraft().displayGuiScreen(current); + } + + public void reopen() { + Minecraft.getMinecraft().displayGuiScreen(current); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/Parameter.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/Parameter.java new file mode 100755 index 00000000..5ca4ce69 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/Parameter.java @@ -0,0 +1,39 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit; + +import lombok.Data; + +@Data +public class Parameter { + private String name; + private Object previousData; + private Object newData; + + public Parameter(String name, Object previousData, Object newData) { + this.name = name; this.previousData = previousData; this.newData = newData; + } + + private Runnable onSetNewData; + + public void setNewData(Object newData) { + this.newData = newData; + if (onSetNewData != null) onSetNewData.run(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonAddSet.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonAddSet.java new file mode 100755 index 00000000..3d356451 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonAddSet.java @@ -0,0 +1,138 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.gui; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.gui.MGui; +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditOffsetPointSet; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import net.minecraft.client.Minecraft; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class GuiDungeonAddSet extends MGui { + + private final ValueEditOffsetPointSet valueEditOffsetPointSet; + + private final MButton add; + private final MButton back; + + + @Getter + private final OffsetPoint start; + @Getter + private final OffsetPoint end; + + public void onWorldRender(float partialTicks) { + for (OffsetPoint pos:getBlockPoses()) { + RenderUtils.highlightBlock(pos.getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(0,255,255,50), partialTicks); + } + RenderUtils.highlightBlock(start.getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(255,0,0,100), partialTicks); + RenderUtils.highlightBlock(end.getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(0,255,0,100), partialTicks); + } + + public List<OffsetPoint> getBlockPoses() { + int minX = Math.min(start.getX(), end.getX()); + int minY = Math.min(start.getY(), end.getY()); + int minZ = Math.min(start.getZ(), end.getZ()); + int maxX = Math.max(start.getX(), end.getX()); + int maxY = Math.max(start.getY(), end.getY()); + int maxZ = Math.max(start.getZ(), end.getZ()); + + List<OffsetPoint> offsetPoints = new ArrayList<OffsetPoint>(); + for (int z = minZ; z <= maxZ; z++) { + for (int x = minX; x <=maxX; x++) { + for (int y = maxY; y >= minY; y --) { + offsetPoints.add(new OffsetPoint(x,y,z)); + } + } + } + return offsetPoints; + } + + public void add() { + valueEditOffsetPointSet.addAll(getBlockPoses()); + } + + public GuiDungeonAddSet(final ValueEditOffsetPointSet processorParameterEditPane) { + this.valueEditOffsetPointSet = processorParameterEditPane; + getMainPanel().setBackgroundColor(new Color(17, 17, 17, 179)); + { + start = new OffsetPoint(EditingContext.getEditingContext().getRoom(), Minecraft.getMinecraft().thePlayer.getPosition()); + end = new OffsetPoint(EditingContext.getEditingContext().getRoom(), Minecraft.getMinecraft().thePlayer.getPosition()); + } + { + MValue mValue = new MValue(start, Collections.emptyList()); + mValue.setBounds(new Rectangle(0,0,150,20)); + getMainPanel().add(mValue); + MValue mValue2 = new MValue(end,Collections.emptyList()); + mValue2.setBounds(new Rectangle(0,20,150,20)); + getMainPanel().add(mValue2); + } + { + add = new MButton() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0,parentHeight - 20, parentWidth / 2, 20)); + } + }; + add.setText("Add"); + add.setBackgroundColor(Color.red); + add.setOnActionPerformed(new Runnable() { + @Override + public void run() { + add(); + EditingContext.getEditingContext().goBack(); + } + }); + + back = new MButton(){ + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(parentWidth / 2,parentHeight - 20, parentWidth / 2, 20)); + } + }; + back.setText("Go back"); + back.setBackgroundColor(Color.green); + back.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EditingContext.getEditingContext().goBack(); + } + }); + getMainPanel().add(add); + getMainPanel().add(back); + } + } + + @Override + public void initGui() { + super.initGui(); + // update bounds + getMainPanel().setBounds(new Rectangle(10, Math.min((Minecraft.getMinecraft().displayHeight - 300) / 2, Minecraft.getMinecraft().displayHeight),200,300)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonParameterEdit.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonParameterEdit.java new file mode 100755 index 00000000..b38fd5dc --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonParameterEdit.java @@ -0,0 +1,174 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.gui; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.gui.MGui; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.panes.DynamicEditor; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditRegistry; +import lombok.Getter; +import net.minecraft.client.Minecraft; + +import java.awt.*; + +public class GuiDungeonParameterEdit extends MGui { + + private final Parameter parameter; + private final DungeonRoom dungeonRoom; + + private String classSelection; + + private final MPanel currentValueEdit; + + private final MButton save; + private final MButton delete; + + @Getter + private ValueEdit valueEdit; + + public GuiDungeonParameterEdit(final MParameter parameter2, final DynamicEditor processorParameterEditPane) { + dungeonRoom = EditingContext.getEditingContext().getRoom(); + getMainPanel().setBackgroundColor(new Color(17, 17, 17, 179)); + this.parameter = parameter2.getParameter(); + { + MTextField mTextField = new MTextField() { + @Override + public void edit(String str) { + parameter.setName(str); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Name", mTextField); + + mTextField.setText(parameter.getName()); + mLabelAndElement.setBounds(new Rectangle(0,0,200, 20)); + getMainPanel().add(mLabelAndElement); + } + { + classSelection = parameter.getNewData() == null ?"null" : parameter.getNewData().getClass().getName(); + final MStringSelectionButton mStringSelectionButton = new MStringSelectionButton(processorParameterEditPane.allowedClass(), classSelection) { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, 20, parentWidth,20)); + } + + @Override + public String selectionToDisplay(String selection) { + String[] split = selection.split("\\."); + return super.selectionToDisplay(split[split.length - 1]); + } + }; + + mStringSelectionButton.setOnUpdate(new Runnable() { + @Override + public void run() { + classSelection = mStringSelectionButton.getSelected(); + updateClassSelection(); + } + }); + mStringSelectionButton.setBounds(new Rectangle(0,20,150,20)); + getMainPanel().add(mStringSelectionButton); + } + { + currentValueEdit = new MPanel(){ + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, 40, parentWidth,parentHeight - 60)); + } + }; + getMainPanel().add(currentValueEdit); + } + { + delete = new MButton() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0,parentHeight - 20, parentWidth / 2, 20)); + } + }; + delete.setText("Delete"); + delete.setBackgroundColor(Color.red); + delete.setOnActionPerformed(new Runnable() { + @Override + public void run() { + processorParameterEditPane.delete(parameter2); + EditingContext.getEditingContext().goBack(); + } + }); + + save = new MButton(){ + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(parentWidth / 2,parentHeight - 20, parentWidth / 2, 20)); + } + }; + save.setText("Go back"); + save.setBackgroundColor(Color.green); + save.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EditingContext.getEditingContext().goBack(); + } + }); + getMainPanel().add(delete); + getMainPanel().add(save); + } + updateClassSelection(); + } + + public void updateClassSelection() { + currentValueEdit.getChildComponents().clear(); + + ValueEditCreator valueEditCreator = ValueEditRegistry.getValueEditMap(classSelection); + + if (!classSelection.equals(parameter.getNewData() == null ?"null" :parameter.getNewData().getClass().getName())) { + parameter.setNewData(valueEditCreator.createDefaultValue(parameter)); + parameter.setPreviousData(valueEditCreator.cloneObj(parameter.getNewData())); + } + + MPanel valueEdit = (MPanel) valueEditCreator.createValueEdit(parameter); + if (valueEdit == null) { + MLabel valueEdit2 = new MLabel() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, 0, parentWidth,20)); + } + }; + valueEdit2.setText("No Value Edit"); + valueEdit2.setBounds(new Rectangle(0,0,150,20)); + valueEdit = valueEdit2; + this.valueEdit = null; + } else{ + this.valueEdit = (ValueEdit) valueEdit; + } + valueEdit.resize0(currentValueEdit.getBounds().width, currentValueEdit.getBounds().height); + currentValueEdit.add(valueEdit); + } + @Override + public void initGui() { + super.initGui(); + // update bounds + getMainPanel().setBounds(new Rectangle(10, Math.min((Minecraft.getMinecraft().displayHeight - 300) / 2, Minecraft.getMinecraft().displayHeight),200,300)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonRoomEdit.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonRoomEdit.java new file mode 100755 index 00000000..386a9b37 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonRoomEdit.java @@ -0,0 +1,69 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.gui; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.gui.MGui; +import kr.syeyoung.dungeonsguide.gui.elements.MTabbedPane; +import kr.syeyoung.dungeonsguide.roomedit.panes.*; +import kr.syeyoung.dungeonsguide.roomedit.panes.*; +import lombok.Getter; +import net.minecraft.client.Minecraft; + +import java.awt.*; + +public class GuiDungeonRoomEdit extends MGui { + + private final DungeonRoom room; + + private final MTabbedPane tabbedPane; + @Getter + private final SecretEditPane sep; + + public GuiDungeonRoomEdit(DungeonRoom room) { + this.room = room; + + MTabbedPane tabbedPane = new MTabbedPane(); + getMainPanel().add(tabbedPane); + tabbedPane.setBackground2(new Color(17, 17, 17, 179)); + + + tabbedPane.addTab("General", new GeneralEditPane(room)); + tabbedPane.addTab("Match", new RoomDataDisplayPane(room)); + tabbedPane.addTab("Secrets", sep = new SecretEditPane(room)); + tabbedPane.addTab("Actions", new ActionDisplayPane(room)); + tabbedPane.addTab("Test", new RoommatchingPane(room)); + tabbedPane.addTab("Proc.Params", new ProcessorParameterEditPane(room)); + this.tabbedPane = tabbedPane; + } + + public boolean isEditingSelected() { + return "Secrets".equals(tabbedPane.getSelectedKey()); + } + public void endEditing() { + tabbedPane.setSelectedKey("General"); + } + + @Override + public void initGui() { + super.initGui(); + // update bounds + getMainPanel().setBounds(new Rectangle(Math.min((Minecraft.getMinecraft().displayWidth - 500) / 2, Minecraft.getMinecraft().displayWidth), Math.min((Minecraft.getMinecraft().displayHeight - 300) / 2, Minecraft.getMinecraft().displayHeight),500,300)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonValueEdit.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonValueEdit.java new file mode 100755 index 00000000..65105830 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/gui/GuiDungeonValueEdit.java @@ -0,0 +1,129 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.gui; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.gui.MGui; +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditRegistry; +import lombok.Getter; +import net.minecraft.client.Minecraft; + +import java.awt.*; +import java.util.List; + +public class GuiDungeonValueEdit extends MGui { + private DungeonRoom dungeonRoom; + + + private MPanel currentValueEdit; + + private MButton save; + + @Getter + private ValueEdit valueEdit; + + private List<MPanel> addons; + + private Object editingObj; + + public GuiDungeonValueEdit(final Object object, final List<MPanel> addons) { + try { + dungeonRoom = EditingContext.getEditingContext().getRoom(); + this.addons = addons; + this.editingObj = object; + getMainPanel().setBackgroundColor(new Color(17, 17, 17, 179)); + { + currentValueEdit = new MPanel() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, 0, parentWidth, parentHeight - 20 - addons.size() * 20)); + } + }; + getMainPanel().add(currentValueEdit); + } + + for (MPanel addon : addons) { + getMainPanel().add(addon); + } + { + save = new MButton() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, parentHeight - 20, parentWidth, 20)); + } + }; + save.setText("Go back"); + save.setBackgroundColor(Color.green); + save.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EditingContext.getEditingContext().goBack(); + } + }); + getMainPanel().add(save); + } + updateClassSelection(); + } catch (Exception e){} + } + + public void updateClassSelection() { + currentValueEdit.getChildComponents().clear(); + + ValueEditCreator valueEditCreator = ValueEditRegistry.getValueEditMap(editingObj == null ?"null":editingObj.getClass().getName()); + + MPanel valueEdit = (MPanel) valueEditCreator.createValueEdit(new Parameter("", editingObj, editingObj)); + if (valueEdit == null) { + MLabel valueEdit2 = new MLabel() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, 0, parentWidth,20)); + } + }; + valueEdit2.setText("No Value Edit"); + valueEdit2.setBounds(new Rectangle(0,0,150,20)); + valueEdit = valueEdit2; + this.valueEdit = null; + } else{ + this.valueEdit = (ValueEdit) valueEdit; + } + valueEdit.resize0(currentValueEdit.getBounds().width, currentValueEdit.getBounds().height); + currentValueEdit.add(valueEdit); + } + @Override + public void initGui() { + super.initGui(); + // update bounds + getMainPanel().setBounds(new Rectangle(10, Math.min((Minecraft.getMinecraft().displayHeight - 300) / 2, Minecraft.getMinecraft().displayHeight),200,300)); + + + for (int i = 0; i < addons.size(); i++) { + addons.get(i).setBounds(new Rectangle(0, getMainPanel().getBounds().height - (i+1) * 20 - 20, getMainPanel().getBounds().width, 20)); + } + save.setBounds(new Rectangle(0 ,getMainPanel().getBounds().height - 20, getMainPanel().getBounds().width, 20)); + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditBreakableWall.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditBreakableWall.java new file mode 100755 index 00000000..1ae2541a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditBreakableWall.java @@ -0,0 +1,144 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonBreakableWall; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.init.Blocks; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Collections; + +public class ValueEditBreakableWall extends MPanel implements ValueEdit<DungeonBreakableWall> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonBreakableWall dungeonBreakableWall; + + private final MLabel label; + private final MValue<OffsetPointSet> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + private final MButton updateOnlyAir; + + public ValueEditBreakableWall(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonBreakableWall = (DungeonBreakableWall) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Wall Points"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonBreakableWall.getSecretPoint(), Collections.emptyList()); + add(value); + + updateOnlyAir = new MButton(); + updateOnlyAir.setText("Update Air"); + updateOnlyAir.setBackgroundColor(Color.green); + updateOnlyAir.setForeground(Color.black); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + add(updateOnlyAir); + updateOnlyAir.setOnActionPerformed(new Runnable() { + @Override + public void run() { + OffsetPointSet ofs = dungeonBreakableWall.getSecretPoint(); + List<OffsetPoint> filtered = new ArrayList<OffsetPoint>(); + for (OffsetPoint offsetPoint : ofs.getOffsetPointList()) { + if (offsetPoint.getBlock(EditingContext.getEditingContext().getRoom()) != Blocks.air) continue; + filtered.add(offsetPoint); + } + dungeonBreakableWall.getSecretPoint().setOffsetPointList(filtered); + } + }); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonBreakableWall.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonBreakableWall.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonBreakableWall.highlight(new Color(0,255,255,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditBreakableWall> { + + @Override + public ValueEditBreakableWall createValueEdit(Parameter parameter) { + return new ValueEditBreakableWall(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonBreakableWall(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonBreakableWall)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditDoor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditDoor.java new file mode 100755 index 00000000..949e5c2e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditDoor.java @@ -0,0 +1,158 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonDoor; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.init.Blocks; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class ValueEditDoor extends MPanel implements ValueEdit<DungeonDoor> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonDoor dungeonDoor; + + private final MLabel label; + private final MValue<OffsetPointSet> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite_par; + private final MTextField preRequisite2; + private final MLabelAndElement preRequisite2_par; + private final MButton updateOnlyAir; + + public ValueEditDoor(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonDoor = (DungeonDoor) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Wall Points"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonDoor.getSecretPoint(), Collections.emptyList()); + add(value); + + updateOnlyAir = new MButton(); + updateOnlyAir.setText("Update Air"); + updateOnlyAir.setBackgroundColor(Color.green); + updateOnlyAir.setForeground(Color.black); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + add(updateOnlyAir); + updateOnlyAir.setOnActionPerformed(new Runnable() { + @Override + public void run() { + OffsetPointSet ofs = dungeonDoor.getSecretPoint(); + List<OffsetPoint> filtered = new ArrayList<OffsetPoint>(); + for (OffsetPoint offsetPoint : ofs.getOffsetPointList()) { + if (offsetPoint.getBlock(EditingContext.getEditingContext().getRoom()) != Blocks.air) continue; + filtered.add(offsetPoint); + } + dungeonDoor.getSecretPoint().setOffsetPointList(filtered); + } + }); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonDoor.setOpenPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonDoor.getOpenPreRequisite(), ",")); + preRequisite_par = new MLabelAndElement("Open Req.",preRequisite); + preRequisite_par.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(preRequisite_par); + + preRequisite2 = new MTextField() { + @Override + public void edit(String str) { + dungeonDoor.setClosePreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite2.setText(TextUtils.join(dungeonDoor.getClosePreRequisite(), ",")); + preRequisite2_par = new MLabelAndElement("Close Req.",preRequisite2); + preRequisite2_par.setBounds(new Rectangle(0,80,getBounds().width,20)); + add(preRequisite2_par); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + preRequisite_par.setBounds(new Rectangle(0,60,getBounds().width,20)); + preRequisite2_par.setBounds(new Rectangle(0,80,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonDoor.highlight(new Color(0,255,255,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditDoor> { + + @Override + public ValueEditDoor createValueEdit(Parameter parameter) { + return new ValueEditDoor(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonDoor(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonDoor)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditDummy.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditDummy.java new file mode 100755 index 00000000..c0cae9b8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditDummy.java @@ -0,0 +1,121 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonDummy; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditDummy extends MPanel implements ValueEdit<DungeonDummy> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonDummy dungeonSecret; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditDummy(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonSecret = (DungeonDummy) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Dummy Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonSecret.getSecretPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonSecret.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonSecret.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonSecret.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditDummy> { + + @Override + public ValueEditDummy createValueEdit(Parameter parameter) { + return new ValueEditDummy(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonDummy(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonDummy)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditFairySoul.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditFairySoul.java new file mode 100755 index 00000000..8deb8d85 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditFairySoul.java @@ -0,0 +1,122 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonFairySoul; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditFairySoul extends MPanel implements ValueEdit<DungeonFairySoul> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonFairySoul dungeonSecret; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditFairySoul(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonSecret = (DungeonFairySoul) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("FairySoul Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonSecret.getSecretPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonSecret.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonSecret.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonSecret.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditFairySoul> { + + @Override + public ValueEditFairySoul createValueEdit(Parameter parameter) { + return new ValueEditFairySoul(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonFairySoul(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonFairySoul)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditJournal.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditJournal.java new file mode 100755 index 00000000..aa82763a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditJournal.java @@ -0,0 +1,122 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonJournal; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + + +public class ValueEditJournal extends MPanel implements ValueEdit<DungeonJournal> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonJournal dungeonSecret; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditJournal(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonSecret = (DungeonJournal) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Journal Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonSecret.getSecretPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonSecret.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonSecret.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonSecret.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditJournal> { + + @Override + public ValueEditJournal createValueEdit(Parameter parameter) { + return new ValueEditJournal(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonJournal(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonJournal)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditLever.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditLever.java new file mode 100755 index 00000000..145209a5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditLever.java @@ -0,0 +1,137 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonLever; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditLever extends MPanel implements ValueEdit<DungeonLever> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonLever dungeonLever; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + private final MTextField target; + private final MLabelAndElement target2; + + public ValueEditLever(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonLever = (DungeonLever) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Secret Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonLever.getLeverPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonLever.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonLever.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + + + target = new MTextField() { + @Override + public void edit(String str) { + dungeonLever.setTriggering(str); + } + }; + target.setText(dungeonLever.getTriggering()); + target2 = new MLabelAndElement("Target",target); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(target2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonLever.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditLever> { + + @Override + public ValueEditLever createValueEdit(Parameter parameter) { + return new ValueEditLever(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonLever(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonLever)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditNPC.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditNPC.java new file mode 100755 index 00000000..83c9e69c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditNPC.java @@ -0,0 +1,121 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonNPC; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditNPC extends MPanel implements ValueEdit<DungeonNPC> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonNPC dungeonSecret; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditNPC(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonSecret = (DungeonNPC) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("NPC Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonSecret.getSecretPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonSecret.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonSecret.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonSecret.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditNPC> { + + @Override + public ValueEditNPC createValueEdit(Parameter parameter) { + return new ValueEditNPC(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonNPC(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonNPC)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditOnewayDoor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditOnewayDoor.java new file mode 100755 index 00000000..cd9a8427 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditOnewayDoor.java @@ -0,0 +1,144 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonOnewayDoor; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.init.Blocks; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class ValueEditOnewayDoor extends MPanel implements ValueEdit<DungeonOnewayDoor> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonOnewayDoor dungeonDoor; + + private final MLabel label; + private final MValue<OffsetPointSet> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + private final MButton updateOnlyAir; + + public ValueEditOnewayDoor(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonDoor = (DungeonOnewayDoor) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Wall Points"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonDoor.getSecretPoint(), Collections.emptyList()); + add(value); + + updateOnlyAir = new MButton(); + updateOnlyAir.setText("Update Air"); + updateOnlyAir.setBackgroundColor(Color.green); + updateOnlyAir.setForeground(Color.black); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + add(updateOnlyAir); + updateOnlyAir.setOnActionPerformed(new Runnable() { + @Override + public void run() { + OffsetPointSet ofs = dungeonDoor.getSecretPoint(); + List<OffsetPoint> filtered = new ArrayList<OffsetPoint>(); + for (OffsetPoint offsetPoint : ofs.getOffsetPointList()) { + if (offsetPoint.getBlock(EditingContext.getEditingContext().getRoom()) != Blocks.air) continue; + filtered.add(offsetPoint); + } + dungeonDoor.getSecretPoint().setOffsetPointList(filtered); + } + }); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonDoor.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonDoor.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonDoor.highlight(new Color(0,255,255,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditOnewayDoor> { + + @Override + public ValueEditOnewayDoor createValueEdit(Parameter parameter) { + return new ValueEditOnewayDoor(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonOnewayDoor(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonOnewayDoor)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditOnewayLever.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditOnewayLever.java new file mode 100755 index 00000000..1c1588de --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditOnewayLever.java @@ -0,0 +1,137 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonOnewayLever; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditOnewayLever extends MPanel implements ValueEdit<DungeonOnewayLever> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonOnewayLever dungeonLever; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + private final MTextField target; + private final MLabelAndElement target2; + + + public ValueEditOnewayLever(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonLever = (DungeonOnewayLever) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Secret Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonLever.getLeverPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonLever.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonLever.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + + + target = new MTextField() { + @Override + public void edit(String str) { + dungeonLever.setTriggering(str); + } + }; + target.setText(dungeonLever.getTriggering()); + target2 = new MLabelAndElement("Target",target); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(target2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonLever.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditOnewayLever> { + + @Override + public ValueEditOnewayLever createValueEdit(Parameter parameter) { + return new ValueEditOnewayLever(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonOnewayLever(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonOnewayLever)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditPressurePlate.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditPressurePlate.java new file mode 100755 index 00000000..ffab9440 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditPressurePlate.java @@ -0,0 +1,136 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonPressurePlate; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditPressurePlate extends MPanel implements ValueEdit<DungeonPressurePlate> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonPressurePlate dungeonPressureplate; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + private final MTextField target; + private final MLabelAndElement target2; + + + public ValueEditPressurePlate(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonPressureplate = (DungeonPressurePlate) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Secret Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonPressureplate.getPlatePoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonPressureplate.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonPressureplate.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + + + target = new MTextField() { + @Override + public void edit(String str) { + dungeonPressureplate.setTriggering(str); + } + }; + target.setText(dungeonPressureplate.getTriggering()); + target2 = new MLabelAndElement("Target",target); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(target2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonPressureplate.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditPressurePlate> { + + @Override + public ValueEditPressurePlate createValueEdit(Parameter parameter) { + return new ValueEditPressurePlate(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonPressurePlate(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonPressurePlate)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditSecret.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditSecret.java new file mode 100755 index 00000000..aed8e10a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditSecret.java @@ -0,0 +1,130 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonSecret; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditSecret extends MPanel implements ValueEdit<DungeonSecret> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonSecret dungeonSecret; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MStringSelectionButton selectionButton; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditSecret(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonSecret = (DungeonSecret) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Secret Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonSecret.getSecretPoint(), Collections.emptyList()); + add(value); + + selectionButton = new MStringSelectionButton(Arrays.asList("CHEST", "BAT", "ITEM_DROP", "ESSENCE"), dungeonSecret.getSecretType().name()); + selectionButton.setOnUpdate(new Runnable() { + @Override + public void run() { + dungeonSecret.setSecretType(DungeonSecret.SecretType.valueOf(selectionButton.getSelected())); + } + }); + add(selectionButton); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonSecret.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonSecret.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + selectionButton.setBounds(new Rectangle(0,40,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonSecret.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditSecret> { + + @Override + public ValueEditSecret createValueEdit(Parameter parameter) { + return new ValueEditSecret(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonSecret(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonSecret)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditTomb.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditTomb.java new file mode 100755 index 00000000..291883b0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/mechanicedit/ValueEditTomb.java @@ -0,0 +1,122 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonTomb; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditTomb extends MPanel implements ValueEdit<DungeonTomb> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonTomb dungeonTomb; + + private final MLabel label; + private final MValue<OffsetPointSet> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditTomb(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonTomb = (DungeonTomb) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Tomb Points"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonTomb.getSecretPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonTomb.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonTomb.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonTomb.highlight(new Color(0,255,255,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditTomb> { + + @Override + public ValueEditTomb createValueEdit(Parameter parameter) { + return new ValueEditTomb(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonTomb(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonTomb)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/ActionDisplayPane.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/ActionDisplayPane.java new file mode 100755 index 00000000..40be4c3e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/ActionDisplayPane.java @@ -0,0 +1,84 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.panes; + +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionTree; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.gui.elements.*; + +import java.awt.*; + +public class ActionDisplayPane extends MPanel { + private final DungeonRoom dungeonRoom; + + private ActionTreeDisplayPane displayPane; + + private final MTextField textField; + private final MButton calculate; + public ActionDisplayPane(final DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + + { + textField = new MTextField(); + textField.setBounds(new Rectangle(0,0,getBounds().width - 100, 20)); + add(textField); + } + { + calculate = new MButton(); + calculate.setBounds(new Rectangle(getBounds().width - 100,0,100, 20)); + calculate.setText("calculate"); + calculate.setOnActionPerformed(new Runnable() { + @Override + public void run() { + try { + remove(displayPane); + + String text = textField.getText(); + String target = text.split(":")[0]; + String state = text.split(":")[1]; + ActionChangeState actionChangeState = new ActionChangeState(target, state); + ActionTree tree= ActionTree.buildActionTree(actionChangeState, dungeonRoom); + + displayPane = new ActionTreeDisplayPane(dungeonRoom, tree); + displayPane.setBounds(new Rectangle(0,25,getBounds().width,getBounds().height-25)); + add(displayPane); + } catch (Throwable t) { + t.printStackTrace(); + } + } + }); + add(calculate); + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + @Override + public void onBoundsUpdate() { + textField.setBounds(new Rectangle(0,0,getBounds().width - 100, 20)); + calculate.setBounds(new Rectangle(getBounds().width - 100,0,100, 20)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/ActionTreeDisplayPane.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/ActionTreeDisplayPane.java new file mode 100755 index 00000000..be0d294c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/ActionTreeDisplayPane.java @@ -0,0 +1,216 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.panes; + +import kr.syeyoung.dungeonsguide.dungeon.actions.Action; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionTree; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionTreeUtil; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class ActionTreeDisplayPane extends MPanel { + + private int offsetX = 0; + private int offsetY = 0; + + private float scale; + + private final DungeonRoom dungeonRoom; + private final ActionTree tree; + private List<Action> linearified; + public ActionTreeDisplayPane(DungeonRoom dungeonRoom, ActionTree tree) { + this.dungeonRoom = dungeonRoom; + this.tree = tree; + try { + this.linearified = ActionTreeUtil.linearifyActionTree(tree); + } catch (Exception e) { + linearified = new ArrayList<Action>(); + e.printStackTrace(); + } + scale = 1.0f; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + GlStateManager.pushMatrix(); + GlStateManager.translate(offsetX, offsetY, 0); + GlStateManager.scale(scale,scale,1); + int x = renderTree(tree, 5, 5, Minecraft.getMinecraft().fontRendererObj, null, new HashMap<ActionTree, Point>()); + renderLinearified(linearified, x, 5, fr); + GlStateManager.popMatrix(); + } + + public int renderTree(ActionTree actionTree, int x, int y, FontRenderer fr, Point drawLineFrom, HashMap<ActionTree, Point> drawmPoints) { + if (drawmPoints.containsKey(actionTree)) { + // recursive, fu + Point pt = drawmPoints.get(actionTree); + + GlStateManager.pushMatrix(); + + GlStateManager.enableBlend(); + GlStateManager.disableDepth(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(770, 771); + GlStateManager.enableBlend(); + GL11.glLineWidth(1); + GlStateManager.color(1, 0, 0, 1); + GL11.glBegin(2); + GL11.glVertex2d(drawLineFrom.x, drawLineFrom.y); + GL11.glVertex2d(pt.x, pt.y); + GL11.glEnd(); + GlStateManager.disableBlend(); + GlStateManager.enableTexture2D(); + GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + + return 0; + } + + Dimension dim = renderAction(actionTree.getCurrent(), x, y, fr); + if (drawLineFrom != null) { + GlStateManager.pushMatrix(); + + + GlStateManager.enableBlend(); + GlStateManager.disableDepth(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(770, 771); + GlStateManager.enableBlend(); + GL11.glLineWidth(1); + GlStateManager.color(1, 1, 1, 1); + GL11.glBegin(2); + GL11.glVertex2d(drawLineFrom.x, drawLineFrom.y); + GL11.glVertex2d(x + dim.width / 2, y); + GL11.glEnd(); + GlStateManager.disableBlend(); + GlStateManager.enableTexture2D(); + GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + + } + Point pt = new Point(x + dim.width / 2, y + dim.height); + + drawmPoints.put(actionTree, new Point(x + dim.width / 2, y + dim.height / 2)); + int xOff = 0; + for (ActionTree tree:actionTree.getChildren()) { + xOff += renderTree(tree, x + xOff, y + dim.height + 10, fr, pt, drawmPoints) + 10; + } + return Math.max(xOff, dim.width); + } + + public void renderLinearified(List<Action> actions, int x, int y, FontRenderer fr) { + Point lastPt = null; + int y2 = y; + + for (Action action : actions) { + Dimension dim = renderAction(action, x, y2, fr); + if (lastPt != null) { + GlStateManager.pushMatrix(); + + + GlStateManager.enableBlend(); + GlStateManager.disableDepth(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(770, 771); + GlStateManager.enableBlend(); + GL11.glLineWidth(1); + GlStateManager.color(1, 1, 1, 1); + GL11.glBegin(2); + GL11.glVertex2d(lastPt.x, lastPt.y); + GL11.glVertex2d(x + dim.width / 2, y2); + GL11.glEnd(); + GlStateManager.disableBlend(); + GlStateManager.enableTexture2D(); + GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + + } + lastPt = new Point(x + dim.width / 2, y2 + dim.height); + + y2 += dim.height + 10; + } + } + + public Dimension renderAction(Action action, int x, int y, FontRenderer fr) { + String[] lines = action.toString().split("\n"); + int maxWidth = 0; + for (String line : lines) { + if (fr.getStringWidth(line) > maxWidth) maxWidth= fr.getStringWidth(line); + } + int offset = 2; + int height = (fr.FONT_HEIGHT + offset) * lines.length; + + Gui.drawRect(x,y,x + maxWidth +10, y + height + 10, 0xff000000); + Gui.drawRect(x+1,y+1,x + maxWidth +8, y + height + 8, 0xff4d4d4d); + for (int i = 0; i < lines.length; i++) { + fr.drawString(lines[i], x + 5, y + 5 + i*(fr.FONT_HEIGHT + offset), 0xffffffff); + } + + return new Dimension(maxWidth + 10, height + 10); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,25,parentWidth,parentHeight-25)); + } + + + private int lastX; + private int lastY; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + lastX = absMouseX; + lastY = absMouseY; + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + int dX = absMouseX - lastX; + int dY = absMouseY - lastY; + offsetX += dX; + offsetY += dY; + lastX = absMouseX; + lastY = absMouseY; + } + + @Override + public void mouseScrolled0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (scrollAmount > 0) scale += 0.1; + if (scrollAmount < 0) scale -= 0.1; + + if (scale < 0) scale = 0.1f; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/DynamicEditor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/DynamicEditor.java new file mode 100755 index 00000000..8d3ba5e9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/DynamicEditor.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.panes; + +import kr.syeyoung.dungeonsguide.gui.elements.MParameter; + +import java.util.List; + +public interface DynamicEditor { + void delete(MParameter parameter); + + List<String> allowedClass(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/GeneralEditPane.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/GeneralEditPane.java new file mode 100755 index 00000000..0abda1c0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/GeneralEditPane.java @@ -0,0 +1,286 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.panes; + +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoomInfoRegistry; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.roomprocessor.ProcessorFactory; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; + +import java.awt.*; +import java.io.*; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.UUID; +import java.util.zip.GZIPOutputStream; + +public class GeneralEditPane extends MPanel { + private final DungeonRoom dungeonRoom; + + private final MLabelAndElement uuid; + private final MLabelAndElement name; + private final MLabelAndElement secrets; + + private final MLabelAndElement shape; + private final MLabelAndElement rotation; + private final MLabelAndElement shape2; + + private MButton save; + private final MButton end; + private final MButton schematic; + + private final MLabelAndElement roomProcessor; + + public GeneralEditPane(final DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + { + MLabel la; + uuid = new MLabelAndElement("Room UUID: ", la = new MLabel()); + la.setText(dungeonRoom.getDungeonRoomInfo().getUuid().toString()); + uuid.setBounds(new Rectangle(0,0,getBounds().width, 20)); + add(uuid); + } + { + MTextField la = new MTextField() { + @Override + public void edit(String str) { + dungeonRoom.getDungeonRoomInfo().setName(str); + } + }; + name = new MLabelAndElement("Room Name: ", la); + la.setText(dungeonRoom.getDungeonRoomInfo().getName()); + name.setBounds(new Rectangle(0,20,getBounds().width, 20)); + add(name); + } + { + final MIntegerSelectionButton la = new MIntegerSelectionButton(dungeonRoom.getDungeonRoomInfo().getTotalSecrets()); + la.setOnUpdate(new Runnable() { + @Override + public void run() { + dungeonRoom.getDungeonRoomInfo().setTotalSecrets(la.getData()); + } + }); + secrets = new MLabelAndElement("Room Secrets: ", la); + secrets.setBounds(new Rectangle(0,40,getBounds().width, 20)); + add(secrets); + } + + { + MLabel la; + shape = new MLabelAndElement("Room Shape: ", la = new MLabel()); + la.setText(dungeonRoom.getDungeonRoomInfo().getShape()+""); + shape.setBounds(new Rectangle(0,60,getBounds().width, 20)); + add(shape); + } + + { + MLabel la; + rotation = new MLabelAndElement("Found Room Rotation: ", la = new MLabel()); + la.setText(dungeonRoom.getRoomMatcher().getRotation()+""); + rotation.setBounds(new Rectangle(0,80,getBounds().width, 20)); + add(rotation); + } + { + MLabel la; + shape2 = new MLabelAndElement("Found Room Shape: ", la = new MLabel()); + la.setText(dungeonRoom.getShape()+""); + shape2.setBounds(new Rectangle(0,100,getBounds().width, 20)); + add(shape2); + } + { + final MStringSelectionButton mStringSelectionButton = new MStringSelectionButton(new ArrayList<String>(ProcessorFactory.getProcessors()), dungeonRoom.getDungeonRoomInfo().getProcessorId()); + roomProcessor = new MLabelAndElement("Room Processor: ", mStringSelectionButton); + roomProcessor.setBounds(new Rectangle(0,120,getBounds().width, 20)); + add(roomProcessor); + + mStringSelectionButton.setOnUpdate(new Runnable() { + @Override + public void run() { + dungeonRoom.getDungeonRoomInfo().setProcessorId(mStringSelectionButton.getSelected()); + dungeonRoom.updateRoomProcessor(); + } + }); + } + { + end = new MButton(); + end.setText("End Editing Session"); + end.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EditingContext.endEditingSession(); + } + }); + end.setBackgroundColor(Color.green); + end.setBounds(new Rectangle(0,140,getBounds().width, 20)); + add(end); + } + { + schematic = new MButton(); + schematic.setText("Save Schematic"); + schematic.setOnActionPerformed(new Runnable() { + @Override + public void run() { + try { + NBTTagCompound nbtTagCompound2 = createNBT(); + + File f=new File(DungeonsGuide.getDungeonsGuide().getConfigDir(), "schematics/"+ + dungeonRoom.getDungeonRoomInfo().getName()+"-"+dungeonRoom.getDungeonRoomInfo().getUuid().toString()+"-"+ UUID.randomUUID()+".schematic"); + + Method method = null; + try { + method = NBTTagCompound.class.getDeclaredMethod("write", DataOutput.class); + method.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + return; + } + FileOutputStream fos = new FileOutputStream(f); + DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(fos))); + + try + { + dataoutputstream.writeByte(nbtTagCompound2.getId()); + + dataoutputstream.writeUTF("Schematic"); + method.invoke(nbtTagCompound2, dataoutputstream); + } + finally + { + dataoutputstream.close(); + } + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fSaved to "+f.getName())); + } catch (Throwable e) { + e.printStackTrace(); + } + + } + }); + schematic.setBackgroundColor(Color.orange); + schematic.setBounds(new Rectangle(0,180,getBounds().width, 20)); + add(schematic); + } + { + if (dungeonRoom.getDungeonRoomInfo().isRegistered()) return; + save = new MButton(); + save.setText("Save RoomData"); + save.setOnActionPerformed(new Runnable() { + @Override + public void run() { + DungeonRoomInfoRegistry.register(dungeonRoom.getDungeonRoomInfo()); + remove(save); + } + }); + save.setBackgroundColor(Color.green); + save.setBounds(new Rectangle(0,10,getBounds().width, 20)); + add(save); + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + @Override + public void onBoundsUpdate() { + if (save != null) + save.setBounds(new Rectangle(0,160,getBounds().width, 20)); + end.setBounds(new Rectangle(1,140,getBounds().width-2, 20)); + if (schematic != null) + schematic.setBounds(new Rectangle(0,180,getBounds().width, 20)); + } + + private NBTTagCompound createNBT() { + NBTTagCompound compound = new NBTTagCompound(); + compound.setShort("Width", (short) (dungeonRoom.getMax().getX() - dungeonRoom.getMin().getX() + 1)); + compound.setShort("Height", (short) 255); + compound.setShort("Length", (short) (dungeonRoom.getMax().getZ() - dungeonRoom.getMin().getZ() + 1)); + int size =compound.getShort("Width") * compound.getShort("Height") * compound.getShort("Length"); + + byte[] blocks = new byte[size]; + byte[] meta = new byte[size]; + byte[] extra = new byte[size]; + byte[] extranibble = new byte[(int) Math.ceil(size / 2.0)]; + + boolean extraEx = false; + NBTTagList tileEntitiesList = new NBTTagList(); + for (int x = 0; x < compound.getShort("Width"); x++) { + for (int y = 0; y < compound.getShort("Height"); y++) { + for (int z = 0; z < compound.getShort("Length"); z++) { + int index = x + (y * compound.getShort("Length") + z) * compound.getShort("Width"); + BlockPos pos = dungeonRoom.getRelativeBlockPosAt(x,y - 70,z); + IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(pos); + boolean acc = dungeonRoom.canAccessRelative(x,z); + int id = Block.getIdFromBlock(blockState.getBlock()); + blocks[index] = acc ? (byte) id : 0; + meta[index] = acc ? (byte) blockState.getBlock().getMetaFromState(blockState) : 0; + if ((extra[index] = (byte) ((acc ? id : 0) >> 8)) > 0) { + extraEx = true; + } + + if (blockState.getBlock().hasTileEntity(blockState)) { + TileEntity tileEntity = dungeonRoom.getContext().getWorld().getTileEntity(pos); + try { + final NBTTagCompound tileEntityCompound = new NBTTagCompound(); + tileEntity.writeToNBT(tileEntityCompound); + tileEntitiesList.appendTag(tileEntityCompound); + } catch (final Exception e) { + final BlockPos tePos = tileEntity.getPos(); + + blocks[index] = (byte) 7; + meta[index] = 0; + extra[index] = 0; + } + } + } + } + } + for (int i = 0; i < extranibble.length; i++) { + if (i * 2 + 1 < extra.length) { + extranibble[i] = (byte) ((extra[i * 2 + 0] << 4) | extra[i * 2 + 1]); + } else { + extranibble[i] = (byte) (extra[i * 2 + 0] << 4); + } + } + + + compound.setByteArray("Blocks", blocks); + compound.setByteArray("Data", meta); + compound.setString("Materials", "Alpha"); + if (extraEx) { + compound.setByteArray("AddBlocks", extranibble); + } + compound.setTag("Entities", new NBTTagList()); + compound.setTag("TileEntities", tileEntitiesList); + + return compound; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/ProcessorParameterEditPane.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/ProcessorParameterEditPane.java new file mode 100755 index 00000000..57038f3b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/ProcessorParameterEditPane.java @@ -0,0 +1,144 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.panes; + +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MParameter; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditRegistry; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class ProcessorParameterEditPane extends MPanel implements DynamicEditor { + private final DungeonRoom dungeonRoom; + + private MButton save; + private MButton create; + private final List<MParameter> parameters = new ArrayList<MParameter>(); + + public ProcessorParameterEditPane(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + buildElements(); + } + + public void buildElements() { + { + create = new MButton(); + create.setText("Create New Parameter"); + create.setBackgroundColor(Color.cyan); + create.setBounds(new Rectangle(0,0,100,20)); + create.setOnActionPerformed(new Runnable() { + @Override + public void run() { + MParameter parameter; + parameters.add(parameter = new MParameter(new Parameter(UUID.randomUUID().toString(), null, null), ProcessorParameterEditPane.this)); + parameter.setParent(ProcessorParameterEditPane.this); + parameter.setBounds(new Rectangle(0,0,getBounds().width, 20)); + } + }); + + save = new MButton(); + save.setText("Save"); + save.setBackgroundColor(Color.green); + save.setBounds(new Rectangle(0,0,100,20)); + save.setOnActionPerformed(new Runnable() { + @Override + public void run() { + DungeonRoomInfo dungeonRoomInfo = dungeonRoom.getDungeonRoomInfo(); + dungeonRoomInfo.getProperties().clear(); + + for (MParameter parameter : parameters) { + Parameter real = parameter.getParameter(); + + ValueEditCreator vec = ValueEditRegistry.getValueEditMap(real.getNewData() == null ? "null" :real.getNewData().getClass().getName()); + + real.setPreviousData(vec.cloneObj(real.getNewData())); + dungeonRoomInfo.getProperties().put(real.getName(), real.getNewData()); + } + } + }); + create.setParent(this); save.setParent(this); + } + { + for (Map.Entry<String, Object> en : dungeonRoom.getDungeonRoomInfo().getProperties().entrySet()) { + ValueEditCreator vec = ValueEditRegistry.getValueEditMap(en.getValue() == null ? "null" :en.getValue().getClass().getName()); + + MParameter mParameter = new MParameter(new Parameter(en.getKey(), vec.cloneObj(en.getValue()), vec.cloneObj(en.getValue())), this); + mParameter.setBounds(new Rectangle(0,0,getBounds().width,20)); + parameters.add(mParameter); + mParameter.setParent(this); + } + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + + public void delete(MParameter parameter) { + parameters.remove(parameter); + } + + @Override + public List<String> allowedClass() { + return ValueEditRegistry.getClassesSupported(); + } + + + @Override + public List<MPanel> getChildComponents() { + ArrayList<MPanel> panels = new ArrayList<MPanel>(parameters); + panels.add(create); + panels.add(save); + return panels; + } + + private int offsetY = 0; + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + int heights = 0; + for (MPanel panel:getChildComponents()) { + panel.setPosition(new Point(0, -offsetY + heights)); + heights += panel.getBounds().height; + } + } + + @Override + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (scrollAmount > 0) offsetY -= 20; + else if (scrollAmount < 0) offsetY += 20; + if (offsetY < 0) offsetY = 0; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoomDataDisplayPane.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoomDataDisplayPane.java new file mode 100755 index 00000000..cae9637b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoomDataDisplayPane.java @@ -0,0 +1,126 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.panes; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import java.awt.*; + +public class RoomDataDisplayPane extends MPanel { + + private int offsetX = 0; + private int offsetY = 0; + + private int selectedX = -1; + private int selectedY = -1; + + private final DungeonRoom dungeonRoom; + public RoomDataDisplayPane(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + int[][] blocks = dungeonRoom.getDungeonRoomInfo().getBlocks(); + // draw Axis; + Gui.drawRect(0,0,10,10,0x77777777); + clip(clip.x + 10, clip.y, clip.width - 10, 10); + Gui.drawRect(0,0,getBounds().width, getBounds().height, 0x77777777); + for (int x = 0; x < blocks[0].length; x++) { + fr.drawString(x+"", x * 16 +10 + offsetX, 0, 0xFFFFFFFF); + } + clip(clip.x, clip.y +10, 10, clip.height-10); + Gui.drawRect(0,0,getBounds().width, getBounds().height, 0x77777777); + for (int z = 0; z < blocks.length; z++) { + fr.drawString(z+"", 2, z * 16 + 10 + offsetY, 0xFFFFFFFF); + } + + int hoverX = (relMousex0 - offsetX - 10) / 16; + int hoverY = (relMousey0 - offsetY - 10) / 16; + // draw Content + clip(clip.x + 10, clip.y +10, clip.width - 10, clip.height - 10); + for (int z = 0; z < blocks.length; z++) { + for (int x = 0; x < blocks[z].length; x++) { + int data = blocks[z][x]; + if (z == selectedY && x == selectedX){ + Gui.drawRect(x *16 +10+offsetX, z *16 +10 + offsetY, x *16 +26 +offsetX, z *16 +26 + offsetY, 0xAA707070); + } else if (z == hoverY && x == hoverX) { + Gui.drawRect(x *16 +10+offsetX, z *16 +10 + offsetY, x *16 +26 +offsetX, z *16 +26 + offsetY, 0xAA505050); + } + + + if (data == -1) fr.drawString("X", x *16 +10 + offsetX, z *16 +10 + offsetY,0xFFFFFF); + else drawItemStack(new ItemStack(Item.getItemFromBlock(Block.getBlockById(data)), 1), x * 16 +10 + offsetX, z *16 +10 + offsetY); + } + } + + } + private void drawItemStack(ItemStack stack, int x, int y) + { + Minecraft.getMinecraft().getRenderItem().renderItemAndEffectIntoGUI(stack, x, y); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + @Override + public void keyPressed(char typedChar, int keyCode) { + int[][] blocks = dungeonRoom.getDungeonRoomInfo().getBlocks(); + if (selectedX != -1 && selectedY != -1 && selectedY < blocks.length && selectedX < blocks[0].length) { + dungeonRoom.getDungeonRoomInfo().getBlocks()[selectedY][selectedX] = -1; + } + } + + private int lastX; + private int lastY; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + lastX = absMouseX; + lastY = absMouseY; + + if (lastAbsClip.contains(absMouseX, absMouseY)) { + selectedX = (relMouseX - offsetX - 10) / 16; + selectedY = (relMouseY - offsetY - 10) / 16; + } + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + int dX = absMouseX - lastX; + int dY = absMouseY - lastY; + offsetX += dX; + offsetY += dY; + lastX = absMouseX; + lastY = absMouseY; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoomMatchDisplayPane.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoomMatchDisplayPane.java new file mode 100755 index 00000000..7a75b01d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoomMatchDisplayPane.java @@ -0,0 +1,152 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.panes; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoomInfoRegistry; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MTooltip; +import kr.syeyoung.dungeonsguide.gui.elements.MTooltipText; +import kr.syeyoung.dungeonsguide.utils.ArrayUtils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import java.awt.*; +import java.util.Arrays; +import java.util.UUID; + +public class RoomMatchDisplayPane extends MPanel { + + private int offsetX = 0; + private int offsetY = 0; + + private final DungeonRoom dungeonRoom; + + private final int[][] currentBlocks; + private int[][] targetBlocks; + public RoomMatchDisplayPane(DungeonRoom dungeonRoom, UUID uid, int rotation) { + this.dungeonRoom = dungeonRoom; + + currentBlocks = dungeonRoom.getRoomMatcher().createNew().getBlocks(); + targetBlocks = DungeonRoomInfoRegistry.getByUUID(uid).getBlocks(); + for (int i = 0; i < rotation; i++) + targetBlocks = ArrayUtils.rotateCounterClockwise(targetBlocks); + } + + MTooltip mTooltip; + int lastTooltipX = -1, lastTooltipZ = -1; + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + int height = Math.max(currentBlocks.length, targetBlocks.length); + int width = Math.max(currentBlocks[0].length, targetBlocks[0].length); + + // draw Axis; + Gui.drawRect(0,0,10,10,0x77777777); + clip(clip.x + 10, clip.y, clip.width - 10, 10); + Gui.drawRect(0,0,getBounds().width, getBounds().height, 0x77777777); + for (int x = 0; x < width; x++) { + fr.drawString(x+"", x * 16 +10 + offsetX, 0, 0xFFFFFFFF); + } + clip(clip.x, clip.y +10, 10, clip.height-10); + Gui.drawRect(0,0,getBounds().width, getBounds().height, 0x77777777); + for (int z = 0; z < height; z++) { + fr.drawString(z+"", 2, z * 16 + 10 + offsetY, 0xFFFFFFFF); + } + + int hoverX = (relMousex0 - offsetX - 10) / 16; + int hoverY = (relMousey0 - offsetY - 10) / 16; + // draw Content + clip(clip.x + 10, clip.y +10, clip.width - 10, clip.height - 10); + boolean tooltiped=false; + for (int z = 0; z < height; z++) { + for (int x = 0; x < width; x++) { + int data1; + try { data1 = currentBlocks[z][x]; } catch (Exception e) { + data1 = -2; + } + int data2; + try { data2 = targetBlocks[z][x]; } catch (Exception e) { + data2 = -2; + } + + if (z == hoverY && x == hoverX) { + Gui.drawRect(x *16 +10+offsetX, z *16 +10 + offsetY, x *16 +26 +offsetX, z *16 +26 + offsetY, 0xAA505050); + } + + if (data1 == data2) drawItemStack(new ItemStack(Item.getItemFromBlock(Block.getBlockById(data1)), 1), x * 16 +10 + offsetX, z *16 +10 + offsetY); + else if (data2 == -1 || data1 == -1) { + drawItemStack(new ItemStack(Item.getItemFromBlock(Block.getBlockById(data1 == -1 ? data2 : data1)), 1), x * 16 +10 + offsetX, z *16 +10 + offsetY); + fr.drawString("S", x *16 +10 + offsetX, z *16 +10 + offsetY,0xFFFFFF00); + } else { + fr.drawString("N", x *16 +10 + offsetX, z *16 +10 + offsetY,0xFFFF0000); + } + if (z == hoverY && x == hoverX) { + tooltiped = true; + if (lastTooltipX != x || lastTooltipZ != z){ + if (mTooltip != null) mTooltip.close(); + mTooltip = new MTooltipText(Arrays.asList("Expected "+data2 +" But found "+data1)); + mTooltip.open(this); + } + } + } + } + if (!tooltiped && mTooltip != null) { + mTooltip.close(); + mTooltip = null; + } + + } + private void drawItemStack(ItemStack stack, int x, int y) + { + Minecraft.getMinecraft().getRenderItem().renderItemAndEffectIntoGUI(stack, x, y); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + private int lastX; + private int lastY; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + lastX = absMouseX; + lastY = absMouseY; + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + int dX = absMouseX - lastX; + int dY = absMouseY - lastY; + offsetX += dX; + offsetY += dY; + lastX = absMouseX; + lastY = absMouseY; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoommatchingPane.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoommatchingPane.java new file mode 100755 index 00000000..ac2c2696 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoommatchingPane.java @@ -0,0 +1,84 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.panes; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MTextField; + +import java.awt.*; +import java.util.UUID; + +public class RoommatchingPane extends MPanel { + private final DungeonRoom dungeonRoom; + + private RoomMatchDisplayPane displayPane; + + private final MTextField textField; + private final MButton calculate; + public RoommatchingPane(final DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + + { + textField = new MTextField(); + textField.setBounds(new Rectangle(0,0,getBounds().width - 100, 20)); + add(textField); + } + { + calculate = new MButton(); + calculate.setBounds(new Rectangle(getBounds().width - 100,0,100, 20)); + calculate.setText("match"); + calculate.setOnActionPerformed(new Runnable() { + @Override + public void run() { + try { + remove(displayPane); + + String text = textField.getText(); + String target = text.split(":")[0]; + String state = text.split(":")[1]; + + UUID uid = UUID.fromString(target); + int rotation = Integer.parseInt(state) % 4; + + + displayPane = new RoomMatchDisplayPane(dungeonRoom, uid, rotation); + displayPane.setBounds(new Rectangle(0,25,getBounds().width,getBounds().height-25)); + add(displayPane); + } catch (Throwable t) { + t.printStackTrace(); + } + } + }); + add(calculate); + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + @Override + public void onBoundsUpdate() { + textField.setBounds(new Rectangle(0,0,getBounds().width - 100, 20)); + calculate.setBounds(new Rectangle(getBounds().width - 100,0,100, 20)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/SecretEditPane.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/SecretEditPane.java new file mode 100755 index 00000000..12af8f8a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/SecretEditPane.java @@ -0,0 +1,156 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.panes; + +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonMechanic; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MParameter; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.roomedit.valueedit.ValueEditRegistry; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class SecretEditPane extends MPanel implements DynamicEditor { + private final DungeonRoom dungeonRoom; + + private MButton save; + private MButton create; + private final List<MParameter> parameters = new ArrayList<MParameter>(); + + private final List<String> allowedClasses = new ArrayList<String>(); + + public SecretEditPane(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + buildElements(); + + for (String clazz : ValueEditRegistry.getClassesSupported()) { + if (clazz.contains("mechanics") || clazz.equals("null")) { + allowedClasses.add(clazz); + } + } + } + + public void createNewMechanic(String uid, DungeonMechanic data) { + MParameter parameter; + parameters.add(parameter = new MParameter(new Parameter(uid, data, data), SecretEditPane.this)); + parameter.setBounds(new Rectangle(0,0,getBounds().width, 20)); + parameter.setParent(SecretEditPane.this); + } + + public void buildElements() { + { + create = new MButton(); + create.setText("Create New Mechanic"); + create.setBackgroundColor(Color.cyan); + create.setBounds(new Rectangle(0,0,100,20)); + create.setOnActionPerformed(new Runnable() { + @Override + public void run() { + createNewMechanic(UUID.randomUUID().toString(), null); + } + }); + + save = new MButton(); + save.setText("Save"); + save.setBackgroundColor(Color.green); + save.setBounds(new Rectangle(0,0,100,20)); + save.setOnActionPerformed(new Runnable() { + @Override + public void run() { + DungeonRoomInfo dungeonRoomInfo = dungeonRoom.getDungeonRoomInfo(); + dungeonRoomInfo.getMechanics().clear(); + + for (MParameter parameter : parameters) { + Parameter real = parameter.getParameter(); + + ValueEditCreator vec = ValueEditRegistry.getValueEditMap(real.getNewData() == null ? "null" :real.getNewData().getClass().getName()); + + real.setPreviousData(vec.cloneObj(real.getNewData())); + dungeonRoomInfo.getMechanics().put(real.getName(), (DungeonMechanic) real.getNewData()); + } + } + }); + create.setParent(this); save.setParent(this); + } + { + for (Map.Entry<String, DungeonMechanic> en : dungeonRoom.getDungeonRoomInfo().getMechanics().entrySet()) { + ValueEditCreator vec = ValueEditRegistry.getValueEditMap(en.getValue() == null ? "null" :en.getValue().getClass().getName()); + + MParameter mParameter = new MParameter(new Parameter(en.getKey(), vec.cloneObj(en.getValue()), vec.cloneObj(en.getValue())), this); + mParameter.setBounds(new Rectangle(0,0,getBounds().width,20)); + parameters.add(mParameter); + mParameter.setParent(this); + } + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + + public void delete(MParameter parameter) { + parameters.remove(parameter); + } + + @Override + public List<String> allowedClass() { + return allowedClasses; + } + + @Override + public List<MPanel> getChildComponents() { + ArrayList<MPanel> panels = new ArrayList<MPanel>(parameters); + panels.add(create); + panels.add(save); + return panels; + } + + private int offsetY = 0; + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + int heights = 0; + for (MPanel panel:getChildComponents()) { + panel.setPosition(new Point(0, -offsetY + heights)); + heights += panel.getBounds().height; + } + } + + @Override + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (scrollAmount > 0) offsetY -= 20; + else if (scrollAmount < 0) offsetY += 20; + if (offsetY < 0) offsetY = 0; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEdit.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEdit.java new file mode 100755 index 00000000..980ae947 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEdit.java @@ -0,0 +1,27 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.roomedit.Parameter; + +public interface ValueEdit<T extends Object> { + void setParameter(Parameter parameter); + + void renderWorld(float partialTicks); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditAColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditAColor.java new file mode 100755 index 00000000..ef310b3d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditAColor.java @@ -0,0 +1,339 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.MColor; +import kr.syeyoung.dungeonsguide.gui.elements.MFloatSelectionButton; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.MathHelper; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + +public class ValueEditAColor extends MPanel implements ValueEdit<AColor> { + private Parameter parameter; + private final MFloatSelectionButton h; + private final MFloatSelectionButton s; + private final MFloatSelectionButton v; + private final MFloatSelectionButton a; + + + @Override + public void renderWorld(float partialTicks) { + + } + public ValueEditAColor(final Parameter parameter2) { + this.parameter = parameter2; + { + MColor color = new MColor() { + @Override + public Color getColor() { + return (Color) parameter2.getPreviousData(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",color); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + MColor color = new MColor() { + @Override + public Color getColor() { + return (Color) parameter2.getNewData(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",color); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + + Color color = (Color) parameter2.getNewData(); + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsv); + alpha = color.getAlpha() / 255.0f; + + { + h = new MFloatSelectionButton(hsv[0] * 360); + h.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[0] = h.getData() / 360; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("H", h); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + s = new MFloatSelectionButton(hsv[1] * 100); + s.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[1] = s.getData() / 100; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("S", s); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + v = new MFloatSelectionButton(hsv[2] * 100); + v.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[2] = v.getData() / 100; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("V", v); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + a = new MFloatSelectionButton(alpha * 100); + a.setOnUpdate(new Runnable() { + @Override + public void run() { + alpha = a.getData() / 100; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("A", a); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + private final float[] hsv = new float[3]; + private float alpha = 0; + + public void update() { + if (hsv[2] > 1) hsv[2] = 1; + if (hsv[2] < 0) hsv[2] = 0; + if (hsv[1] > 1) hsv[1] = 1; + if (hsv[1] < 0) hsv[1] = 0; + parameter.setNewData(new AColor(Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0xffffff | (MathHelper.clamp_int((int)(alpha * 255), 0, 255) << 24), true )); + h.setData((float) Math.floor(hsv[0] * 360)); + s.setData((float) Math.floor(hsv[1] * 100)); + v.setData((float) Math.floor(hsv[2] * 100)); + a.setData((float) Math.floor(alpha * 100)); + h.updateSelected(); + s.updateSelected(); + v.updateSelected(); + a.updateSelected(); + } + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + // draw CoolRect + int width = getBounds().width - 60; + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + int shademodel = GL11.glGetInteger(GL11.GL_SHADE_MODEL); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + GlStateManager.enableBlend(); + GlStateManager.disableDepth(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + +// worldrenderer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR); + + int rgb = Color.HSBtoRGB(hsv[0], hsv[1], 1); + float r = (rgb >> 16 & 255) / 255.0f; + float g = (rgb >> 8 & 255) / 255.0f; + float b = (rgb & 255) / 255.0f; + GL11.glBegin(GL11.GL_TRIANGLES); + GlStateManager.color(0,0,0,alpha);GL11.glVertex3i(25+width ,45, 0); + GlStateManager.color(0,0,0,alpha);GL11.glVertex3i(10+width , 45, 0); + GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(25+width , 45+width, 0); + + GlStateManager.color(0,0,0,alpha); GL11.glVertex3i(10+width , 45, 0); + GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(10+width , 45 + width, 0); + GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(25+width , 45+width, 0); + GL11.glEnd(); + rgb = Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]); + r = (rgb >> 16 & 255) / 255.0f; + g = (rgb >> 8 & 255) / 255.0f; + b = (rgb & 255) / 255.0f; + GL11.glBegin(GL11.GL_TRIANGLES); + GlStateManager.color(r,g,b,0);GL11.glVertex3i(50+width ,45, 0); + GlStateManager.color(r,g,b,0);GL11.glVertex3i(35+width , 45, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(50+width , 45+width, 0); + +// GlStateManager.color(r,g,b,0); GL11.glVertex3i(35+width , 45, 0); +// GlStateManager.color(r,g,b,1);GL11.glVertex3i(35+width , 45 + width, 0); +// GlStateManager.color(r,g,b,1);GL11.glVertex3i(50+width , 45+width, 0); + GL11.glEnd(); + + + float radius = width/2f; + float cx = 5 + radius; + float cy = 45 + radius; + + GL11.glBegin(GL11.GL_TRIANGLE_FAN); + GlStateManager.color(1,1,1,alpha); + GL11.glVertex3f(cx,cy,0); + for (int i = 0; i <= 360; i++) { + float rad = 3.141592653f * i / 180; + int rgb2 = Color.HSBtoRGB(i / 360f, 1, hsv[2]); + float r2 = (rgb2 >> 16 & 255) / 255.0f; + float g2 = (rgb2 >> 8 & 255) / 255.0f; + float b2 = (rgb2 & 255) / 255.0f; + GlStateManager.color(r2,g2,b2, alpha); + GL11.glVertex3f(MathHelper.sin(rad) * radius + cx, MathHelper.cos(rad) * radius + cy, 0); + } + GL11.glEnd(); + GlStateManager.shadeModel(shademodel); + + GlStateManager.color(1,1,1,1); + worldrenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION); + float rad2 = 2 * 3.141592653f * hsv[0] ; + float x = 5 + radius + (MathHelper.sin(rad2)) * hsv[1] * radius; + float y = 45 + radius + (MathHelper.cos(rad2))* hsv[1] * radius; + for (int i = 0; i < 100; i++) { + float rad = 2 * 3.141592653f * (i / 100f); + worldrenderer.pos(MathHelper.sin(rad) * 2 + x, MathHelper.cos(rad) * 2 + y, 0).endVertex(); + } + tessellator.draw(); + + worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + worldrenderer.pos(8+width, 45 + (hsv[2]) * width, 0.5).endVertex(); + worldrenderer.pos(27+width, 45 + (hsv[2]) * width, 0.5).endVertex(); + tessellator.draw(); + + worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + worldrenderer.pos(33+width, 45 + (alpha) * width, 0.5).endVertex(); + worldrenderer.pos(52+width, 45 + (alpha) * width, 0.5).endVertex(); + tessellator.draw(); + + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + GlStateManager.color(1,1,1,1); + GlStateManager.color(1,1,1,1); + } + private int selected = 0; + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + int width = getBounds().width - 60; + float radius = width / 2f; + float circleX = 5 + radius; + float circleY = 45 + radius; + selected = 0; + { + // check circle + float dx = relMouseX - circleX; + float dy = circleY - relMouseY; + if (dx * dx + dy * dy <= radius * radius) { + double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180 + 90) % 360; + hsv[0] = (float) theta / 360f; + hsv[1] = MathHelper.sqrt_float(dx * dx + dy * dy) / radius; + selected = 1; + } + } + { + if (10+width <= relMouseX && relMouseX <= 25 + width && + 45 <= relMouseY && relMouseY <= 45 + width) { + hsv[2] = (relMouseY - 45) / (float)width; + selected = 2; + } + } + { + if (35+width <= relMouseX && relMouseX <= 50 + width && + 45 <= relMouseY && relMouseY <= 45 + width) { + alpha = (relMouseY - 45) / (float)width; + selected = 3; + } + } + update(); + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + int width = getBounds().width - 60; + float radius = width / 2f; + float circleX = 5 + radius; + float circleY = 45 + radius; + { + // check circle + float dx = relMouseX - circleX; + float dy = circleY - relMouseY; + if (selected == 1) { + double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180 + 90) % 360; + hsv[0] = (float) theta / 360f; + hsv[1] = MathHelper.clamp_float(MathHelper.sqrt_float(dx * dx + dy * dy) / radius, 0, 1); + } + } + { + if (selected == 2) { + hsv[2] = MathHelper.clamp_float((relMouseY - 45) / (float)width, 0, 1); + } + if (selected == 3) { + alpha = MathHelper.clamp_float((relMouseY - 45) / (float)width, 0, 1); + } + } + update(); + } + + @Override + public void onBoundsUpdate() { + int cnt = 0; + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); cnt++; + if (cnt > 2) { + panel.setPosition(new Point(0, getBounds().width + (cnt - 3) * 20)); + } + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditAColor> { + + @Override + public ValueEditAColor createValueEdit(Parameter parameter) { + return new ValueEditAColor(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new AColor(255,0,0,255); + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditBoolean.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditBoolean.java new file mode 100755 index 00000000..ab6a9ada --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditBoolean.java @@ -0,0 +1,101 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.gui.elements.MStringSelectionButton; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; + +import java.awt.*; +import java.util.Arrays; + +public class ValueEditBoolean extends MPanel implements ValueEdit<Boolean> { + private Parameter parameter; + + + public ValueEditBoolean(Parameter parameter2) { + this.parameter = parameter2; + { + MLabel label = new MLabel() { + @Override + public String getText() { + return parameter.getPreviousData().toString(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",label); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + boolean newData = (Boolean) parameter.getNewData(); + final MStringSelectionButton textField = new MStringSelectionButton(Arrays.asList("true", "false"), Boolean.toString(newData)); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + parameter.setNewData(Boolean.valueOf(textField.getSelected())); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",textField); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditBoolean> { + + @Override + public ValueEditBoolean createValueEdit(Parameter parameter) { + return new ValueEditBoolean(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return true; + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditColor.java new file mode 100755 index 00000000..8acec6f4 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditColor.java @@ -0,0 +1,290 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.gui.elements.MColor; +import kr.syeyoung.dungeonsguide.gui.elements.MFloatSelectionButton; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.MathHelper; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + +public class ValueEditColor extends MPanel implements ValueEdit<Color> { + private Parameter parameter; + private final MFloatSelectionButton h; + private final MFloatSelectionButton s; + private final MFloatSelectionButton v; + + + @Override + public void renderWorld(float partialTicks) { + + } + public ValueEditColor(final Parameter parameter2) { + this.parameter = parameter2; + { + MColor color = new MColor() { + @Override + public Color getColor() { + return (Color) parameter2.getPreviousData(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",color); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + MColor color = new MColor() { + @Override + public Color getColor() { + return (Color) parameter2.getNewData(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",color); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + + Color color = (Color) parameter2.getNewData(); + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsv); + + { + h = new MFloatSelectionButton(hsv[0] * 360); + h.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[0] = h.getData() / 360; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("H", h); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + s = new MFloatSelectionButton(hsv[1] * 100); + s.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[1] = s.getData() / 100; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("S", s); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + v = new MFloatSelectionButton(hsv[2] * 100); + v.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[2] = v.getData() / 100; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("V", v); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + private final float[] hsv = new float[3]; + + public void update() { + if (hsv[2] > 1) hsv[2] = 1; + if (hsv[2] < 0) hsv[2] = 0; + if (hsv[1] > 1) hsv[1] = 1; + if (hsv[1] < 0) hsv[1] = 0; + parameter.setNewData(new Color(Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]))); + h.setData((float) Math.floor(hsv[0] * 360)); + s.setData((float) Math.floor(hsv[1] * 100)); + v.setData((float) Math.floor(hsv[2] * 100)); + h.updateSelected(); + s.updateSelected(); + v.updateSelected(); + } + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + // draw CoolRect + int width = getBounds().width - 30; + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + int shademodel = GL11.glGetInteger(GL11.GL_SHADE_MODEL); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); +// worldrenderer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR); + + int rgb = Color.HSBtoRGB(hsv[0], hsv[1], 1); + float r = (rgb >> 16 & 255) / 255.0f; + float g = (rgb >> 8 & 255) / 255.0f; + float b = (rgb & 255) / 255.0f; + GL11.glBegin(GL11.GL_TRIANGLES); + GlStateManager.color(0,0,0,1);GL11.glVertex3i(25+width ,45, 0); + GlStateManager.color(0,0,0,1);GL11.glVertex3i(10+width , 45, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(25+width , 45+width, 0); + + GlStateManager.color(0,0,0,1); GL11.glVertex3i(10+width , 45, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(10+width , 45 + width, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(25+width , 45+width, 0); + GL11.glEnd(); + + float radius = width/2f; + float cx = 5 + radius; + float cy = 45 + radius; + + GL11.glBegin(GL11.GL_TRIANGLE_FAN); + GlStateManager.color(1,1,1,1); + GL11.glVertex3f(cx,cy,0); + for (int i = 0; i <= 360; i++) { + float rad = 3.141592653f * i / 180; + int rgb2 = Color.HSBtoRGB(i / 360f, 1, hsv[2]); + float r2 = (rgb2 >> 16 & 255) / 255.0f; + float g2 = (rgb2 >> 8 & 255) / 255.0f; + float b2 = (rgb2 & 255) / 255.0f; + GlStateManager.color(r2,g2,b2, 1); + GL11.glVertex3f(MathHelper.sin(rad) * radius + cx, MathHelper.cos(rad) * radius + cy, 0); + } + GL11.glEnd(); + GlStateManager.shadeModel(shademodel); + + GlStateManager.color(1,1,1,1); + worldrenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION); + float rad2 = 2 * 3.141592653f * hsv[0] ; + float x = 5 + radius + (MathHelper.sin(rad2)) * hsv[1] * radius; + float y = 45 + radius + (MathHelper.cos(rad2))* hsv[1] * radius; + for (int i = 0; i < 100; i++) { + float rad = 2 * 3.141592653f * (i / 100f); + worldrenderer.pos(MathHelper.sin(rad) * 2 + x, MathHelper.cos(rad) * 2 + y, 0).endVertex(); + } + tessellator.draw(); + + worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + worldrenderer.pos(8+width, 45 + (hsv[2]) * width, 0.5).endVertex(); + worldrenderer.pos(27+width, 45 + (hsv[2]) * width, 0.5).endVertex(); + tessellator.draw(); + + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + GlStateManager.color(1,1,1,1); + GlStateManager.color(1,1,1,1); + } + private int selected = 0; + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + int width = getBounds().width - 30; + float radius = width / 2f; + float circleX = 5 + radius; + float circleY = 45 + radius; + selected = 0; + { + // check circle + float dx = relMouseX - circleX; + float dy = circleY - relMouseY; + if (dx * dx + dy * dy <= radius * radius) { + double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180 + 90) % 360; + hsv[0] = (float) theta / 360f; + hsv[1] = MathHelper.sqrt_float(dx * dx + dy * dy) / radius; + selected = 1; + } + } + { + if (10+width <= relMouseX && relMouseX <= 25 + width && + 45 <= relMouseY && relMouseY <= 45 + width) { + hsv[2] = (relMouseY - 45) / (float)width; + selected = 2; + } + } + update(); + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + int width = getBounds().width - 30; + float radius = width / 2f; + float circleX = 5 + radius; + float circleY = 45 + radius; + { + // check circle + float dx = relMouseX - circleX; + float dy = circleY - relMouseY; + if (selected == 1) { + double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180 + 90) % 360; + hsv[0] = (float) theta / 360f; + hsv[1] = MathHelper.clamp_float(MathHelper.sqrt_float(dx * dx + dy * dy) / radius, 0, 1); + } + } + { + if (selected == 2) { + hsv[2] = MathHelper.clamp_float((relMouseY - 45) / (float)width, 0, 1); + } + } + update(); + } + + @Override + public void onBoundsUpdate() { + int cnt = 0; + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); cnt++; + if (cnt > 2) { + panel.setPosition(new Point(0, getBounds().width + (cnt - 2) * 20)); + } + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditColor> { + + @Override + public ValueEditColor createValueEdit(Parameter parameter) { + return new ValueEditColor(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return Color.red; + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditCreator.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditCreator.java new file mode 100755 index 00000000..41579f0c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditCreator.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.roomedit.Parameter; + +public interface ValueEditCreator<T extends ValueEdit> { + T createValueEdit(Parameter parameter); + + Object createDefaultValue(Parameter parameter); + + Object cloneObj(Object object); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditFloat.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditFloat.java new file mode 100755 index 00000000..66fa4c54 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditFloat.java @@ -0,0 +1,99 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.MFloatSelectionButton; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; + +import java.awt.*; + +public class ValueEditFloat extends MPanel implements ValueEdit<Float> { + private Parameter parameter; + + + @Override + public void renderWorld(float partialTicks) { + + } + public ValueEditFloat(final Parameter parameter2) { + this.parameter = parameter2; + { + MLabel label = new MLabel() { + @Override + public String getText() { + return parameter.getPreviousData().toString(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",label); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + float newData = (Float) parameter.getNewData(); + final MFloatSelectionButton textField = new MFloatSelectionButton(newData); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + parameter.setNewData(textField.getData()); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",textField); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditFloat> { + + @Override + public ValueEditFloat createValueEdit(Parameter parameter) { + return new ValueEditFloat(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return 0.0f; + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditInteger.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditInteger.java new file mode 100755 index 00000000..37430077 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditInteger.java @@ -0,0 +1,99 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.MIntegerSelectionButton; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; + +import java.awt.*; + +public class ValueEditInteger extends MPanel implements ValueEdit<Integer> { + private Parameter parameter; + + + @Override + public void renderWorld(float partialTicks) { + + } + public ValueEditInteger(final Parameter parameter2) { + this.parameter = parameter2; + { + MLabel label = new MLabel() { + @Override + public String getText() { + return parameter.getPreviousData().toString(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",label); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + int newData = (Integer) parameter.getNewData(); + final MIntegerSelectionButton textField = new MIntegerSelectionButton(newData); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + parameter.setNewData(textField.getData()); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",textField); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditInteger> { + + @Override + public ValueEditInteger createValueEdit(Parameter parameter) { + return new ValueEditInteger(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return 0; + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditNull.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditNull.java new file mode 100755 index 00000000..475a942a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditNull.java @@ -0,0 +1,38 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.roomedit.Parameter; + +public class ValueEditNull implements ValueEditCreator { + @Override + public ValueEdit createValueEdit(Parameter parameter) { + return null; + } + + @Override + public Cloneable createDefaultValue(Parameter parameter) { + return null; + } + + @Override + public Object cloneObj(Object object) { + return null; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditOffsetPoint.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditOffsetPoint.java new file mode 100755 index 00000000..978ead50 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditOffsetPoint.java @@ -0,0 +1,167 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MIntegerSelectionButton; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.*; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.BlockPos; +import java.awt.*; + +public class ValueEditOffsetPoint extends MPanel implements ValueEdit<String> { + private Parameter parameter; + + @Override + public void renderWorld(float partialTicks) { + RenderUtils.highlightBlock(((OffsetPoint)parameter.getPreviousData()).getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(255,0,0,150), partialTicks); + RenderUtils.highlightBlock(((OffsetPoint)parameter.getNewData()).getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(0,255,0,150), partialTicks); + } + + public ValueEditOffsetPoint(final Parameter parameter2) { + this.parameter = parameter2; + { + MLabel label = new MLabel() { + @Override + public String getText() { + return parameter.getPreviousData().toString(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",label); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + OffsetPoint newData = (OffsetPoint) parameter.getNewData(); + { + final MIntegerSelectionButton textField = new MIntegerSelectionButton(newData.getX()); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + ((OffsetPoint) parameter.getNewData()).setX(textField.getData()); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("x",textField); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + final MIntegerSelectionButton textField = new MIntegerSelectionButton(newData.getY()); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + ((OffsetPoint) parameter.getNewData()).setY(textField.getData()); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("y",textField); + mLabelAndElement.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(mLabelAndElement); + } + { + final MIntegerSelectionButton textField = new MIntegerSelectionButton(newData.getZ()); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + ((OffsetPoint) parameter.getNewData()).setZ(textField.getData()); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("z",textField); + mLabelAndElement.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(mLabelAndElement); + } + { + final MLabel setToHEre = new MLabel() { + @Override + public String getText() { + OffsetPoint offsetPoint = (OffsetPoint) parameter.getNewData(); + return Block.getIdFromBlock(offsetPoint.getBlock(EditingContext.getEditingContext().getRoom())) + + ":" + offsetPoint.getData(EditingContext.getEditingContext().getRoom()); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("newPt",setToHEre); + mLabelAndElement.setBounds(new Rectangle(0,80,getBounds().width,20)); + add(mLabelAndElement); + } + { + final MButton setToHEre2 = new MButton(); + setToHEre2.setText("Set to here"); + setToHEre2.setBackgroundColor(Color.green); + setToHEre2.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EntityPlayer player = Minecraft.getMinecraft().thePlayer; + BlockPos pos = new BlockPos(player.posX, player.posY, player.posZ); + ((OffsetPoint)parameter2.getNewData()).setPosInWorld(EditingContext.getEditingContext().getRoom(),pos ); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("set",setToHEre2); + mLabelAndElement.setBounds(new Rectangle(0,100,getBounds().width,20)); + add(mLabelAndElement); + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditOffsetPoint> { + + @Override + public ValueEditOffsetPoint createValueEdit(Parameter parameter) { + return new ValueEditOffsetPoint(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new OffsetPoint(EditingContext.getEditingContext().getRoom(), Minecraft.getMinecraft().thePlayer.getPosition()); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((OffsetPoint)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditOffsetPointSet.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditOffsetPointSet.java new file mode 100755 index 00000000..cdc32448 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditOffsetPointSet.java @@ -0,0 +1,250 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonAddSet; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.Getter; +import net.minecraft.client.Minecraft; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ValueEditOffsetPointSet extends MPanel implements ValueEdit<OffsetPointSet> { + private Parameter parameter; + + // scroll pane + // just create + // add set + + private final MPanel scroll; + @Getter + private final List<MPanel> MParameters = new ArrayList<MPanel>(); + + private final MButton add; + private final MButton addSet; + + public void delete(OffsetPoint offsetPoint) { + ((OffsetPointSet)parameter.getNewData()).getOffsetPointList().remove(offsetPoint); + Iterator<MPanel> iterator = MParameters.iterator(); + while (iterator.hasNext()) { + MValue panel = (MValue) iterator.next(); + if (panel.getData() == offsetPoint) { + iterator.remove(); + break; + } + } + + } + + public ValueEditOffsetPointSet(final Parameter parameter2) { + this.parameter = parameter2; + { + scroll = new MPanel() { + private int offsetY = 0; + + @Override + public List<MPanel> getChildComponents() { + return MParameters; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + int heights = 0; + for (MPanel panel:getChildComponents()) { + panel.setPosition(new Point(0, -offsetY + heights)); + heights += panel.getBounds().height; + } + } + + @Override + public boolean mouseClicked0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int mouseButton) { + if (!getBounds().contains(relMouseX0, relMouseY0)) { + return false; + } + + int relMousex = relMouseX0 - getBounds().x; + int relMousey = relMouseY0 - getBounds().y; + + boolean noClip = true; + boolean focusedOverall = false; + for (MPanel childComponent : getChildComponents()) { + if (childComponent.mouseClicked0(absMouseX, absMouseY, relMousex, relMousey, mouseButton)) { + noClip = false; + focusedOverall = true; + } + } + + if (getBounds().contains(relMouseX0, relMouseY0) && noClip) { + isFocused = true; + focusedOverall = true; + } else { + isFocused = false; + } + + mouseClicked(absMouseX, absMouseY, relMousex, relMousey, mouseButton); + return focusedOverall; + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + @Override + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (new Rectangle(new Point(0,0), getSize()).contains(relMouseX0, relMouseY0)) { + if (scrollAmount >0) offsetY += 20; + else if (scrollAmount < 0) offsetY -= 20; + if (offsetY <0) offsetY = 0; + } + } + }; + scroll.setBounds(new Rectangle(0,0,getBounds().width, getBounds().height-20)); + add(scroll); + } + + { + add = new MButton() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0,parentHeight - 20, parentWidth / 2, 20)); + } + }; + add.setText("Add"); + add.setBackgroundColor(Color.green); + add.setOnActionPerformed(new Runnable() { + @Override + public void run() { + OffsetPoint offsetPoint = new OffsetPoint(EditingContext.getEditingContext().getRoom(), Minecraft.getMinecraft().thePlayer.getPosition()); + MValue mValue; + MParameters.add(mValue = new MValue(offsetPoint, buildAddonsFor(offsetPoint))); + ((OffsetPointSet)parameter.getNewData()).getOffsetPointList().add(offsetPoint); + mValue.setSize(new Dimension(getBounds().width, 20)); + } + }); + + addSet = new MButton(){ + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(parentWidth / 2,parentHeight - 20, parentWidth / 2, 20)); + } + }; + addSet.setText("Add Set"); + addSet.setBackgroundColor(Color.cyan); + addSet.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EditingContext.getEditingContext().openGui(new GuiDungeonAddSet(ValueEditOffsetPointSet.this)); + } + }); + add(add); + add(addSet); + } + for (OffsetPoint offsetPoint : ((OffsetPointSet)parameter.getNewData()).getOffsetPointList()) { + MParameters.add(new MValue(offsetPoint, buildAddonsFor(offsetPoint))); + } + } + + public List<MPanel> buildAddonsFor(final OffsetPoint offsetPoint) { + ArrayList<MPanel> panels = new ArrayList<MPanel>(); + MButton mButton = new MButton(); + mButton.setText("Delete"); + mButton.setForeground(Color.white); + mButton.setBackgroundColor(Color.red); + mButton.setOnActionPerformed(new Runnable() { + @Override + public void run() { + delete(offsetPoint); + } + }); + panels.add(mButton); + return panels; + } + + @Override + public void onBoundsUpdate() { + scroll.setBounds(new Rectangle(0,0,getBounds().width, getBounds().height-20)); + add.setBounds(new Rectangle(0,getBounds().height-20,getBounds().width / 2, 20)); + addSet.setBounds(new Rectangle(getBounds().width / 2,getBounds().height-20,getBounds().width / 2, 20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + for (OffsetPoint offsetPoint :((OffsetPointSet)parameter.getNewData()).getOffsetPointList()) { + RenderUtils.highlightBlock(offsetPoint.getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(0,255,255,50), partialTicks); + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public void addAll(List<OffsetPoint> blockPoses) { + ((OffsetPointSet)parameter.getNewData()).getOffsetPointList().addAll(blockPoses); + for (OffsetPoint blockPose : blockPoses) { + MParameters.add(new MValue(blockPose, buildAddonsFor(blockPose))); + } + } + + public static class Generator implements ValueEditCreator<ValueEditOffsetPointSet> { + + @Override + public ValueEditOffsetPointSet createValueEdit(Parameter parameter) { + return new ValueEditOffsetPointSet(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new OffsetPointSet(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((OffsetPointSet)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditRegistry.java new file mode 100755 index 00000000..611dc533 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditRegistry.java @@ -0,0 +1,71 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.*; +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.roomedit.mechanicedit.*; +import kr.syeyoung.dungeonsguide.roomedit.mechanicedit.*; + +import java.awt.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ValueEditRegistry { + private static final Map<String, ValueEditCreator> valueEditMap = new HashMap<String, ValueEditCreator>(); + + public static ValueEditCreator getValueEditMap(String className) { + return valueEditMap.get(className); + } + + public static List<String> getClassesSupported() { + return new ArrayList<String>(valueEditMap.keySet()); + } + + static { + valueEditMap.put("null", new ValueEditNull()); + valueEditMap.put(String.class.getName(), new ValueEditString.Generator()); + valueEditMap.put(Boolean.class.getName(), new ValueEditBoolean.Generator()); + valueEditMap.put(Integer.class.getName(), new ValueEditInteger.Generator()); + valueEditMap.put(Float.class.getName(), new ValueEditFloat.Generator()); + valueEditMap.put(OffsetPoint.class.getName(), new ValueEditOffsetPoint.Generator()); + valueEditMap.put(OffsetPointSet.class.getName(), new ValueEditOffsetPointSet.Generator()); + valueEditMap.put(Color.class.getName(), new ValueEditColor.Generator()); + valueEditMap.put(AColor.class.getName(), new ValueEditAColor.Generator()); + + + valueEditMap.put(DungeonSecret.class.getName(), new ValueEditSecret.Generator()); + valueEditMap.put(DungeonFairySoul.class.getName(), new ValueEditFairySoul.Generator()); + valueEditMap.put(DungeonNPC.class.getName(), new ValueEditNPC.Generator()); + valueEditMap.put(DungeonTomb.class.getName(), new ValueEditTomb.Generator()); + valueEditMap.put(DungeonBreakableWall.class.getName(), new ValueEditBreakableWall.Generator()); + valueEditMap.put(DungeonJournal.class.getName(), new ValueEditJournal.Generator()); + valueEditMap.put(DungeonDummy.class.getName(), new ValueEditDummy.Generator()); + + valueEditMap.put(DungeonPressurePlate.class.getName(), new ValueEditPressurePlate.Generator()); + valueEditMap.put(DungeonOnewayLever.class.getName(), new ValueEditOnewayLever.Generator()); + valueEditMap.put(DungeonLever.class.getName(), new ValueEditLever.Generator()); + valueEditMap.put(DungeonDoor.class.getName(), new ValueEditDoor.Generator()); + valueEditMap.put(DungeonOnewayDoor.class.getName(), new ValueEditOnewayDoor.Generator()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditString.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditString.java new file mode 100755 index 00000000..2eeca0fb --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomedit/valueedit/ValueEditString.java @@ -0,0 +1,99 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.gui.elements.MTextField; + +import java.awt.*; + +public class ValueEditString extends MPanel implements ValueEdit<String> { + private Parameter parameter; + + @Override + public void renderWorld(float partialTicks) { + + } + + public ValueEditString(Parameter parameter2) { + this.parameter = parameter2; + { + MLabel label = new MLabel() { + @Override + public String getText() { + return parameter.getPreviousData().toString(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",label); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + String newData = (String) parameter.getNewData(); + MTextField textField = new MTextField() { + @Override + public void edit(String str) { + parameter.setNewData(str); + } + }; + textField.setText(newData); + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",textField); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditString> { + + @Override + public ValueEditString createValueEdit(Parameter parameter) { + return new ValueEditString(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return "default"; + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/GeneralRoomProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/GeneralRoomProcessor.java new file mode 100755 index 00000000..6a9dd3d2 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/GeneralRoomProcessor.java @@ -0,0 +1,446 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionComplete; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMove; +import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMoveNearestAir; +import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonMechanic; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonRoomDoor; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonSecret; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.dungeon.DungeonActionManager; +import kr.syeyoung.dungeonsguide.events.BlockUpdateEvent; +import kr.syeyoung.dungeonsguide.events.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.pathfinding.NodeProcessorDungeonRoom; +import kr.syeyoung.dungeonsguide.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonAddSet; +import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonRoomEdit; +import kr.syeyoung.dungeonsguide.utils.VectorUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.entity.passive.EntityBat; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.util.*; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.*; + +public class GeneralRoomProcessor implements RoomProcessor { + + @Getter + @Setter + private DungeonRoom dungeonRoom; + public GeneralRoomProcessor(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + } + private boolean ticked = false; + + + @Override + public void tick() { + if (!ticked && FeatureRegistry.SECRET_AUTO_START.isEnabled()) + searchForNextTarget(); + if (!ticked && FeatureRegistry.SECRET_PATHFIND_ALL.isEnabled()) { + for (Map.Entry<String, DungeonMechanic> value : getDungeonRoom().getDungeonRoomInfo().getMechanics().entrySet()) { + if (value.getValue() instanceof DungeonSecret && ((DungeonSecret) value.getValue()).getSecretStatus(dungeonRoom) != DungeonSecret.SecretStatus.FOUND) { + DungeonSecret dungeonSecret = (DungeonSecret) value.getValue(); + if (FeatureRegistry.SECRET_PATHFIND_ALL.isBat() && dungeonSecret.getSecretType() == DungeonSecret.SecretType.BAT) + pathfind(value.getKey(), "found", FeatureRegistry.SECRET_LINE_PROPERTIES_PATHFINDALL_BAT.getRouteProperties()); + if (FeatureRegistry.SECRET_PATHFIND_ALL.isChest() && dungeonSecret.getSecretType() == DungeonSecret.SecretType.CHEST) + pathfind(value.getKey(), "found", FeatureRegistry.SECRET_LINE_PROPERTIES_PATHFINDALL_CHEST.getRouteProperties()); + if (FeatureRegistry.SECRET_PATHFIND_ALL.isEssence() && dungeonSecret.getSecretType() == DungeonSecret.SecretType.ESSENCE) + pathfind(value.getKey(), "found", FeatureRegistry.SECRET_LINE_PROPERTIES_PATHFINDALL_ESSENCE.getRouteProperties()); + if (FeatureRegistry.SECRET_PATHFIND_ALL.isItemdrop() && dungeonSecret.getSecretType() == DungeonSecret.SecretType.ITEM_DROP) + pathfind(value.getKey(), "found", FeatureRegistry.SECRET_LINE_PROPERTIES_PATHFINDALL_ITEM_DROP.getRouteProperties()); + } + } + } + if (!ticked && FeatureRegistry.SECRET_BLOOD_RUSH.isEnabled()) { + for (Map.Entry<String, DungeonMechanic> value : getDungeonRoom().getMechanics().entrySet()) { + if (value.getValue() instanceof DungeonRoomDoor) { + DungeonRoomDoor dungeonDoor = (DungeonRoomDoor) value.getValue(); + if (dungeonDoor.getDoorfinder().getType().isHeadToBlood()) { + pathfind(value.getKey(), "navigate", FeatureRegistry.SECRET_BLOOD_RUSH_LINE_PROPERTIES.getRouteProperties()); + } + } + } + } + ticked = true; + + Set<String> toRemove = new HashSet<>(); + path.entrySet().forEach(a -> { + a.getValue().onTick(); + if (a.getValue().getCurrentAction() instanceof ActionComplete) + toRemove.add(a.getKey()); + }); + toRemove.forEach(path::remove); + + + for (DungeonMechanic value : dungeonRoom.getMechanics().values()) { + if (value instanceof DungeonSecret) ((DungeonSecret) value).tick(dungeonRoom); + } + + if (toRemove.contains("AUTO-BROWSE") && FeatureRegistry.SECRET_AUTO_BROWSE_NEXT.isEnabled()) { + searchForNextTarget(); + } + } + private final Set<String> visited = new HashSet<String>(); + + public void searchForNextTarget() { + if (getDungeonRoom().getCurrentState() == DungeonRoom.RoomState.FINISHED) { + cancelAll(); + return; + } + + BlockPos pos = Minecraft.getMinecraft().thePlayer.getPosition(); + + double lowestCost = 99999999999999.0; + Map.Entry<String, DungeonMechanic> lowestWeightMechanic = null; + for (Map.Entry<String, DungeonMechanic> mech: dungeonRoom.getMechanics().entrySet()) { + if (!(mech.getValue() instanceof DungeonSecret)) continue; + if (visited.contains(mech.getKey())) continue; + if (((DungeonSecret) mech.getValue()).getSecretStatus(getDungeonRoom()) != DungeonSecret.SecretStatus.FOUND) { + double cost = 0; + if (((DungeonSecret) mech.getValue()).getSecretType() == DungeonSecret.SecretType.BAT && + ((DungeonSecret) mech.getValue()).getPreRequisite().size() == 0) { + cost += -100000000; + } + if (mech.getValue().getRepresentingPoint(getDungeonRoom()) == null) continue; + BlockPos blockpos = mech.getValue().getRepresentingPoint(getDungeonRoom()).getBlockPos(getDungeonRoom()); + + cost += blockpos.distanceSq(pos); + cost += ((DungeonSecret) mech.getValue()).getPreRequisite().size() * 100; + + if (cost < lowestCost) { + lowestCost = cost; + lowestWeightMechanic = mech; + } + } + } + if (lowestWeightMechanic != null) { + visited.add(lowestWeightMechanic.getKey()); + pathfind("AUTO-BROWSE", lowestWeightMechanic.getKey(), "found", FeatureRegistry.SECRET_LINE_PROPERTIES_AUTOPATHFIND.getRouteProperties()); + } else { + visited.clear(); + } + } + + @Override + public void drawScreen(float partialTicks) { + path.values().forEach(a -> { + a.onRenderScreen(partialTicks); + }); + + if (FeatureRegistry.ADVANCED_ROOMEDIT.isEnabled() && FeatureRegistry.DEBUG.isEnabled()) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + if (Minecraft.getMinecraft().objectMouseOver == null) return; + Entity en = Minecraft.getMinecraft().objectMouseOver.entityHit; + if (en == null) return; + + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + if (DungeonActionManager.getSpawnLocation().containsKey(en.getEntityId())) { + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Spawned at " + DungeonActionManager.getSpawnLocation().get(en.getEntityId()), sr.getScaledWidth() / 2, sr.getScaledHeight() / 2, 0xFFFFFFFF); + } + } + } + + @Override + public void drawWorld(float partialTicks) { + if (FeatureRegistry.DEBUG.isEnabled() && (EditingContext.getEditingContext() != null && EditingContext.getEditingContext().getCurrent() instanceof GuiDungeonRoomEdit)) { + for (Map.Entry<String, DungeonMechanic> value : dungeonRoom.getMechanics().entrySet()) { + if (value.getValue() == null) continue; + value.getValue().highlight(new Color(0,255,255,50), value.getKey(), dungeonRoom, partialTicks); + } + } + + + ActionRoute finalSmallest = getBestFit(partialTicks); + path.values().forEach(a -> { + a.onRenderWorld(partialTicks, finalSmallest == a); + }); + } + + private ActionRoute getBestFit(float partialTicks) { + + ActionRoute smallest = null; + double smallestTan = 0.002; + for (ActionRoute value : path.values()) { + BlockPos target; + if (value.getCurrentAction() instanceof ActionMove) { + target = ((ActionMove) value.getCurrentAction()).getTarget().getBlockPos(dungeonRoom); + } else if (value.getCurrentAction() instanceof ActionMoveNearestAir) { + target = ((ActionMoveNearestAir) value.getCurrentAction()).getTarget().getBlockPos(dungeonRoom); + } else if (value.getCurrent() >= 1 && value.getActions().get(value.getCurrent()-1) instanceof ActionMove) { + target = ((ActionMove)value.getActions().get(value.getCurrent()-1)).getTarget().getBlockPos(dungeonRoom); + } else if (value.getCurrent() >= 1 && value.getActions().get(value.getCurrent()-1) instanceof ActionMoveNearestAir) { + target = ((ActionMoveNearestAir)value.getActions().get(value.getCurrent()-1)).getTarget().getBlockPos(dungeonRoom); + } else continue; + + if (value.getActionRouteProperties().getLineRefreshRate() != -1 && value.getActionRouteProperties().isPathfind() && !FeatureRegistry.SECRET_FREEZE_LINES.isEnabled()) continue; + + Entity e = Minecraft.getMinecraft().getRenderViewEntity(); + + double vectorV = VectorUtils.distSquared(e.getLook(partialTicks), e.getPositionEyes(partialTicks), new Vec3(target).addVector(0.5,0.5,0.5)); + + if (vectorV < smallestTan) { + smallest = value; + smallestTan = vectorV; + } + } + return smallest; + } + + @Override + public void chatReceived(IChatComponent chat) { + if (lastChest != null && chat.getFormattedText().equals("§r§cThis chest has already been searched!§r")) { + getDungeonRoom().getRoomContext().put("c-"+lastChest.toString(), 2); + lastChest = null; + } + } + + private int stack = 0; + private long secrets2 = 0; + @Override + public void actionbarReceived(IChatComponent chat) { + if (!DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnDungeon()) return; + if (dungeonRoom.getTotalSecrets() == -1) { + DungeonsGuide.sendDebugChat(new ChatComponentText(chat.getFormattedText().replace('§', '&') + " - received")); + } + if (!chat.getFormattedText().contains("/")) return; + BlockPos pos = Minecraft.getMinecraft().thePlayer.getPosition(); + DungeonContext context = DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext(); + Point pt1 = context.getMapProcessor().worldPointToRoomPoint(pos.add(2, 0, 2)); + Point pt2 = context.getMapProcessor().worldPointToRoomPoint(pos.add(-2, 0, -2)); + if (!pt1.equals(pt2)) { + stack = 0; + secrets2 = -1; + return; + } + BlockPos pos2 = dungeonRoom.getMin().add(5, 0, 5); + + String text = chat.getFormattedText(); + int secretsIndex = text.indexOf("Secrets"); + int secrets = 0; + if (secretsIndex != -1) { + int theindex = 0; + for (int i = secretsIndex; i >= 0; i--) { + if (text.startsWith("§7", i)) { + theindex = i; + } + } + String it = text.substring(theindex + 2, secretsIndex - 1); + + secrets = Integer.parseInt(it.split("/")[1]); + } + + if (secrets2 == secrets) stack++; + else { + stack = 0; + secrets2 = secrets; + } + + if (stack == 4 && dungeonRoom.getTotalSecrets() != secrets) { + dungeonRoom.setTotalSecrets(secrets); + if (FeatureRegistry.DUNGEON_INTERMODCOMM.isEnabled()) + Minecraft.getMinecraft().thePlayer.sendChatMessage("/pchat $DG-Comm " + pos2.getX() + "/" + pos2.getZ() + " " + secrets); + } + } + + @Override + public boolean readGlobalChat() { + return false; + } + + @Getter + private Map<String, ActionRoute> path = new HashMap<>(); + + public ActionRoute getPath(String id){ + return path.get(id); + } + + public String pathfind(String mechanic, String state, ActionRoute.ActionRouteProperties actionRouteProperties) { + String str; + pathfind(str = UUID.randomUUID().toString(), mechanic, state, actionRouteProperties); + return str; + } + public void pathfind(String id, String mechanic, String state, ActionRoute.ActionRouteProperties actionRouteProperties) { + path.put(id, new ActionRoute(getDungeonRoom(), mechanic, state, actionRouteProperties)); + } + public void cancelAll() { + path.clear(); + } + public void cancel(String id) { + path.remove(id); + } + + @Override + public void onPostGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) { + + } + + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving instanceof EntityArmorStand && + updateEvent.entityLiving.getName() != null && + updateEvent.entityLiving.getName().contains("Mimic") && + !dungeonRoom.getContext().isGotMimic()) { + dungeonRoom.getContext().setGotMimic(true); +// Minecraft.getMinecraft().thePlayer.sendChatMessage("/pc $DG-Mimic"); + } + } + + @Override + public void onKeybindPress(KeyBindPressedEvent keyInputEvent) { + if (FeatureRegistry.SECRET_NEXT_KEY.isEnabled() && FeatureRegistry.SECRET_NEXT_KEY.<Integer>getParameter("key").getValue() == keyInputEvent.getKey()) { + searchForNextTarget(); + } else if (FeatureRegistry.SECRET_CREATE_REFRESH_LINE.getKeybind() == keyInputEvent.getKey() && FeatureRegistry.SECRET_CREATE_REFRESH_LINE.isEnabled()) { + ActionRoute actionRoute = getBestFit(0); + // actually do force refresh because of force freeze pathfind + if (actionRoute.getCurrentAction() instanceof ActionMove) { + ActionMove ac = (ActionMove) actionRoute.getCurrentAction(); + ac.forceRefresh(getDungeonRoom()); + } else if (actionRoute.getCurrentAction() instanceof ActionMoveNearestAir) { + ActionMoveNearestAir ac = (ActionMoveNearestAir) actionRoute.getCurrentAction(); + ac.forceRefresh(getDungeonRoom()); + } else if (actionRoute.getCurrent() >= 1 && actionRoute.getActions().get(actionRoute.getCurrent()-1) instanceof ActionMove) { + ((ActionMove)actionRoute.getActions().get(actionRoute.getCurrent()-1)).forceRefresh(dungeonRoom); + } else if (actionRoute.getCurrent() >= 1 && actionRoute.getActions().get(actionRoute.getCurrent()-1) instanceof ActionMoveNearestAir) { + ((ActionMoveNearestAir)actionRoute.getActions().get(actionRoute.getCurrent()-1)).forceRefresh(dungeonRoom); + } + + if (FeatureRegistry.SECRET_CREATE_REFRESH_LINE.isPathfind() && !actionRoute.getActionRouteProperties().isPathfind()) { + actionRoute.getActionRouteProperties().setPathfind(true); + actionRoute.getActionRouteProperties().setLineRefreshRate(FeatureRegistry.SECRET_CREATE_REFRESH_LINE.getRefreshRate()); + } + } + } + + @Override + public void onInteract(PlayerInteractEntityEvent event) { + path.values().forEach(a -> { + a.onLivingInteract(event); + }); + } + + private boolean last = false; + private BlockPos lastChest; + @Override + public void onInteractBlock(PlayerInteractEvent event) { + path.values().forEach(a -> { + a.onPlayerInteract(event); + }); + + if (event.pos != null) { + IBlockState iBlockState = event.world.getBlockState(event.pos); + if (iBlockState.getBlock() == Blocks.chest || iBlockState.getBlock() == Blocks.trapped_chest) + lastChest = event.pos; + } + + if (event.entityPlayer.getHeldItem() != null && + event.entityPlayer.getHeldItem().getItem() == Items.stick && + FeatureRegistry.ADVANCED_ROOMEDIT.isEnabled() && + FeatureRegistry.DEBUG.isEnabled()) { + EditingContext ec = EditingContext.getEditingContext(); + if (ec == null) return; + if (!(ec.getCurrent() instanceof GuiDungeonAddSet)) return; + GuiDungeonAddSet gdas = (GuiDungeonAddSet) ec.getCurrent(); + if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) { + if (last) + gdas.getEnd().setPosInWorld(getDungeonRoom(), event.pos); + else + gdas.getStart().setPosInWorld(getDungeonRoom(), event.pos); + + last = !last; + } + } + } + + @Override + public void onEntityDeath(LivingDeathEvent deathEvent) { + path.values().forEach(a -> { + a.onLivingDeath(deathEvent); + }); + if (EditingContext.getEditingContext() != null && EditingContext.getEditingContext().getRoom() == getDungeonRoom()) { + if (deathEvent.entity instanceof EntityBat) { + for (GuiScreen screen : EditingContext.getEditingContext().getGuiStack()) { + if (screen instanceof GuiDungeonRoomEdit) { + DungeonSecret secret = new DungeonSecret(); + secret.setSecretType(DungeonSecret.SecretType.BAT); + secret.setSecretPoint(new OffsetPoint(dungeonRoom, + DungeonActionManager.getSpawnLocation().get(deathEvent.entity.getEntityId()) + )); + ((GuiDungeonRoomEdit) screen).getSep().createNewMechanic("BAT-"+ UUID.randomUUID(), + secret); + return; + } + } + if (EditingContext.getEditingContext().getCurrent() instanceof GuiDungeonRoomEdit) { + DungeonSecret secret = new DungeonSecret(); + secret.setSecretType(DungeonSecret.SecretType.BAT); + secret.setSecretPoint(new OffsetPoint(dungeonRoom, + DungeonActionManager.getSpawnLocation().get(deathEvent.entity.getEntityId()) + )); + ((GuiDungeonRoomEdit) EditingContext.getEditingContext().getCurrent()).getSep().createNewMechanic("BAT-"+ UUID.randomUUID(), + secret); + } + } + } + } + @Override + public void onBlockUpdate(BlockUpdateEvent blockUpdateEvent) { + for (Tuple<BlockPos, IBlockState> updatedBlock : blockUpdateEvent.getUpdatedBlocks()) { + if (updatedBlock.getSecond().equals(NodeProcessorDungeonRoom.preBuilt)) continue; + dungeonRoom.resetBlock(updatedBlock.getFirst()); + } + } + + public static class Generator implements RoomProcessorGenerator<GeneralRoomProcessor> { + @Override + public GeneralRoomProcessor createNew(DungeonRoom dungeonRoom) { + GeneralRoomProcessor defaultRoomProcessor = new GeneralRoomProcessor(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/ProcessorFactory.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/ProcessorFactory.java new file mode 100755 index 00000000..6c09b1c2 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/ProcessorFactory.java @@ -0,0 +1,65 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.boxpuzzle.RoomProcessorBoxSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.icefill.RoomProcessorIcePath2; +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.RoomProcessorWaterPuzzle; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class ProcessorFactory { + private static final Map<String, RoomProcessorGenerator> map = new HashMap<String, RoomProcessorGenerator>(); + + public static RoomProcessorGenerator getRoomProcessorGenerator(String processorId) { + return map.get(processorId); + } + + public static void registerRoomProcessor(String processorId, RoomProcessorGenerator generator) { + map.put(processorId, generator); + } + + public static Set<String> getProcessors() { + return map.keySet(); + } + + static { + registerRoomProcessor("default", new GeneralRoomProcessor.Generator()); + registerRoomProcessor("button_5", new RoomProcessorButtonSolver.Generator()); + registerRoomProcessor("puzzle_water_solver", new RoomProcessorWaterPuzzle.Generator()); + registerRoomProcessor("puzzle_teleport_solver", new RoomProcessorTeleportMazeSolver.Generator()); + registerRoomProcessor("puzzle_riddle_solver", new RoomProcessorRiddle.Generator()); + registerRoomProcessor("puzzle_creeper_solver", new RoomProcessorCreeperSolver.Generator()); + registerRoomProcessor("puzzle_tictactoe_solver", new RoomProcessorTicTacToeSolver.Generator()); + + registerRoomProcessor("puzzle_blaze_solver", new RoomProcessorBlazeSolver.Generator()); + + + registerRoomProcessor("puzzle_silverfish", new RoomProcessorIcePath.Generator()); // done + registerRoomProcessor("puzzle_icefill", new RoomProcessorIcePath2.Generator()); + registerRoomProcessor("puzzle_box", new RoomProcessorBoxSolver.Generator()); + registerRoomProcessor("puzzle_trivia", new RoomProcessorTrivia.Generator()); + registerRoomProcessor("puzzle_bombdefuse", new RoomProcessorBombDefuseSolver.Generator()); + + registerRoomProcessor("bossroom", new RoomProcessorRedRoom.Generator()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessor.java new file mode 100755 index 00000000..f4a26f77 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessor.java @@ -0,0 +1,49 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import kr.syeyoung.dungeonsguide.events.BlockUpdateEvent; +import kr.syeyoung.dungeonsguide.events.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +public interface RoomProcessor { + void tick(); + void drawScreen(float partialTicks); + void drawWorld(float partialTicks); + void chatReceived(IChatComponent chat); + void actionbarReceived(IChatComponent chat); + + boolean readGlobalChat(); + + void onPostGuiRender(GuiScreenEvent.DrawScreenEvent.Post event); + void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent); + void onEntityDeath(LivingDeathEvent deathEvent); + + void onKeybindPress(KeyBindPressedEvent keyInputEvent); + + void onInteract(PlayerInteractEntityEvent event); + void onInteractBlock(PlayerInteractEvent event); + + void onBlockUpdate(BlockUpdateEvent blockUpdateEvent); +}
\ No newline at end of file diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorBlazeSolver.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorBlazeSolver.java new file mode 100755 index 00000000..aa7dc3a9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorBlazeSolver.java @@ -0,0 +1,201 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.entity.monster.EntityBlaze; +import net.minecraft.util.*; +import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class RoomProcessorBlazeSolver extends GeneralRoomProcessor { + + private boolean highToLow = false; + + private List<EntityArmorStand> entityList = new ArrayList<EntityArmorStand>(); + private List<EntityBlaze> blazeList = new ArrayList<>(); + private EntityArmorStand next; + private EntityBlaze nextBlaze, theoneafterit; + public RoomProcessorBlazeSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + Object highToLow = dungeonRoom.getDungeonRoomInfo().getProperties().get("order"); + if (highToLow == null) this.highToLow = false; + else this.highToLow = (Boolean) highToLow; + } + + @Override + public void tick() { + super.tick(); + + DungeonRoom dungeonRoom = getDungeonRoom(); + World w = dungeonRoom.getContext().getWorld(); + final BlockPos low = dungeonRoom.getMin(); + final BlockPos high = dungeonRoom.getMax(); + entityList = new ArrayList<EntityArmorStand>(w.getEntities(EntityArmorStand.class, input -> { + BlockPos pos = input.getPosition(); + return low.getX() < pos.getX() && pos.getX() < high.getX() + && low.getZ() < pos.getZ() && pos.getZ() < high.getZ() && input.getName().toLowerCase().contains("blaze"); + })); + blazeList = new ArrayList<EntityBlaze>(w.getEntities(EntityBlaze.class, input -> { + BlockPos pos = input.getPosition(); + return low.getX() < pos.getX() && pos.getX() < high.getX() + && low.getZ() < pos.getZ() && pos.getZ() < high.getZ(); + })); + + Comparator<EntityArmorStand> comparator = Comparator.comparingInt(a -> { + String name = a.getName(); + String colorGone = TextUtils.stripColor(name); + String health2 = TextUtils.keepIntegerCharactersOnly(colorGone.split("/")[1]); + try { + return Integer.parseInt(health2); + } catch (Exception e) {return -1;} + }); + if (highToLow) { + entityList.sort(comparator.reversed()); + } else { + entityList.sort(comparator); + } + + if (entityList.size() > 0) { + next = entityList.get(0); + nextBlaze = blazeList.stream().min(Comparator.comparingDouble(e -> e.getDistanceSqToEntity(next))).orElse(null); + } else { + next = null; + nextBlaze = null; + } + if (entityList.size() > 1) { + EntityArmorStand thenextone = entityList.get(1); + theoneafterit = blazeList.stream().min(Comparator.comparingDouble(e -> e.getDistanceSqToEntity(thenextone))).orElse(null); + } else { + theoneafterit = null; + } + } + + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_BLAZE.isEnabled()) return; + if (next == null) return; + Vec3 pos = next.getPositionEyes(partialTicks); + RenderUtils.drawTextAtWorld("NEXT", (float)pos.xCoord, (float)pos.yCoord, (float)pos.zCoord, 0xFFFF0000, 0.5f, true, false, partialTicks); + + Entity viewing_from = Minecraft.getMinecraft().getRenderViewEntity(); + + double x_fix = viewing_from.lastTickPosX + ((viewing_from.posX - viewing_from.lastTickPosX) * partialTicks); + double y_fix = viewing_from.lastTickPosY + ((viewing_from.posY - viewing_from.lastTickPosY) * partialTicks); + double z_fix = viewing_from.lastTickPosZ + ((viewing_from.posZ - viewing_from.lastTickPosZ) * partialTicks); + + + for (EntityBlaze entity : blazeList) { + GlStateManager.pushMatrix(); + float f = entity.prevRotationYaw + (entity.rotationYaw - entity.prevRotationYaw) * partialTicks; + double x = entity.prevPosX + (entity.posX - entity.prevPosX) * partialTicks; + double y = entity.prevPosY + (entity.posY - entity.prevPosY) * partialTicks; + double z = entity.prevPosZ + (entity.posZ - entity.prevPosZ) * partialTicks; + + + GL11.glEnable(GL11.GL_STENCIL_TEST); + GL11.glClearStencil(0); + GlStateManager.disableDepth(); + GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT); + + GL11.glStencilMask(0xFF); + GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF); + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_REPLACE, GL11.GL_REPLACE); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + + GlStateManager.colorMask(false, false, false, false); + Minecraft.getMinecraft().getRenderManager().doRenderEntity(entity, x,y,z,f,partialTicks, true); + GlStateManager.colorMask(true, true, true, true); + + GlStateManager.popMatrix(); + + + GL11.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF); + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); + +// Gui.drawRect(-9999,-9999, 9999, 9999, 0xFFFFFFFF); + + boolean border = true; + + RenderUtils.highlightBox(entity, AxisAlignedBB.fromBounds(-0.8,0, -0.8, 0.8, 2, 0.8), FeatureRegistry.SOLVER_BLAZE.getBlazeColor(), partialTicks, false); + if (entity == theoneafterit) { + RenderUtils.highlightBox(entity, AxisAlignedBB.fromBounds(-0.8,0, -0.8, 0.8, 2, 0.8), FeatureRegistry.SOLVER_BLAZE.getNextUpBlazeColor(), partialTicks, false); + } else if (entity == nextBlaze) + RenderUtils.highlightBox(entity, AxisAlignedBB.fromBounds(-0.8,0, -0.8, 0.8, 2, 0.8), FeatureRegistry.SOLVER_BLAZE.getNextBlazeColor(), partialTicks, false); + + GlStateManager.color(1,1,1,1); + + + if (FeatureRegistry.SOLVER_BLAZE.<AColor>getParameter("blazeborder").getValue().getAlpha() > 0x10) { + GL11.glStencilFunc(GL11.GL_NOTEQUAL, 3, 0x01); + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_REPLACE, GL11.GL_REPLACE); + GlStateManager.pushMatrix(); + + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + GlStateManager.translate(x, y + 0.7, z); + GlStateManager.scale(1.1f, 1.1f, 1.1f); + + GlStateManager.colorMask(false, false, false, false); + Minecraft.getMinecraft().getRenderManager().doRenderEntity(entity, 0, -0.7, 0, f, partialTicks, true); + GlStateManager.colorMask(true, true, true, true); + + GlStateManager.popMatrix(); + + + + GL11.glStencilFunc(GL11.GL_EQUAL, 3, 0xFF); + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); + + RenderUtils.highlightBox(entity, AxisAlignedBB.fromBounds(-1, 0, -1, 1, 2, 1), FeatureRegistry.SOLVER_BLAZE.<AColor>getParameter("blazeborder").getValue(), partialTicks, false); + + + } + GL11.glDisable(GL11.GL_STENCIL_TEST); + GlStateManager.enableDepth(); + GlStateManager.popMatrix(); + } + } + + + + public static class Generator implements RoomProcessorGenerator<RoomProcessorBlazeSolver> { + @Override + public RoomProcessorBlazeSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorBlazeSolver defaultRoomProcessor = new RoomProcessorBlazeSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorButtonSolver.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorButtonSolver.java new file mode 100644 index 00000000..e46472e5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorButtonSolver.java @@ -0,0 +1,132 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.util.BlockPos; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +import java.awt.*; +import java.util.Arrays; + +public class RoomProcessorButtonSolver extends GeneralRoomProcessor { + public RoomProcessorButtonSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + + OffsetPointSet ops = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("buttons"); + if (ops == null) { + bugged = true; + return; + } + + buttons = new BlockPos[12]; + woods = new BlockPos[12]; + for (int i = 0; i < ops.getOffsetPointList().size(); i++) { + buttons[i] = ops.getOffsetPointList().get(i).getBlockPos(dungeonRoom); + woods[i] = buttons[i].add(0,-1,0); + } + } + + private boolean bugged; + + private BlockPos[] buttons; + private BlockPos[] woods; + + private long clicked; + private int clickedButton = -1; + + private final int[] result = new int[12]; + + @Override + public void onInteractBlock(PlayerInteractEvent event) { + super.onInteractBlock(event); + if (bugged) return; + + if (event.action != PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) return; + for (int i = 0; i < buttons.length; i++) { + if (event.pos.equals(buttons[i])) { + clicked = System.currentTimeMillis(); + clickedButton = i; + return; + } + } + } + + @Override + public void chatReceived(IChatComponent chat) { + super.chatReceived(chat); + if (bugged) return; + + if (clickedButton == -1) return; + if (clicked + 500 < System.currentTimeMillis()) return; + + String msg = chat.getFormattedText(); + if (msg.equals("§r§cThis button doesn't seem to do anything...§r")) { + result[clickedButton] = -1; + clickedButton = -1; + } else if (msg.equals("§r§aThis button seems connected to something§r")) { + Arrays.fill(result, -1); + if (clickedButton % 4 != 0) result[clickedButton - 1] = 1; + if (clickedButton % 4 != 3) result[clickedButton + 1] = 1; + clickedButton = -1; + } else if (msg.equals("§r§aClick! you Hear the sound of a door opening§r")) { + Arrays.fill(result, -1); + result[clickedButton] = 2; + clickedButton = -1; + } else if (msg.equals("§r§aWrong button, looks like the system reset!§r")) { + Arrays.fill(result, 0); + clickedButton = -1; + } + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (bugged) return; + if (Minecraft.getMinecraft().thePlayer.getPosition().distanceSq(woods[6]) > 100) return; + + + for (int i = 0; i < woods.length; i++) { + int data = result[i]; + BlockPos pos = woods[i]; + + if (data == 0) { + RenderUtils.highlightBlock(pos, new Color(0, 255, 255, 50), partialTicks, false); + } else if (data == -1) { + RenderUtils.highlightBlock(pos, new Color(255, 0, 0, 50), partialTicks, false); + } else if (data == 1) { + RenderUtils.highlightBlock(pos, new Color(0, 255, 0, 50), partialTicks, false); + } else if (data == 2) { + RenderUtils.highlightBlock(pos, new Color(0, 255, 0, 100), partialTicks, false); + } + } + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorButtonSolver> { + @Override + public RoomProcessorButtonSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorButtonSolver defaultRoomProcessor = new RoomProcessorButtonSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorCreeperSolver.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorCreeperSolver.java new file mode 100755 index 00000000..954197ac --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorCreeperSolver.java @@ -0,0 +1,147 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class RoomProcessorCreeperSolver extends GeneralRoomProcessor { + + private final List<BlockPos[]> poses = new ArrayList<BlockPos[]>(); + + private final boolean bugged = false; + + public RoomProcessorCreeperSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + + findCreeperAndDoPoses(); + } + + private boolean check(AxisAlignedBB axis, Vec3 vec) { + if (vec == null) return false; + return axis.isVecInside(vec); + } + + private void findCreeperAndDoPoses() { + World w = getDungeonRoom().getContext().getWorld(); + List<BlockPos> prismarines = new ArrayList<BlockPos>(); + final BlockPos low = getDungeonRoom().getMin().add(0,-2,0); + final BlockPos high = getDungeonRoom().getMax().add(0,20,0); + final AxisAlignedBB axis = AxisAlignedBB.fromBounds( + low.getX() + 17, low.getY() + 7, low.getZ() + 17, + low.getX() + 16, low.getY() + 10.5, low.getZ() + 16 + ); + + for (BlockPos pos : BlockPos.getAllInBox(low, high)) { + Block b = w.getBlockState(pos).getBlock(); + if (b == Blocks.prismarine || b == Blocks.sea_lantern) { + for (EnumFacing face:EnumFacing.VALUES) { + if (w.getBlockState(pos.offset(face)).getBlock() == Blocks.air) { + prismarines.add(pos); + break; + } + } + } + } + double offset = 0.1; + + while (prismarines.size() > 1) { + BlockPos first = prismarines.get(0); + BlockPos highestMatch = null; + int highestDist = 0; + label: for (int i = 1; i < prismarines.size(); i++) { + BlockPos second = prismarines.get(i); + + if (second.distanceSq(first) < highestDist) continue; + + Vec3 startLoc = new Vec3(first).addVector(0.5,0.5,0.5); + Vec3 dest = new Vec3(second).addVector(0.5,0.5,0.5); + if (check(axis, startLoc.getIntermediateWithYValue(dest, axis.minY+offset)) || + check(axis, startLoc.getIntermediateWithYValue(dest, axis.maxY-offset)) || + check(axis, startLoc.getIntermediateWithXValue(dest, axis.minX+offset)) || + check(axis, startLoc.getIntermediateWithXValue(dest, axis.maxX-offset)) || + check(axis, startLoc.getIntermediateWithZValue(dest, axis.minZ+offset)) || + check(axis, startLoc.getIntermediateWithZValue(dest, axis.maxZ-offset))) { + highestDist = (int) second.distanceSq(first); + highestMatch = second; + } + + } + + + if (highestMatch == null) { + prismarines.remove(first); + } else { + prismarines.remove(first); + prismarines.remove(highestMatch); + poses.add(new BlockPos[] {first, highestMatch}); + } + } + } + + @Override + public void tick() { + super.tick(); + if (bugged) { + findCreeperAndDoPoses(); + } + } + + private static final Color[] colors = new Color[] {Color.red, Color.orange, Color.green, Color.cyan, Color.blue, Color.pink, Color.yellow, Color.darkGray, Color.lightGray}; + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_CREEPER.isEnabled()) return; + World w = getDungeonRoom().getContext().getWorld(); + for (int i = 0; i < poses.size(); i++) { + BlockPos[] poset = poses.get(i); + Color color = colors[i % colors.length]; + boolean oneIsConnected = w.getChunkFromBlockCoords(poset[0]).getBlock(poset[0]) != Blocks.sea_lantern && + w.getChunkFromBlockCoords(poset[1]).getBlock(poset[1]) != Blocks.sea_lantern; + RenderUtils.drawLine(new Vec3(poset[0].getX() +0.5, poset[0].getY() +0.5, poset[0].getZ()+0.5), + new Vec3(poset[1].getX() +0.5, poset[1].getY() +0.5, poset[1].getZ()+0.5), oneIsConnected ? new Color(0,0,0,50) : color, partialTicks, true); + } + final BlockPos low = getDungeonRoom().getMin(); + final AxisAlignedBB axis = AxisAlignedBB.fromBounds( + low.getX() + 17, low.getY() + 5, low.getZ() + 17, + low.getX() + 16, low.getY() + 8.5, low.getZ() + 16 + ); + RenderUtils.highlightBox(axis, new Color(0x4400FF00, true), partialTicks, false); + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorCreeperSolver> { + @Override + public RoomProcessorCreeperSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorCreeperSolver defaultRoomProcessor = new RoomProcessorCreeperSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorGenerator.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorGenerator.java new file mode 100755 index 00000000..16fc5f23 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorGenerator.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; + +public interface RoomProcessorGenerator<T extends RoomProcessor> { + T createNew(DungeonRoom dungeonRoom); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorIcePath.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorIcePath.java new file mode 100755 index 00000000..b0f09a0e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorIcePath.java @@ -0,0 +1,234 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import com.google.common.base.Predicate; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.minecraft.entity.Entity; +import net.minecraft.entity.monster.EntitySilverfish; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class RoomProcessorIcePath extends GeneralRoomProcessor { + + private int[][] map; + private OffsetPoint[][] map2; + private final Set<OffsetPoint> endNode = new HashSet<OffsetPoint>(); + + private final List<BlockPos> solution = new ArrayList<BlockPos>(); + + private BlockPos lastSilverfishLoc; + private int sameTick; + + private Entity silverfish; + + private boolean err; + + public RoomProcessorIcePath(DungeonRoom dungeonRoom) { + super(dungeonRoom); + findSilverFishanddoStuff(); + } + + public void findSilverFishanddoStuff() { + final BlockPos low = getDungeonRoom().getMin(); + final BlockPos high = getDungeonRoom().getMax(); + List<EntitySilverfish> silverfishs = getDungeonRoom().getContext().getWorld().getEntities(EntitySilverfish.class, new Predicate<EntitySilverfish>() { + @Override + public boolean apply(@Nullable EntitySilverfish input) { + if (input.isInvisible()) return false; + BlockPos pos = input.getPosition(); + return low.getX() < pos.getX() && pos.getX() < high.getX() + && low.getZ() < pos.getZ() && pos.getZ() < high.getZ(); + } + }); + + if (!silverfishs.isEmpty()) silverfish = silverfishs.get(0); + if (silverfishs.isEmpty()) { + err = true; + return; + } + try { + buildMap(); + err = false; + } catch (Exception e) { + e.printStackTrace(); + err = true; + return; + } + } + + private void buildMap() { + int width = (Integer) getDungeonRoom().getDungeonRoomInfo().getProperties().get("width"); + int height = (Integer) getDungeonRoom().getDungeonRoomInfo().getProperties().get("height"); + OffsetPointSet ops = (OffsetPointSet) getDungeonRoom().getDungeonRoomInfo().getProperties().get("board"); + OffsetPointSet endNodes = (OffsetPointSet) getDungeonRoom().getDungeonRoomInfo().getProperties().get("endnodes"); + map2 = new OffsetPoint[width][height]; + map = new int[width][height]; + for (int y = 0; y < height; y ++) { + for (int x =0; x < width; x++) { + OffsetPoint op = ops.getOffsetPointList().get(y * width + x); + map2[y][x] = op; + map[y][x] = op.getBlock(getDungeonRoom()) == Blocks.air ? 0 : 1; + } + } + endNode.addAll(endNodes.getOffsetPointList()); + } + + public void tick() { + super.tick(); + if (err || silverfish.isDead) { + findSilverFishanddoStuff(); + if (err) return; + } + if (silverfish.getPosition().equals(lastSilverfishLoc)) { + if (sameTick < 10) { + sameTick ++; + return; + } else if (sameTick == 10) { + sameTick ++; + Point silverfish = getPointOfSilverFishOnMap(this.silverfish.getPosition()); + List<Point> tempSol = solve(map, silverfish.x, silverfish.y, new Predicate<Point>() { + @Override + public boolean apply(@Nullable Point input) { + return endNode.contains(map2[input.y][input.x]); + } + }); + { + solution.clear(); + for (Point point : tempSol) { + solution.add(map2[point.y][point.x].getBlockPos(getDungeonRoom())); + } + } + + } + } else { + sameTick = 0; + } + + lastSilverfishLoc = silverfish.getPosition(); + } + + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_SILVERFISH.isEnabled()) return; + if (!err) + RenderUtils.drawLines(solution, FeatureRegistry.SOLVER_SILVERFISH.getLineColor(),FeatureRegistry.SOLVER_SILVERFISH.getLineWidth(), partialTicks, true); + } + + public Point getPointOfSilverFishOnMap(BlockPos blockPos) { + for (int y = 0; y < map.length; y ++) { + for (int x = 0; x < map[0].length; x++) { + if (map2[y][x].getBlockPos(getDungeonRoom()).equals(blockPos)) + return new Point(x,y); + } + } + return null; + } + + + // Taken from https://stackoverflow.com/a/55271133 and modified to suit our needs + // Answer by ofekp (https://stackoverflow.com/users/4295037/ofekp) + public static List<Point> solve(int[][] board, int startX, int startY, Predicate<Point> finishLinePredicate) { + Point startPoint = new Point(startX, startY); + + LinkedList<Point> queue = new LinkedList<Point>(); + Point[][] boardSearch = new Point[board.length][board[0].length]; + + queue.addLast(new Point(startX, startY)); + boardSearch[startY][startX] = startPoint; + + while (queue.size() != 0) { + Point currPos = queue.pollFirst(); + for (Direction dir : Direction.values()) { + Point nextPos = move(board, boardSearch, currPos, dir); + if (nextPos != null) { + queue.addLast(nextPos); + boardSearch[nextPos.y][nextPos.x] = new Point(currPos.x, currPos.y); + if (finishLinePredicate.apply(nextPos)) { + List<Point> route = new ArrayList<Point>(); + Point tmp = currPos; + route.add(nextPos); + route.add(currPos); + while (tmp != startPoint) { + tmp = boardSearch[tmp.y][tmp.x]; + route.add(tmp); + } + return route; + } + } + } + } + return Collections.emptyList(); + } + + public static Point move(int[][] board, Point[][] boardSearch, Point currPos, Direction dir) { + int x = currPos.x; + int y = currPos.y; + + int diffX = dir.dx; + int diffY = dir.dy; + + int i = 1; + while (x + i * diffX >= 0 && x + i * diffX < board[0].length + && y + i * diffY >= 0 && y + i * diffY < board.length + && board[y + i * diffY][x + i * diffX] != 1) { + i++; + } + i--; + + if (boardSearch[y + i * diffY][x + i * diffX] != null) { + return null; + } + + return new Point(x + i * diffX, y + i * diffY); + } + + @Getter + @AllArgsConstructor + public enum Direction { + LEFT(-1,0), + RIGHT(1,0), + UP(0,-1), + DOWN(0,1); + + int dx, dy; + } + + + public static class Generator implements RoomProcessorGenerator<RoomProcessorIcePath> { + @Override + public RoomProcessorIcePath createNew(DungeonRoom dungeonRoom) { + RoomProcessorIcePath defaultRoomProcessor = new RoomProcessorIcePath(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorRedRoom.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorRedRoom.java new file mode 100644 index 00000000..327b98f6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorRedRoom.java @@ -0,0 +1,121 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonDoor; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.impl.boss.FeatureWarningOnPortal; +import kr.syeyoung.dungeonsguide.features.text.StyledTextRenderer; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.util.BlockPos; +import net.minecraft.util.MathHelper; +import net.minecraft.util.Vec3; +import org.lwjgl.opengl.GL11; + +import javax.vecmath.Vector3f; + +public class RoomProcessorRedRoom extends GeneralRoomProcessor { + public RoomProcessorRedRoom(DungeonRoom dungeonRoom) { + super(dungeonRoom); + BlockPos basePt = dungeonRoom.getMin().add(dungeonRoom.getMax()); + this.basePt = new Vec3(basePt.getX() / 2.0f, basePt.getY() / 2.0f, basePt.getZ() / 2.0f); + } + + Vec3 basePt; + int dir = 0; + + @Override + public void tick() { + BlockPos basePt = getDungeonRoom().getMin().add(getDungeonRoom().getMax()); + this.basePt = new Vec3(basePt.getX() / 2.0f, basePt.getY() / 2.0f + 4, basePt.getZ() / 2.0f); + DungeonDoor real = null; + for (DungeonDoor door : getDungeonRoom().getDoors()) { + if (door.getType().isExist()) { + real = door;break; + } + } + if (real != null) { + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), real.getPosition()); + offsetPoint = new OffsetPoint(33- offsetPoint.getX(), offsetPoint.getY(), 33 - offsetPoint.getZ()); + BlockPos opposite =offsetPoint.getBlockPos(getDungeonRoom()); + BlockPos dir = new BlockPos(real.getPosition().subtract(opposite)); + dir = new BlockPos(MathHelper.clamp_int(dir.getX() / 10, -1, 1), 0, MathHelper.clamp_int(dir.getZ() / 10, -1, 1)); + + this.basePt = new Vec3(opposite.add(dir.getX() * 6 + dir.getZ(), 3, dir.getZ() * 6 - dir.getX())); + + if (dir.getX() > 0) this.dir = 270; + else if (dir.getX() < 0) this.dir = 90; + else if (dir.getZ() < 0) this.dir = 0; + else if (dir.getZ() > 0) this.dir = 180; + else this.dir = Integer.MIN_VALUE; + } else { + dir = Integer.MIN_VALUE; + } + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.BOSSFIGHT_WARNING_ON_PORTAL.isEnabled()) return; + + + FeatureWarningOnPortal featureWarningOnPortal = FeatureRegistry.BOSSFIGHT_WARNING_ON_PORTAL; + { + RenderManager renderManager = Minecraft.getMinecraft().getRenderManager(); + + Vector3f renderPos = RenderUtils.getRenderPos((float)basePt.xCoord,(float) basePt.yCoord, (float)basePt.zCoord, partialTicks); + + GlStateManager.color(1f, 1f, 1f, 0.5f); + GlStateManager.pushMatrix(); + GlStateManager.translate(renderPos.x, renderPos.y, renderPos.z); + if (dir == Integer.MIN_VALUE) + GlStateManager.rotate(-renderManager.playerViewY, 0.0f, 1.0f, 0.0f); + else + GlStateManager.rotate(dir, 0.0f, 1.0f, 0.0f); + GlStateManager.scale(-0.05f, -0.05f, 0.05f); + GlStateManager.disableLighting(); + GlStateManager.depthMask(false); GL11.glDisable(GL11.GL_DEPTH_TEST); + GlStateManager.disableDepth(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + + StyledTextRenderer.drawTextWithStylesAssociated(featureWarningOnPortal.getText(), 0, 0,0, featureWarningOnPortal.getStylesMap(), StyledTextRenderer.Alignment.LEFT); + + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.depthMask(true); + GlStateManager.enableDepth(); + GlStateManager.popMatrix(); + } + } + + + public static class Generator implements RoomProcessorGenerator<RoomProcessorRedRoom> { + @Override + public RoomProcessorRedRoom createNew(DungeonRoom dungeonRoom) { + RoomProcessorRedRoom defaultRoomProcessor = new RoomProcessorRedRoom(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorRiddle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorRiddle.java new file mode 100755 index 00000000..96192ef7 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorRiddle.java @@ -0,0 +1,121 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import com.google.common.base.Predicate; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.init.Blocks; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +public class RoomProcessorRiddle extends GeneralRoomProcessor { + + public RoomProcessorRiddle(DungeonRoom dungeonRoom) { + super(dungeonRoom); + } + + private static final List<Pattern> patternList = Arrays.asList( + Pattern.compile("My chest doesn't have the reward. We are all telling the truth.*"), + Pattern.compile("The reward isn't in any of our chests.*"), + Pattern.compile("The reward is not in my chest!.*"), + Pattern.compile("At least one of them is lying, and the reward is not in .+'s chest.*"), + Pattern.compile("Both of them are telling the truth. Also,.+has the reward in their chest.*"), + Pattern.compile("My chest has the reward and I'm telling the truth.*") + ); + + @Override + public void chatReceived(IChatComponent chat) { + super.chatReceived(chat); + if (!FeatureRegistry.SOLVER_RIDDLE.isEnabled()) return; + String ch2 = chat.getUnformattedText(); + if (!ch2.startsWith("§e[NPC] ")) { + return; + } + String watsaid = TextUtils.stripColor(ch2.split(":")[1]).trim(); + boolean foundMatch = false; + for (Pattern p:patternList) { + if (p.matcher(watsaid).matches()) { + foundMatch = true; + break; + } + } + if (foundMatch) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §eRiddle §7:: "+ch2.split(":")[0].trim()+" §fhas the reward!")); + final String name = TextUtils.stripColor(ch2.split(":")[0]).replace("[NPC] ","").trim(); + final BlockPos low = getDungeonRoom().getMin(); + final BlockPos high = getDungeonRoom().getMax(); + World w = getDungeonRoom().getContext().getWorld(); + List<EntityArmorStand> armor = w.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() { + @Override + public boolean apply(@Nullable EntityArmorStand input) { + BlockPos pos = input.getPosition(); + return low.getX() < pos.getX() && pos.getX() < high.getX() + && low.getZ() < pos.getZ() && pos.getZ() < high.getZ() && TextUtils.stripColor(input.getName()).equalsIgnoreCase(name); + } + }); + + if (armor != null) { + this.chest = null; + BlockPos pos = armor.get(0).getPosition(); + for (BlockPos allInBox : BlockPos.getAllInBox(pos.add(-1, 0, -1), pos.add(1, 0, 1))) { + Block b = w.getChunkFromBlockCoords(allInBox).getBlock(allInBox); + + if ((b == Blocks.chest || b == Blocks.trapped_chest)&& allInBox.distanceSq(pos) == 1 ) { + this.chest = allInBox; + return; + } + } + } + + } + } + + BlockPos chest; + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_RIDDLE.isEnabled()) return; + if (chest != null) { + RenderUtils.highlightBoxAColor(AxisAlignedBB.fromBounds(chest.getX(), chest.getY(), chest.getZ(), chest.getX()+1, chest.getY() + 1, chest.getZ() + 1), FeatureRegistry.SOLVER_RIDDLE.getTargetColor(), partialTicks, true); + } + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorRiddle> { + @Override + public RoomProcessorRiddle createNew(DungeonRoom dungeonRoom) { + RoomProcessorRiddle defaultRoomProcessor = new RoomProcessorRiddle(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorTeleportMazeSolver.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorTeleportMazeSolver.java new file mode 100755 index 00000000..cadd3024 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorTeleportMazeSolver.java @@ -0,0 +1,141 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.init.Blocks; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +import java.util.ArrayList; +import java.util.List; + +public class RoomProcessorTeleportMazeSolver extends GeneralRoomProcessor { + private BlockPos lastPlayerLocation; + + public RoomProcessorTeleportMazeSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + yLevel = dungeonRoom.getMin().getY() - 1; + } + + private final List<BlockPos> visitedPortals = new ArrayList<BlockPos>(); + + private int yLevel = 0; + private double slope1, slope2; + private double posX1, posZ1, posX2, posZ2; + private int times=0 ; + + private double intersectionX, intersectionZ; + private BlockPos intersection; + + @Override + public void tick() { + super.tick(); + + + + World w = getDungeonRoom().getContext().getWorld(); + EntityPlayerSP entityPlayerSP = Minecraft.getMinecraft().thePlayer; + BlockPos pos2 = new BlockPos(Math.floor(entityPlayerSP.posX), Math.floor(entityPlayerSP.posY), Math.floor(entityPlayerSP.posZ)); + Block b = w.getChunkFromBlockCoords(pos2).getBlock(pos2); + Vec3 lookVec = entityPlayerSP.getLookVec(); + + if (times % 4 == 1) { + posX1 = entityPlayerSP.posX; + posZ1 = entityPlayerSP.posZ; + slope1 = lookVec.zCoord / lookVec.xCoord; + times ++; + } else if (times % 4 == 3) { + posX2 = entityPlayerSP.posX; + posZ2 = entityPlayerSP.posZ; + slope2 = lookVec.zCoord / lookVec.xCoord; + + double yInt1 = posZ1 - posX1 * slope1; + double yInt2 = posZ2 - posX2 * slope2; + + intersectionX = (yInt2 - yInt1) / (slope1 - slope2); + intersectionZ = (slope1 * intersectionX + yInt1); + intersection = new BlockPos((int) intersectionX, yLevel, (int) intersectionZ); + times++; + } + + if (b == Blocks.stone_slab || b == Blocks.stone_slab2) { + boolean teleport = false; + if (lastPlayerLocation.distanceSq(pos2) < 3) return; + for (BlockPos allInBox : BlockPos.getAllInBox(lastPlayerLocation, pos2)) { + if (w.getChunkFromBlockCoords(allInBox).getBlock(allInBox) == Blocks.iron_bars) { + teleport = true; + break; + } + } + + if (teleport) { + if (times % 4 == 0) { + times ++; + } else if (times % 4 == 2){ + times++; + } + + for (BlockPos allInBox : BlockPos.getAllInBox(pos2.add(-1, 0, -1), pos2.add(1, 0, 1))) { + if (w.getChunkFromBlockCoords(allInBox).getBlock(allInBox) == Blocks.end_portal_frame) { + if (!visitedPortals.contains(allInBox)) + visitedPortals.add(allInBox); + break; + } + } + for (BlockPos allInBox : BlockPos.getAllInBox(lastPlayerLocation.add(-1, -1, -1), lastPlayerLocation.add(1, 1, 1))) { + if (w.getChunkFromBlockCoords(allInBox).getBlock(allInBox) == Blocks.end_portal_frame) { + if (!visitedPortals.contains(allInBox)) + visitedPortals.add(allInBox); + break; + } + } + } + } + + lastPlayerLocation = pos2; + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_TELEPORT.isEnabled()) return; + for (BlockPos bpos:visitedPortals) { + RenderUtils.highlightBoxAColor( AxisAlignedBB.fromBounds(bpos.getX(), bpos.getY(), bpos.getZ(), bpos.getX()+1, bpos.getY() + 1, bpos.getZ() + 1), FeatureRegistry.SOLVER_TELEPORT.getTargetColor2(), partialTicks, true); + } + + if (intersection != null) { + RenderUtils.highlightBoxAColor( AxisAlignedBB.fromBounds(intersection.getX(), intersection.getY(), intersection.getZ(), intersection.getX()+1, intersection.getY() + 1, intersection.getZ() + 1), FeatureRegistry.SOLVER_TELEPORT.getTargetColor(), partialTicks, false); + } + } + public static class Generator implements RoomProcessorGenerator<RoomProcessorTeleportMazeSolver> { + @Override + public RoomProcessorTeleportMazeSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorTeleportMazeSolver defaultRoomProcessor = new RoomProcessorTeleportMazeSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorTicTacToeSolver.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorTicTacToeSolver.java new file mode 100755 index 00000000..d63d432f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorTicTacToeSolver.java @@ -0,0 +1,214 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.entity.item.EntityItemFrame; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemMap; +import net.minecraft.item.ItemStack; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.storage.MapData; + +import java.util.List; + +public class RoomProcessorTicTacToeSolver extends GeneralRoomProcessor { + + private final OffsetPointSet board; + private byte[][] lastBoard; + public RoomProcessorTicTacToeSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + + board = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("board"); + } + + // -1 com, 1 pla, 0 emp + private byte[][] buildBoardState() { + byte[][] board = new byte[3][3]; + World w= getDungeonRoom().getContext().getWorld(); + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 3; y++) { + OffsetPoint op = this.board.getOffsetPointList().get(x * 3 + y); + BlockPos bpos = op.getBlockPos(getDungeonRoom()); + Block b = w.getChunkFromBlockCoords(bpos).getBlock(bpos); + if (b == Blocks.stone_button) { + board[y][x] = 0; + } else if (b == Blocks.air){ + AxisAlignedBB abab = AxisAlignedBB.fromBounds(bpos.getX() , bpos.getY(), bpos.getZ(), bpos.getX() +1, bpos.getY() +1, bpos.getZ() +1); + List<EntityItemFrame> frames = getDungeonRoom().getContext().getWorld().getEntitiesWithinAABB(EntityItemFrame.class, abab); + if (frames.isEmpty()) board[y][x] = 0; + else { + ItemStack displayedItem = frames.get(0).getDisplayedItem(); + if (displayedItem == null || displayedItem.getItem() == null || !displayedItem.getItem().isMap()) { + board[y][x] = 0; + continue; + } + MapData mapData = ((ItemMap)displayedItem.getItem()).getMapData(displayedItem, w); + byte center = mapData.colors[64 * 128+64]; + if (center == 114) + board[y][x] = -1; + else + board[y][x] = 1; + } + } + } + } + return board; + } + + private byte checkWinner(byte[][] board) { + for (int y = 0; y <3; y++) { + byte potentialWinner = board[y][0]; + if (potentialWinner == 0) continue; + boolean found = false; + for (int x = 0; x < 3; x++) { + if (potentialWinner != board[y][x]) { + found = true; + break; + } + } + if (!found) { + return potentialWinner; + } + } + for (int x = 0; x <3; x++) { + byte potentialWinner = board[0][x]; + if (potentialWinner == 0) continue; + boolean found = false; + for (int y = 0; y < 3; y++) { + if (potentialWinner != board[y][x]) { + found = true; + break; + } + } + if (!found) { + return potentialWinner; + } + } + if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != 0) { + return board[0][0]; + } + if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != 0) { + return board[0][2]; + } + return 0; + } + + private int chosePos = -1; + private int minimax(byte[][] board, byte player) { + byte winner = checkWinner(board); + if (winner != 0) { + return winner * player; + } + + int move = -1; + int score = -2; + for (int i = 0; i < 9; i++) { + if (board[i % 3][i / 3] == 0) { + byte[][] cloned = new byte[3][]; + for(int k = 0; k < 3; k++) + cloned[k] = board[k].clone(); + + cloned[i % 3][i/3] = player; + int scoreForMove = -minimax(cloned, (byte) -player); + if (scoreForMove > score) { + score = scoreForMove; + move = i; + } + } + } + chosePos = move; + if (move == -1) { + return 0; + } + + return score; + } + + private boolean gameEnded = false; + + @Override + public void tick() { + super.tick(); + if (board == null) return; + if (gameEnded) return; + byte[][] board = buildBoardState(); + if (checkWinner(board) != 0) { + gameEnded = true; + return; + } + if (lastBoard != null) { + boolean yesdoit = false; + label: + for (int y = 0; y < 3; y++) + for (int x = 0; x < 3; x++) + if (board[y][x] != lastBoard[y][x]) { + yesdoit = true; + break label; + } + if (!yesdoit) return; + } + lastBoard = board; + + minimax(board, (byte) 1); + if (chosePos == -1) { + gameEnded = true; + return; + } + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_TICTACTOE.isEnabled()) return; + if (chosePos != -1) { + BlockPos block = board.getOffsetPointList().get(chosePos).getBlockPos(getDungeonRoom()); + boolean whoseturn = false; // false => hype true => me + if (lastBoard != null) { + int ones = 0; + int negativeones = 0; + for (byte[] bytes : lastBoard) { + for (byte aByte : bytes) { + if (aByte == 1) ones++; + else if (aByte == -1) negativeones++; + } + } + whoseturn = ones < negativeones; + } + RenderUtils.highlightBoxAColor(AxisAlignedBB.fromBounds(block.getX(), block.getY(), block.getZ(), block.getX()+1, block.getY() + 1, block.getZ() + 1), + whoseturn ? FeatureRegistry.SOLVER_TICTACTOE.getTargetColor() + : FeatureRegistry.SOLVER_TICTACTOE.getTargetColor2(), partialTicks, true); + } + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorTicTacToeSolver> { + @Override + public RoomProcessorTicTacToeSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorTicTacToeSolver defaultRoomProcessor = new RoomProcessorTicTacToeSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorTrivia.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorTrivia.java new file mode 100755 index 00000000..3f979c41 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorTrivia.java @@ -0,0 +1,165 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.SkyblockUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import kr.syeyoung.dungeonsguide.wsresource.StaticResourceCache; +import net.minecraft.client.Minecraft; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; +import org.apache.commons.lang3.math.NumberUtils; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.*; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RoomProcessorTrivia extends GeneralRoomProcessor { + + public RoomProcessorTrivia(DungeonRoom dungeonRoom) { + super(dungeonRoom); + } + + + private final List<String> questionDialog = new ArrayList<String>(); + private boolean questionDialogStart = false; + + private boolean parseDialog = false; + @Override + public void chatReceived(IChatComponent chat) { + super.chatReceived(chat); + if (!FeatureRegistry.SOLVER_KAHOOT.isEnabled()) return; + String ch2 = chat.getUnformattedText(); + if (parseDialog) { + parseDialog = false; + parseDialog(); + } + if (chat.getFormattedText().contains("§r§6§lQuestion ")) { + questionDialogStart = true; + questionDialog.clear(); + } + if (questionDialogStart && (chat.getFormattedText().startsWith("§r§r§r") || chat.getFormattedText().startsWith("§r§r§r") || chat.getFormattedText().trim().startsWith("§r§6 "))) { + questionDialog.add(chat.getFormattedText()); + } + + if (chat.getFormattedText().contains("§r§6 ⓒ")) { + questionDialogStart = false; + parseDialog = true; + } + } + public static final Pattern anwerPattern = Pattern.compile("§r§6 . §a(.+)§r"); + private void parseDialog() { + String question = TextUtils.stripColor(questionDialog.get(1)).trim(); + String answerA = getAnswer(questionDialog.get(2)); + String answerB = getAnswer(questionDialog.get(3)); + String answerC = getAnswer(questionDialog.get(4)); + match(question, answerA, answerB, answerC); + + } + String correctAnswer; + + + private String getAnswer(String answerString) { + Matcher matcher = anwerPattern.matcher(answerString.trim()); + if (!matcher.matches()) return ""; + return matcher.group(1); + } + private void match(String question, String a, String b, String c) { + StaticResourceCache.INSTANCE.getResource(StaticResourceCache.TRIVIA_ANSWERS).thenAccept(value -> { + JSONObject answersJSON = new JSONObject(value.getValue()); + + String semi_answers = answersJSON.getString(question.toLowerCase().trim()); + String theRealAnswer; + if (semi_answers == null) theRealAnswer = null; + else { + semi_answers = takeCareOfPlaceHolders(semi_answers); + String[] answers = semi_answers.split(","); + if (match(answers, a)) theRealAnswer = "A"; + else if (match(answers, b)) theRealAnswer = "B"; + else if (match(answers, c)) theRealAnswer = "C"; + else theRealAnswer = semi_answers; + } + if (theRealAnswer == null) + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §eTrivia §7:: §cCouldn't determine the answer! (no question found)")); + else if (theRealAnswer.length() >1) + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §eTrivia §7:: §cCouldn't determine the answer! ("+theRealAnswer+")")); + else + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §eTrivia §7:: "+theRealAnswer+"§f is the correct answer!")); + correctAnswer = theRealAnswer; + }); + } + + private String takeCareOfPlaceHolders(String input) { + String str = input; + if (str.contains("$year")) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §fuses §eInventiveTalent§7(https://github.com/InventivetalentDev)§e's Skyblock Api §fto fetch current skyblock year!")); + try { + str = str.replace("$year", SkyblockUtils.getSkyblockYear()+""); + } catch (IOException e) { + str = str.replace("$year", "Couldn't determine current skyblock year :: "+e.getMessage()); + } + } + return str; + } + private boolean match(String[] match, String match2) { + for (String s : match) { + if (NumberUtils.isNumber(s)) { + if (match2.toLowerCase().contains(s)) return true; + } else { + if (match2.equalsIgnoreCase(s)) return true; + } + } + return false; + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_KAHOOT.isEnabled()) return; + if (correctAnswer == null) return; + + OffsetPoint op = (OffsetPoint) getDungeonRoom().getDungeonRoomInfo().getProperties().get(correctAnswer); + if (op != null) { + BlockPos solution = op.getBlockPos(getDungeonRoom()); + RenderUtils.highlightBoxAColor(AxisAlignedBB.fromBounds(solution.getX(), solution.getY(), solution.getZ(), solution.getX()+1, solution.getY() + 1, solution.getZ() + 1), FeatureRegistry.SOLVER_KAHOOT.getTargetColor(), partialTicks, false); + } + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorTrivia> { + @Override + public RoomProcessorTrivia createNew(DungeonRoom dungeonRoom) { + RoomProcessorTrivia defaultRoomProcessor = new RoomProcessorTrivia(dungeonRoom); + return defaultRoomProcessor; + } + } + + @Override + public boolean readGlobalChat() { + return true; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/RoomProcessorBombDefuseSolver.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/RoomProcessorBombDefuseSolver.java new file mode 100644 index 00000000..993f0c2b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/RoomProcessorBombDefuseSolver.java @@ -0,0 +1,441 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.events.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor; +import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessorGenerator; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.DummyDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.arrow.ArrowProcessorMatcher; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.bugged.ImpossibleMatcher; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.color.ColorProcessorMatcher; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.creeper.CreeperProcessorMatcher; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.goldenpath.GoldenPathProcessorMatcher; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.maze.MazeProcessorMatcher; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.number.NumberProcessorMatcher; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import org.apache.commons.codec.binary.Base64; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class RoomProcessorBombDefuseSolver extends GeneralRoomProcessor { + + @Getter + private final List<ChamberSet> chambers = new ArrayList<ChamberSet>(); + @Getter + private OffsetPointSet doors; + + private static final List<BombDefuseChamberGenerator> chamberGenerators = new ArrayList<BombDefuseChamberGenerator>(); + { + chamberGenerators.add(new ArrowProcessorMatcher()); + chamberGenerators.add(new ColorProcessorMatcher()); + chamberGenerators.add(new CreeperProcessorMatcher()); + chamberGenerators.add(new NumberProcessorMatcher()); + chamberGenerators.add(new GoldenPathProcessorMatcher()); + chamberGenerators.add(new MazeProcessorMatcher()); + chamberGenerators.add(new ImpossibleMatcher()); + } + + private boolean bugged = false; + private boolean maze = false; + private boolean impossible = false; + + public RoomProcessorBombDefuseSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + if (!FeatureRegistry.SOLVER_BOMBDEFUSE.isEnabled()) { + bugged = true; + return; + } + chambers.add(new ChamberSet( + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("L1"), 1, true), + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("R1"), 1, true), null + )); + chambers.add(new ChamberSet( + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("L2"), 2, true), + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("R2"), 2, true), null + )); + chambers.add(new ChamberSet( + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("L3"), 3, true), + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("R3"), 3, true), null + )); + chambers.add(new ChamberSet( + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("L4"), 4, true), + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("R4"), 4, true), null + )); + doors = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("Door"); + if (doors == null) {bugged = true; return;} + for (ChamberSet set:chambers) { + if (set.getLeft().getChamberBlocks() == null) { + bugged = true; + return; + } + if (set.getRight().getChamberBlocks() == null) { + bugged = true; + return; + } + } + + for (ChamberSet set:chambers) { + if (set.getLeft().getChamberBlocks() == null) { + bugged = true; + return; + } + if (set.getRight().getChamberBlocks() == null) { + bugged = true; + return; + } + } + + for (ChamberSet set:chambers) { + for (BombDefuseChamberGenerator bdcg:chamberGenerators) { + if (bdcg.match(set.getLeft(), set.getRight())) { + set.setChamberGen(bdcg); + set.getLeft().setProcessor(bdcg.createLeft(set.getLeft(), this)); + set.getRight().setProcessor(bdcg.createRight(set.getRight(), this)); + if (bdcg instanceof ImpossibleMatcher) impossible=true; + if (bdcg instanceof MazeProcessorMatcher) maze = true; + break; + } + } + if (set.getChamberGen() == null) { + set.setChamberGen(null); + set.getLeft().setProcessor(new DummyDefuseChamberProcessor(this, set.getLeft())); + set.getRight().setProcessor(new DummyDefuseChamberProcessor(this, set.getRight())); + } + } + + OffsetPoint warning1 = (OffsetPoint) dungeonRoom.getDungeonRoomInfo().getProperties().get("Warning"); + if (warning1 != null) warning = warning1.getBlockPos(dungeonRoom); + } + + public BDChamber buildChamber(OffsetPointSet ops, int level, boolean left) { + return new BDChamber(getDungeonRoom(), ops, left, level, null); + } + BlockPos warning; + + + public void communicate(NBTTagCompound compound) { + if (bugged) return; + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream w = new DataOutputStream(baos); + CompressedStreamTools.writeCompressed(compound, w); + w.flush(); + byte[] bytes = baos.toByteArray(); + String str = Base64.encodeBase64String(bytes); + Minecraft.getMinecraft().thePlayer.sendChatMessage("/pc $DG-BD " +str); + + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) + ch.getLeft().getProcessor().onDataRecieve(compound); + if (ch.getRight() != null && ch.getRight().getProcessor() != null) + ch.getRight().getProcessor().onDataRecieve(compound); + } + } catch (IOException e2) { + e2.printStackTrace(); + DungeonsGuide.sendDebugChat(new ChatComponentText("Failed to send Bomb Defuse Chat")); + } + } + + @Override + public void chatReceived(IChatComponent component) { + super.chatReceived(component); + if (bugged) return; + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) + ch.getLeft().getProcessor().chatReceived(component); + if (ch.getRight() != null && ch.getRight().getProcessor() != null) + ch.getRight().getProcessor().chatReceived(component); + } + + if (component.getFormattedText().contains("$DG-BD ")) { + try { + String data = component.getFormattedText().substring(component.getFormattedText().indexOf("$DG-BD")); + String actual = TextUtils.stripColor(data).trim().split(" ")[1]; + byte[] data2 = Base64.decodeBase64(actual); + NBTTagCompound compound = CompressedStreamTools.readCompressed(new ByteArrayInputStream(data2)); + + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) + ch.getLeft().getProcessor().onDataRecieve(compound); + if (ch.getRight() != null && ch.getRight().getProcessor() != null) + ch.getRight().getProcessor().onDataRecieve(compound); + } + } catch (Throwable t) { + t.printStackTrace(); + DungeonsGuide.sendDebugChat(new ChatComponentText("Failed to analyze Bomb Defuse Chat")); + } + } + } + + + @Override + public void tick() { + super.tick(); + if (bugged) return; + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().tick(); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().tick(); + } + } + } + } + + + @Override + public void drawScreen(float partialTicks) { + super.drawScreen(partialTicks); + if (bugged) return; + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + if (FeatureRegistry.DEBUG.isEnabled()) { + for (ChamberSet ch : chambers) { + if (ch.getChamberGen() == null) continue; + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().drawScreen(partialTicks); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + String str = "Current: " + ch.getChamberGen().getName() + " Specific: " + ch.getLeft().getProcessor().getName(); + fr.drawString(str, 0, 0, 0xFFFFFFFF); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().drawScreen(partialTicks); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + if (ch.getChamberGen() == null || ch.getRight().getProcessor() == null) continue; + String str = "Current: " + ch.getChamberGen().getName() + " Specific: " + ch.getRight().getProcessor().getName(); + fr.drawString(str, 0, 0, 0xFFFFFFFF); + } + } + } + } + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (bugged) return; + + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos((int)Minecraft.getMinecraft().thePlayer.posX, 68, (int)Minecraft.getMinecraft().thePlayer.posZ)); + boolean found = false; + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + found = true; + ch.getLeft().getProcessor().drawWorld(partialTicks); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + found = true; + ch.getRight().getProcessor().drawWorld(partialTicks); + } + } + } + + if ((maze || impossible) && warning != null && !found) { + if (impossible) { + RenderUtils.drawTextAtWorld("Warning: This Bomb Defuse is bugged and Impossible" , warning.getX()+ 0.5f, warning.getY(), warning.getZ()+ 0.5f, 0xFF00FF00, 0.03F, false, false, partialTicks); + } else { + RenderUtils.drawTextAtWorld("Warning: This Bomb Defuse must be done with 2 people (maze)" , warning.getX()+ 0.5f, warning.getY(), warning.getZ()+ 0.5f, 0xFF00FF00, 0.03F, false, false, partialTicks); + } + } + if (warning != null && !found) { + for (int i = 0; i < 4; i++) { + BombDefuseChamberGenerator bdcg = chambers.get(i).getChamberGen(); + RenderUtils.drawTextAtWorld((i + 1) + ". " + (bdcg == null ? "null" : bdcg.getName()), warning.getX() + 0.5f, warning.getY() - ((i + 1) * 0.3f), warning.getZ() + 0.5f, 0xFF00FF00, 0.03F, false, false, partialTicks); + } + } + } + + @Override + public void actionbarReceived(IChatComponent chat) { + super.actionbarReceived(chat); + if (bugged) return; + + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) + ch.getLeft().getProcessor().actionbarReceived(chat); + if (ch.getRight() != null && ch.getRight().getProcessor() != null) + ch.getRight().getProcessor().actionbarReceived(chat); + } + } + + @Override + public void onPostGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) { + super.onPostGuiRender(event); + if (bugged) return; + + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().onPostGuiRender(event); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().onPostGuiRender(event); + } + } + } + } + + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + super.onEntityUpdate(updateEvent); + if (bugged) return; + + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().onEntityUpdate(updateEvent); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { +// if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().onEntityUpdate(updateEvent); +// } + } + } + } + + @Override + public void onKeybindPress(KeyBindPressedEvent keyInputEvent) { + super.onKeybindPress(keyInputEvent); + if (bugged) return; + + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().onKeybindPress(keyInputEvent); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().onKeybindPress(keyInputEvent); + } + } + } + } + + @Override + public void onInteract(PlayerInteractEntityEvent event) { + super.onInteract(event); + if (bugged) return; + + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().onInteract(event); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().onInteract(event); + } + } + } + } + + @Override + public void onInteractBlock(PlayerInteractEvent event) { + super.onInteractBlock(event); + if (bugged) return; + + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().onInteractBlock(event); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().onInteractBlock(event); + } + } + } + } + + @Override public boolean readGlobalChat() { return true; } + + @Data + @AllArgsConstructor + public static class ChamberSet { + private BDChamber left; + private BDChamber right; + private BombDefuseChamberGenerator chamberGen; + } + + + public static class Generator implements RoomProcessorGenerator<RoomProcessorBombDefuseSolver> { + @Override + public RoomProcessorBombDefuseSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorBombDefuseSolver defaultRoomProcessor = new RoomProcessorBombDefuseSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/BDChamber.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/BDChamber.java new file mode 100644 index 00000000..aa6cb469 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/BDChamber.java @@ -0,0 +1,82 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers; + +import com.google.common.base.Predicate; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.util.BlockPos; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +@AllArgsConstructor +@Data +public class BDChamber { + private DungeonRoom room; + private OffsetPointSet chamberBlocks; + + private boolean isLeft; + private int level; + + private ChamberProcessor processor; + + // for whatever's sake, 6: z, 9: x. Starts from botoom right, left, then up + + public OffsetPoint getOffsetPoint(int x, int z) { + return chamberBlocks.getOffsetPointList().get(z * 9 + x); + } + + public BlockPos getBlockPos(int x, int y, int z) { + return getOffsetPoint(x,z).getBlockPos(room).add(0,y,0); + } + + public IBlockState getBlock(int x, int y, int z) { + BlockPos pos = getBlockPos(x,y,z); + return room.getContext().getWorld().getBlockState(pos); + } + + public boolean isWithinAbsolute(int x, int y, int z) { + return isWithinAbsolute(new BlockPos(x,68,z)); + } + public boolean isWithinAbsolute(BlockPos pos) { + return chamberBlocks.getOffsetPointList().contains(new OffsetPoint(room, new BlockPos(pos.getX(), 68, pos.getZ()))); + } + + + public <T extends Entity> T getEntityAt(Class<T> entity, int x, int y, int z) { + final BlockPos pos = getBlockPos(x,y,z); + return getEntityAt(entity, pos); + } + public <T extends Entity> T getEntityAt(Class<T> entity, final BlockPos pos) { + List<T> entities = room.getContext().getWorld().getEntities(entity, new Predicate<T>() { + @Override + public boolean apply(@Nullable T input) { + return input.getPosition().equals(pos); + } + }); + if (entities.size() == 0) return null; + return entities.get(0); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/BombDefuseChamberGenerator.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/BombDefuseChamberGenerator.java new file mode 100644 index 00000000..21cebf0c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/BombDefuseChamberGenerator.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; + +public interface BombDefuseChamberGenerator { + boolean match(BDChamber left, BDChamber right); + + String getName(); + + ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver); + ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver); +}
\ No newline at end of file diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/ChamberProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/ChamberProcessor.java new file mode 100644 index 00000000..95c33a8d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/ChamberProcessor.java @@ -0,0 +1,27 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers; + +import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessor; +import net.minecraft.nbt.NBTTagCompound; + +public interface ChamberProcessor extends RoomProcessor { + void onDataRecieve(NBTTagCompound compound); + String getName(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/DummyDefuseChamberProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/DummyDefuseChamberProcessor.java new file mode 100644 index 00000000..1736f094 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/DummyDefuseChamberProcessor.java @@ -0,0 +1,32 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; + +public class DummyDefuseChamberProcessor extends GeneralDefuseChamberProcessor { + public DummyDefuseChamberProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + } + + @Override + public String getName() { + return "dummy"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/GeneralDefuseChamberProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/GeneralDefuseChamberProcessor.java new file mode 100644 index 00000000..70c0c31f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/GeneralDefuseChamberProcessor.java @@ -0,0 +1,137 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers; + +import kr.syeyoung.dungeonsguide.events.BlockUpdateEvent; +import kr.syeyoung.dungeonsguide.events.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +@Getter +public abstract class GeneralDefuseChamberProcessor implements ChamberProcessor{ + private final RoomProcessorBombDefuseSolver solver; + private final BDChamber chamber; + + public GeneralDefuseChamberProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + this.solver = solver; + this.chamber = chamber; + } + + + @Override + public void onDataRecieve(NBTTagCompound compound) { + + } + + @Override + public void tick() { + + } + + @Override + public void drawScreen(float partialTicks) { + + } + + @Override + public void drawWorld(float partialTicks) { + + } + + @Override + public void chatReceived(IChatComponent chat) { + + } + + @Override + public void onEntityDeath(LivingDeathEvent deathEvent) { + + } + + @Override + public void actionbarReceived(IChatComponent chat) { + + } + @Override + public void onBlockUpdate(BlockUpdateEvent blockUpdateEvent) { + + } + + @Override + public boolean readGlobalChat() { + return false; + } + + @Override + public void onPostGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) { + + } + + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + + } + + protected void drawPressKey() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + String str = "Press "+ GameSettings.getKeyDisplayString(FeatureRegistry.SOLVER_BOMBDEFUSE.<Integer>getParameter("key").getValue()) + " to save and send solution"; + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(str, (sr.getScaledWidth() - fr.getStringWidth(str)) / 2, (sr.getScaledHeight() - fr.FONT_HEIGHT) / 2, 0xFFFFFFFF); + } + + @Override + public void onKeybindPress(KeyBindPressedEvent keyInputEvent) { + if (keyInputEvent.getKey() == FeatureRegistry.SOLVER_BOMBDEFUSE.<Integer>getParameter("key").getValue()) { + if (!getChamber().isWithinAbsolute(Minecraft.getMinecraft().thePlayer.getPosition())) { + return; + } + onSendData(); + } + } + + @Override + public void onInteract(PlayerInteractEntityEvent event) { + + } + + @Override + public void onInteractBlock(PlayerInteractEvent event) { + + } + + public void onSendData() {} +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/arrow/ArrowLeftProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/arrow/ArrowLeftProcessor.java new file mode 100644 index 00000000..70792c4e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/arrow/ArrowLeftProcessor.java @@ -0,0 +1,138 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.arrow; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; + +import java.util.HashMap; +import java.util.Map; + +public class ArrowLeftProcessor extends GeneralDefuseChamberProcessor { + public ArrowLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + for (int i = 0; i < 9; i++) { + grid[i] = chamber.getBlockPos(7,1 + (i / 3),1 + (i % 3)); + } + } + + @Override + public String getName() { + return "arrowLeft"; + } + + + private int answer = -1; + private final int[] answers = new int[9]; + private final BlockPos[] grid = new BlockPos[9]; + @Override + public void tick() { + super.tick(); + if (answer != -1) return; + for (int i = 0; i < 9; i++) + answers[i] = match(getChamber().getEntityAt(EntityArmorStand.class, grid[i].add(0, -1, 0))); + + answer = 0; + for (int i =0; i < 9; i++) { + answer = answer * 10 + answers[i]; + } + } + + @Override + public void drawScreen(float partialTicks) { + if (answer == -1) return; + drawPressKey(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + + if (answer == -1) return; + for (int i = 0; i < 9; i++) { + BlockPos pos = grid[i]; + int direction = answers[i]; + String charac = arrows.get(direction); + + RenderUtils.drawTextAtWorld(charac, pos.getX()+ 0.5f, pos.getY()+ 0.5f, pos.getZ()+ 0.5f, 0xFFFFFFFF, 0.05F, false, false, partialTicks); + } + } + + @Override + public void onSendData() { + if (answer == -1) return; + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 3); + nbt.setInteger("b", answer); + getSolver().communicate(nbt); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (3 == compound.getByte("a")) { + answer = compound.getInteger("b"); + for (int i = 8; i >= 0; i--) { + answers[i] = answer % 10; + answer = answer / 10; + } + answer = compound.getInteger("b"); + } + } + + private int match(EntityArmorStand armorStand) { + if (armorStand == null) return -1; + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return !integers.containsKey(str) ? -1 : integers.get(str); + } + + private static final BiMap<String, Integer> integers = HashBiMap.create(8); + private static final Map<Integer, String> arrows = new HashMap<Integer, String>(); + { + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDczZTFmZTBmZmNkNTQ2YzIxYjYzZWFhOTEwYWI1YzkzMTMyYTY0ZTY0NDE3OWZjY2FhMjFkYzhiYzY2MCJ9fX0=", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNThmZTI1MWE0MGU0MTY3ZDM1ZDA4MWMyNzg2OWFjMTUxYWY5NmI2YmQxNmRkMjgzNGQ1ZGM3MjM1ZjQ3NzkxZCJ9fX0=", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTc3ZWM0NGZiNzUwM2RlNmFmZTNiZGQ3ZTU4M2M3YjkzOTc5ZjU5ZjZkNjM0YjZiNmE1YWY3ZjNhMWM1ODUxNSJ9fX0=", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjJmM2EyZGZjZTBjM2RhYjdlZTEwZGIzODVlNTIyOWYxYTM5NTM0YThiYTI2NDYxNzhlMzdjNGZhOTNiIn19fQ==", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGUxY2U5YzBkMzMyMzZmOTkyMWQyMmM0ZWM0YmY1MDkyMzdhZWY2NzZiNWQxZDJiYWNjOTNmNWE4MTk0ODAifX19", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWI3Y2U2ODNkMDg2OGFhNDM3OGFlYjYwY2FhNWVhODA1OTZiY2ZmZGFiNmI1YWYyZDEyNTk1ODM3YTg0ODUzIn19fQ==", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTI2NTFlY2QzNzgwY2Y2ZTQ1MWVjYWNjZGVlNjk3MTVjMDhjYWU3Y2Q0NTA5MDg0NDYyY2RjZDk2M2E2YjMyMiJ9fX0=", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmIwZjZlOGFmNDZhYzZmYWY4ODkxNDE5MWFiNjZmMjYxZDY3MjZhNzk5OWM2MzdjZjJlNDE1OWZlMWZjNDc3In19fQ==", 8); + + arrows.put(0, "?"); + arrows.put(1, "↖"); + arrows.put(2, "↑"); + arrows.put(3, "↗"); + arrows.put(4, "→"); + arrows.put(5, "↘"); + arrows.put(6, "↓"); + arrows.put(7, "↙"); + arrows.put(8, "←"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/arrow/ArrowProcessorMatcher.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/arrow/ArrowProcessorMatcher.java new file mode 100644 index 00000000..8ab6fd64 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/arrow/ArrowProcessorMatcher.java @@ -0,0 +1,52 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.arrow; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class ArrowProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return left.getBlock(8,1,1).getBlock() == Blocks.planks && + left.getBlock(8,1,2).getBlock() == Blocks.planks && + left.getBlock(8,1,3).getBlock() == Blocks.planks && + right.getBlock(0,1,1).getBlock() == Blocks.planks && + right.getBlock(0,1,2).getBlock() == Blocks.planks && + right.getBlock(0,1,3).getBlock() == Blocks.planks; + } + + @Override + public String getName() { + return "arrowMatch"; + } + + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new ArrowLeftProcessor(solver, left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new ArrowRightProcessor(solver, right); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/arrow/ArrowRightProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/arrow/ArrowRightProcessor.java new file mode 100644 index 00000000..cc87315f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/arrow/ArrowRightProcessor.java @@ -0,0 +1,126 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.arrow; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; + +import java.util.HashMap; +import java.util.Map; + +public class ArrowRightProcessor extends GeneralDefuseChamberProcessor { + public ArrowRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + for (int i = 0; i < 9; i++) { + grid[i] = chamber.getBlockPos(1,1 + (i / 3),1 + (2 - (i % 3))); + } + + center = chamber.getBlockPos(4,4,4); + } + + @Override + public String getName() { + return "arrowRight"; + } + + + private int answer = -1; + private final int[] correctAnswers = new int[9]; + private final int[] currentAnswers = new int[9]; + private final BlockPos[] grid = new BlockPos[9]; + private final BlockPos center; + @Override + public void tick() { + super.tick(); + for (int i = 0; i < 9; i++) + currentAnswers[i] = match(getChamber().getEntityAt(EntityArmorStand.class, grid[i].add(0, -1, 0))); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + + RenderUtils.drawTextAtWorld(answer == -1 ? "Answer not received yet. Visit left room to obtain solution" : "" , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + for (int i = 0; i < 9; i++) { + BlockPos pos = grid[i]; + int direction = correctAnswers[i]; + int direction2 = currentAnswers[i]; + String charac = arrows.get(direction); + String car2 = arrows.get(direction2); + + RenderUtils.drawTextAtWorld(car2, pos.getX()+ 0.5f, pos.getY()+ 0.6f, pos.getZ()+ 0.5f, direction == direction2 ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(charac, pos.getX()+ 0.5f, pos.getY()+ 0.2f, pos.getZ()+ 0.5f, 0xFFFFFF00, 0.03F, false, false, partialTicks); + } + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (3 == compound.getByte("a")) { + answer = compound.getInteger("b"); + for (int i = 8; i >= 0; i--) { + correctAnswers[i] = answer % 10; + answer = answer / 10; + } + answer = compound.getInteger("b"); + } + } + + private int match(EntityArmorStand armorStand) { + if (armorStand == null) return -1; + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return !integers.containsKey(str) ? -1 : integers.get(str); + } + + private static final BiMap<String, Integer> integers = HashBiMap.create(8); + private static final Map<Integer, String> arrows = new HashMap<Integer, String>(); + { + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY1NDI2YTMzZGY1OGI0NjVmMDYwMWRkOGI5YmVjMzY5MGIyMTkzZDFmOTUwM2MyY2FhYjc4ZjZjMjQzOCJ9fX0=", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzA0MGZlODM2YTZjMmZiZDJjN2E5YzhlYzZiZTUxNzRmZGRmMWFjMjBmNTVlMzY2MTU2ZmE1ZjcxMmUxMCJ9fX0=", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTBlMGE0ZDQ4Y2Q4MjlhNmQ1ODY4OTA5ZDY0M2ZhNGFmZmQzOWU4YWU2Y2FhZjZlYzc5NjA5Y2Y3NjQ5YjFjIn19fQ==", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTliZjMyOTJlMTI2YTEwNWI1NGViYTcxM2FhMWIxNTJkNTQxYTFkODkzODgyOWM1NjM2NGQxNzhlZDIyYmYifX19", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzVjYmRiMjg5OTFhMTZlYjJjNzkzNDc0ZWY3ZDBmNDU4YTVkMTNmZmZjMjgzYzRkNzRkOTI5OTQxYmIxOTg5In19fQ==", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzQzNzM0NmQ4YmRhNzhkNTI1ZDE5ZjU0MGE5NWU0ZTc5ZGFlZGE3OTVjYmM1YTEzMjU2MjM2MzEyY2YifX19", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzU0Y2U4MTU3ZTcxZGNkNWI2YjE2NzRhYzViZDU1NDkwNzAyMDI3YzY3NWU1Y2RjZWFjNTVkMmZiYmQ1YSJ9fX0=", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ2OWUwNmU1ZGFkZmQ4NGU1ZjNkMWMyMTA2M2YyNTUzYjJmYTk0NWVlMWQ0ZDcxNTJmZGM1NDI1YmMxMmE5In19fQ==", 8); + + + arrows.put(0, "?"); + arrows.put(1, "↖"); + arrows.put(2, "↑"); + arrows.put(3, "↗"); + arrows.put(4, "→"); + arrows.put(5, "↘"); + arrows.put(6, "↓"); + arrows.put(7, "↙"); + arrows.put(8, "←"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/bugged/ImpossibleMatcher.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/bugged/ImpossibleMatcher.java new file mode 100644 index 00000000..a7ef6e13 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/bugged/ImpossibleMatcher.java @@ -0,0 +1,47 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.bugged; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class ImpossibleMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return left.getBlock(1,1,1).getBlock() == Blocks.barrier; + } + + @Override + public String getName() { + return "buggedMazeMatcher"; + } + + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return null; + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return null; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/color/ColorLeftProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/color/ColorLeftProcessor.java new file mode 100644 index 00000000..64bd2add --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/color/ColorLeftProcessor.java @@ -0,0 +1,230 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.color; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +import java.util.HashMap; +import java.util.Map; + +public class ColorLeftProcessor extends GeneralDefuseChamberProcessor { + public ColorLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + center = chamber.getBlockPos(4,6,4); + b1p = chamber.getBlockPos(1,1,4); + b2p = chamber.getBlockPos(4,1,4); + b3p = chamber.getBlockPos(7,1,4); + } + + private final BlockPos center; + + private Block w1, w2, w3, c1, c2, c3; + private final BlockPos b1p; + private final BlockPos b2p; + private final BlockPos b3p; + private int s1, s2, s3; + private int s1t, s2t, s3t; + private boolean solutionBuilt; + + @Override + public String getName() { + return "colorRight"; + } + + @Override + public void tick() { + super.tick(); + if (solutionBuilt) return; + World w = getChamber().getRoom().getContext().getWorld(); + if ((c1 = w.getBlockState(b1p).getBlock()) == w1 && s1t < 7) { + int semi = match(getChamber().getEntityAt(EntityArmorStand.class,b1p.add(0, 1, 0))); + if (s1 == semi) { + s1t++; + } else { + s1 = semi; + s1t = 0; + } + } + if ((c2 = w.getBlockState(b2p).getBlock()) == w2 && s2t < 7) { + int semi = match(getChamber().getEntityAt(EntityArmorStand.class,b2p.add(0, 2, 0))); + if (s2 == semi) { + s2t++; + } else { + s2 = semi; + s2t = 0; + } + } + if ((c3 =w.getBlockState(b3p).getBlock()) == w3 && s3t < 7) { + int semi = match(getChamber().getEntityAt(EntityArmorStand.class,b3p.add(0, 1, 0))); + if (s3== semi) { + s3t++; + } else { + s3 = semi; + s3t = 0; + } + } + + if (s1t > 5 && s2t > 5 && s3t > 5) { + solutionBuilt = true; + } + } + + @Override + public void drawScreen(float partialTicks) { + super.drawScreen(partialTicks); + if (solutionBuilt) + drawPressKey(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(w1 == null ? "Request Not Received Yet" : "Building- "+w1.getLocalizedName() +" / "+w2.getLocalizedName() +" / "+w3.getLocalizedName() , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + RenderUtils.drawTextAtWorld(w1 == null ? "null" : w1.getLocalizedName(), b1p.getX()+ 0.5f, b1p.getY() + 0.2f, b1p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(w2 == null ? "null" : w2.getLocalizedName(), b2p.getX()+ 0.5f, b2p.getY() + 0.2f, b2p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(w3 == null ? "null" : w3.getLocalizedName(), b3p.getX()+ 0.5f, b3p.getY() + 0.2f, b3p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(c1 == null ? "null" : c1.getLocalizedName(), b1p.getX()+ 0.5f, b1p.getY() + 0.6f, b1p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(c2 == null ? "null" : c2.getLocalizedName(), b2p.getX()+ 0.5f, b2p.getY() + 0.6f, b2p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(c3 == null ? "null" : c3.getLocalizedName(), b3p.getX()+ 0.5f, b3p.getY() + 0.6f, b3p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + if (FeatureRegistry.DEBUG.isEnabled()) { + RenderUtils.drawTextAtWorld(s1 + "", b1p.getX() + 0.5f, b1p.getY() + 2.6f, b1p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(s2 + "", b2p.getX() + 0.5f, b2p.getY() + 3.6f, b2p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(s3 + "", b3p.getX() + 0.5f, b3p.getY() + 2.6f, b3p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + } + + RenderUtils.drawTextAtWorld(colors.get(s1), b1p.getX()+ 0.5f, b1p.getY() + 2.2f, b1p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(colors.get(s2), b2p.getX()+ 0.5f, b2p.getY() + 3.2f, b2p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(colors.get(s3), b3p.getX()+ 0.5f, b3p.getY() + 2.2f, b3p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + if (FeatureRegistry.DEBUG.isEnabled()) { + RenderUtils.drawTextAtWorld(s1t + "", b1p.getX() + 0.5f, b1p.getY() + 1.5f, b1p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(s2t + "", b2p.getX() + 0.5f, b2p.getY() + 2f, b2p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(s3t + "", b3p.getX() + 0.5f, b3p.getY() + 1.5f, b3p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + } + } + + @Override + public void onSendData() { + super.onSendData(); + if (!solutionBuilt) return; + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 7); + int answer = s1 * 10000 + s2 * 100 + s3; + nbt.setInteger("b", answer); + getSolver().communicate(nbt); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (6 == compound.getByte("a")) { + w1 = Block.getBlockById(compound.getByte("f")); + w2 = Block.getBlockById(compound.getByte("s")); + w3 = Block.getBlockById(compound.getByte("t")); + solutionBuilt = false; + s1 = s2 = s3 = s1t = s2t = s3t =0; + } + } + + private byte match(EntityArmorStand armorStand) { + if (armorStand == null) { + return 0; + } + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return (byte) (!integers.containsKey(str) ? 0 : integers.get(str)); + } + + private static final Map<String, Integer> integers = new HashMap<String, Integer>(); + private static final BiMap<Integer, String> colors = HashBiMap.create(); + static { + colors.put(0, "?"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2YzZTQwNjI5MTE3NGQyNGNkZjBmOTUzZjhhMTc0YTgyYmIzNDg5ZGNlOGY2NzlhNDQzZWYxYWFlMDE2OTA2MSJ9fX0=", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWE4MWZjYjUxYmUyYTlmODliMWFkYzlkODcyMzliYTQyOWQ2MzVmYmUwMWIzN2VjMzI5MTY0ODg3YmY2NjViIn19fQ==", 1); + colors.put(1, "blue"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2FiMDI2M2JkZDc2ZjNlNDE4ZGJhNWJmNDgxYjkyMWNlZDM5N2Q4YjhhMzRhNTU2MWZiN2JlYWE0NmVjZTEifX19", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2ZhNGRkYTZkMTlhMWZlMmQ5ODhkNjVkZWM1MzQyOTUwNTMwODE2NmM5MDY3YjY4YTQ3NzBjYTVjNDM2Y2Y5NCJ9fX0=", 2); + colors.put(2, "black"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDg0Njg0MzQ0YWUwOTg1MjlmYzk0MWFhODRlMTk1YmRjYTM3NDhkNjlhY2ZlZTJiYWMxMzMyMTM1ZWRkOThjIn19fQ==", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTM1ODFjMmY5Y2YzNThkN2VkYzc4ZGQ2ZmQ0YjYyNTc1MDFiYzRlNjQ1NWUzM2ZhMGNhYWUyMDdjZjAzMjFhMiJ9fX0=", 3); + colors.put(3, "green"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTllNjkxN2YyZmI0ZWEwOGU3MTMyZGYzMDk2MWQyYjVjNTIzYWJiYTE5Y2U0M2Y4MzVmYzE0YzU2OGY0In19fQ==", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWRmMjFmNTMyMTIyNTY2YWY4OTNkYTI3ODgwYTFiNjA5NWMzNTcxMmYyOWEzNzhjZmVjYzdmZTJiMTMyOGFiNCJ9fX0=", 4); + colors.put(4, "gray"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODhlZmFkNzRiMjU0ZTU3Yzc5OTc2M2RjZWVlNDUxMWZhMmY4NWFlOWZhNTU2ZWFhOTdkNDViZjY3ZTBiNmIzIn19fQ==", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWZhZGY3NDFhYjc2Y2QzNjIwYWQxNjEzMDAyMDJkN2I1OWEzMzA1MWU1OTY3ZTRiNjE5NGJhYzQwYmIyODBmZiJ9fX0=", 5); + colors.put(5, "cyan"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzJlMzZmNmE2NTRkZTc0NTgzZDgwMzAxNzdhZDZlM2FjNjc1NWQ3NDM1ZDkxMjNlOGViZGZmNzRiMmQ5MGNiIn19fQ==", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJjYmQ5ZjQzNjE5YWI1Y2IxYjExZjkxY2IwM2U5NTVjNmZjNmM0NThhYmY4OWFiNjEwMzEzNDZhMDkwNjEyZSJ9fX0=", 6); + colors.put(6, "brown"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjFhZjQ2ZmViZDQ1YzBmNGQ4MWU4ZmExYjY2YjI3NWQ4OWUyNzJiMmFkNTVjOTc4NTUzYTk5YzczM2UxZmYifX19", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTYzZTY2NDZmMWMwZDQxZmQzYmY1NTg0YTFjZTA0NGY1YzQ2ZDU5ODI1OGRiNDYyMTYxMTc4NTlmNTdhZjE5NyJ9fX0=", 7); + colors.put(7, "light-blue"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDY3NDcwYTBjMThmNjg1MWU5MTQzNTM3MTllNzk1ODc3ZDI5YjMyNTJmN2U2YmQ0YTFiODY1NzY1YmQ3NGZlYiJ9fX0=", 8); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzc0NzJkNjA4ODIxZjQ1YTg4MDUzNzZlYzBjNmZmY2I3ODExNzgyOWVhNWY5NjAwNDFjMmEwOWQxMGUwNGNiNCJ9fX0=", 8); + colors.put(8, "lime"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWJiNDM4NmJjZGE4NGUzNTNjMzFkNzc4ZDNiMTFiY2QyNmZlYTQ5NGRkNjM0OTZiOGE4MmM3Yzc4YTRhZCJ9fX0=", 9); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjk3MDEyZWQ2YTkyYjA1ZWEwZjE5NDk1MDc0ODU0NGUwNzViYWEyODc4MWNhMzczZDFiMjdlMjhjMjY5NTNjIn19fQ==", 9); + colors.put(9, "magenta"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2JmNzc5N2EyNGE2YWY4NzVmNWM4MjcxYzViOGM0MjVlMTlmMzcyYTQxNWUwNTUyZmMyNDc3NjNmMjg1OWQxIn19fQ==", 10); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWRmMmViMjA1YTIzYzExOTZiM2VjZjIxZTY4YzA3NmI2OTZlNzYxNjNhYzhmYzRmYjlmNTMxOGMyYTVlNWIxYSJ9fX0=", 10); + colors.put(10, "orange"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNmJlY2ZiMzg3OTkzNmI4OTllNDIwYmZjZDNhNzRmOGExYmY5ZGQ1NGM1OGVjN2ZiOWY4MWQ5YTVkOTg4ZSJ9fX0=", 11); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDA4ODM2NTBlYTkyOWRiMGVhYmRmNWJjNzU1OTlkOGVmMDBkNzAzNDBjZDFjZTVlMDRhZDk1ZWY4ZWQ4M2I3MyJ9fX0=", 11); + colors.put(11, "pink"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmE5NGNiMjVkZTYyOGNhMzU5YjJmNmVhNWE4ODY4Y2JlMjY1OTVlZWRiMmJmZmI3NTA5NjdhZDFlZTE4NTAifX19", 12); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODllYzVhMzAyMjJkMDY1OWIwZGJlZTg0NGI4ZjUzZWFlNjJmZTk1YjRhMzQ0OGE5ZWY3OTBhN2FlZGIyOTZkOSJ9fX0=", 12); + colors.put(12, "purple"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODZkMzVhOTYzZDU5ODc4OTRiNmJjMjE0ZTMyOGIzOWNkMjM4MjQyNmZmOWM4ZTA4MmIwYjZhNmUwNDRkM2EzIn19fQ==", 13); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjk1M2IxMmEwOTQ2YjYyOWI0YzA4ODlkNDFmZDI2ZWQyNmZiNzI5ZDRkNTE0YjU5NzI3MTI0YzM3YmI3MGQ4ZCJ9fX0=", 13); + colors.put(13, "red"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTk4YmEyYjM3NGNmYzg5NDU0YzFiOGMzMmRiNDU4YTI3MDY3NTQzOWE0OTU0OTZjOTY3NzFjOTg5MTE2MTYyIn19fQ==", 14); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTUyODhkZGM5MTFhNzVmNzdjM2E1ZDMzNjM2NWE4ZjhiMTM5ZmE1MzkzMGI0YjZlZTEzOTg3NWM4MGNlMzY2YyJ9fX0=", 14); + colors.put(14, "light-gray"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2ZhZjRjMjlmMWU3NDA1ZjQ2ODBjNWMyYjAzZWY5Mzg0ZjFhZWNmZTI5ODZhZDUwMTM4YzYwNWZlZmZmMmYxNSJ9fX0=", 15); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDA4ZGY2MGM1MTA3NGVlZjI1NDRmZjM4Y2VhZDllMTY2NzVhZTQyNTE5MTYxMDUxODBlMWY4Y2UxOTdhYjNiYyJ9fX0=", 15); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTVhZDkzZDU2NTQ2ZjEyZDUzNTZlZmZjYmM2ZWM0Yzg3YmEyNDVkODFlMTY2MmM0YjgzMGY3ZDI5OGU5In19fQ==", 15); + colors.put(15, "white"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDRiMDM3OTRiOWIzZTNiNWQwN2UzYmU2OGI5NmFmODdkZjIxNWMzNzUyZTU0NzM2YzgwZjdkNTBiZDM0MzdhNCJ9fX0=", 16); + colors.put(16, "rainbow"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTkxMjdjYjdiZDNhOTg5ZDcyYzJlNWM0MjZlMWNjMTQ0NmI1ZTZkZTc0MTRkNDI3ODNmMmZlNmJhZGIxNzdkNCJ9fX0=", 17); + colors.put(17, "lilac"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTkxMjdjYjdiZDNhOTg5ZDcyYzJlNWM0MjZlMWNjMTQ0NmI1ZTZkZTc0MTRkNDI3ODNmMmZlNmJhZGIxNzdkNCJ9fX0=", 18); + colors.put(18, "dark-red"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzM4NmY5YjBiMWQ5ODc5YzNkYTMzYzdhOGNhMjQ0MGMxZTQxMWZlOTNjMjdjOWRiYmZmNTZiZDY5N2JiNzM3NSJ9fX0=", 19); + colors.put(19, "i-rainbow"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjdiYmQwYjI5MTFjOTZiNWQ4N2IyZGY3NjY5MWE1MWI4YjEyYzZmZWZkNTIzMTQ2ZDhhYzVlZjFiOGVlIn19fQ==", 20); + colors.put(20, "yellow"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/color/ColorProcessorMatcher.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/color/ColorProcessorMatcher.java new file mode 100644 index 00000000..ad0e01e1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/color/ColorProcessorMatcher.java @@ -0,0 +1,49 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.color; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class ColorProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return + right.getBlock(0,1,1).getBlock() == Blocks.stonebrick && + right.getBlock(0,1,2).getBlock() == Blocks.stonebrick && + right.getBlock(0,1,3).getBlock() == Blocks.stonebrick; + } + + @Override + public String getName() { + return "colorMatch"; + } + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new ColorLeftProcessor(solver,left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new ColorRightProcessor(solver,right); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/color/ColorRightProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/color/ColorRightProcessor.java new file mode 100644 index 00000000..93b82626 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/color/ColorRightProcessor.java @@ -0,0 +1,175 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.color; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; + +import java.util.HashMap; +import java.util.Map; + +public class ColorRightProcessor extends GeneralDefuseChamberProcessor { + public ColorRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + center = chamber.getBlockPos(4,4,4); + b1 = chamber.getBlockPos(1,3,3); + b2 = chamber.getBlockPos(1,3,2); + b3 = chamber.getBlockPos(1,3,1); + } + + private final BlockPos center; + + private final BlockPos b1; + private final BlockPos b2; + private final BlockPos b3; + private byte b1b = 0, b2b = 0, b3b = 0, c1b, c2b, c3b; + private int answer = -1; + + @Override + public String getName() { + return "colorRight"; + } + + @Override + public void tick() { + super.tick(); + c1b = match(getChamber().getEntityAt(EntityArmorStand.class,b1.add(0, -1, 0))); + c2b = match(getChamber().getEntityAt(EntityArmorStand.class,b2.add(0, -1, 0))); + c3b = match(getChamber().getEntityAt(EntityArmorStand.class,b3.add(0, -1, 0))); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(answer == -1 ? "Press "+ GameSettings.getKeyDisplayString(FeatureRegistry.SOLVER_BOMBDEFUSE.<Integer>getParameter("key").getValue()) +" to request solution" : "" , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld( colors.get((int) c1b), b1.getX()+ 0.5f, b1.getY()+0.6f, b1.getZ()+ 0.5f,c1b == b1b ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld( colors.get((int) c2b), b2.getX()+ 0.5f, b2.getY()+0.6f, b2.getZ()+ 0.5f,c2b == b2b ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld( colors.get((int) c3b), b3.getX()+ 0.5f, b3.getY()+0.6f, b3.getZ()+ 0.5f,c3b == b3b ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + + RenderUtils.drawTextAtWorld( colors.get((int) b1b), b1.getX()+ 0.5f, b1.getY()+0.2f, b1.getZ()+ 0.5f,0xFFFFFF00, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld( colors.get((int) b2b), b2.getX()+ 0.5f, b2.getY()+0.2f, b2.getZ()+ 0.5f,0xFFFFFF00, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld( colors.get((int) b3b), b3.getX()+ 0.5f, b3.getY()+0.2f, b3.getZ()+ 0.5f,0xFFFFFF00, 0.03F, false, false, partialTicks); + } + + @Override + public void onSendData() { + super.onSendData(); + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 6); + nbt.setByte("f", (byte) Block.getIdFromBlock(getChamber().getBlock(0,3,3).getBlock())); + nbt.setByte("s", (byte) Block.getIdFromBlock(getChamber().getBlock(0,3,2).getBlock())); + nbt.setByte("t", (byte) Block.getIdFromBlock(getChamber().getBlock(0,3,1).getBlock())); + getSolver().communicate(nbt); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (7 == compound.getByte("a")) { + answer = compound.getInteger("b"); + b3b = (byte) (answer / 10000); + b2b = (byte) ((answer % 10000) / 100); + b1b = (byte) (answer % 100); + + } + } + + private byte match(EntityArmorStand armorStand) { + if (armorStand == null) { + return 0; + } + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return (byte) (!integers.containsKey(str) ? 0 : integers.get(str)); + } + + private static final Map<String, Integer> integers = new HashMap<String, Integer>(); + private static final BiMap<Integer, String> colors = HashBiMap.create(); + static { + colors.put(0, "?"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2YzZTQwNjI5MTE3NGQyNGNkZjBmOTUzZjhhMTc0YTgyYmIzNDg5ZGNlOGY2NzlhNDQzZWYxYWFlMDE2OTA2MSJ9fX0=", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWE4MWZjYjUxYmUyYTlmODliMWFkYzlkODcyMzliYTQyOWQ2MzVmYmUwMWIzN2VjMzI5MTY0ODg3YmY2NjViIn19fQ==", 1); + colors.put(1, "blue"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2FiMDI2M2JkZDc2ZjNlNDE4ZGJhNWJmNDgxYjkyMWNlZDM5N2Q4YjhhMzRhNTU2MWZiN2JlYWE0NmVjZTEifX19", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2ZhNGRkYTZkMTlhMWZlMmQ5ODhkNjVkZWM1MzQyOTUwNTMwODE2NmM5MDY3YjY4YTQ3NzBjYTVjNDM2Y2Y5NCJ9fX0=", 2); + colors.put(2, "black"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDg0Njg0MzQ0YWUwOTg1MjlmYzk0MWFhODRlMTk1YmRjYTM3NDhkNjlhY2ZlZTJiYWMxMzMyMTM1ZWRkOThjIn19fQ==", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTM1ODFjMmY5Y2YzNThkN2VkYzc4ZGQ2ZmQ0YjYyNTc1MDFiYzRlNjQ1NWUzM2ZhMGNhYWUyMDdjZjAzMjFhMiJ9fX0=", 3); + colors.put(3, "green"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTllNjkxN2YyZmI0ZWEwOGU3MTMyZGYzMDk2MWQyYjVjNTIzYWJiYTE5Y2U0M2Y4MzVmYzE0YzU2OGY0In19fQ==", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWRmMjFmNTMyMTIyNTY2YWY4OTNkYTI3ODgwYTFiNjA5NWMzNTcxMmYyOWEzNzhjZmVjYzdmZTJiMTMyOGFiNCJ9fX0=", 4); + colors.put(4, "gray"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODhlZmFkNzRiMjU0ZTU3Yzc5OTc2M2RjZWVlNDUxMWZhMmY4NWFlOWZhNTU2ZWFhOTdkNDViZjY3ZTBiNmIzIn19fQ==", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWZhZGY3NDFhYjc2Y2QzNjIwYWQxNjEzMDAyMDJkN2I1OWEzMzA1MWU1OTY3ZTRiNjE5NGJhYzQwYmIyODBmZiJ9fX0=", 5); + colors.put(5, "cyan"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzJlMzZmNmE2NTRkZTc0NTgzZDgwMzAxNzdhZDZlM2FjNjc1NWQ3NDM1ZDkxMjNlOGViZGZmNzRiMmQ5MGNiIn19fQ==", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJjYmQ5ZjQzNjE5YWI1Y2IxYjExZjkxY2IwM2U5NTVjNmZjNmM0NThhYmY4OWFiNjEwMzEzNDZhMDkwNjEyZSJ9fX0=", 6); + colors.put(6, "brown"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjFhZjQ2ZmViZDQ1YzBmNGQ4MWU4ZmExYjY2YjI3NWQ4OWUyNzJiMmFkNTVjOTc4NTUzYTk5YzczM2UxZmYifX19", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTYzZTY2NDZmMWMwZDQxZmQzYmY1NTg0YTFjZTA0NGY1YzQ2ZDU5ODI1OGRiNDYyMTYxMTc4NTlmNTdhZjE5NyJ9fX0=", 7); + colors.put(7, "light-blue"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDY3NDcwYTBjMThmNjg1MWU5MTQzNTM3MTllNzk1ODc3ZDI5YjMyNTJmN2U2YmQ0YTFiODY1NzY1YmQ3NGZlYiJ9fX0=", 8); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzc0NzJkNjA4ODIxZjQ1YTg4MDUzNzZlYzBjNmZmY2I3ODExNzgyOWVhNWY5NjAwNDFjMmEwOWQxMGUwNGNiNCJ9fX0=", 8); + colors.put(8, "lime"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWJiNDM4NmJjZGE4NGUzNTNjMzFkNzc4ZDNiMTFiY2QyNmZlYTQ5NGRkNjM0OTZiOGE4MmM3Yzc4YTRhZCJ9fX0=", 9); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjk3MDEyZWQ2YTkyYjA1ZWEwZjE5NDk1MDc0ODU0NGUwNzViYWEyODc4MWNhMzczZDFiMjdlMjhjMjY5NTNjIn19fQ==", 9); + colors.put(9, "magenta"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2JmNzc5N2EyNGE2YWY4NzVmNWM4MjcxYzViOGM0MjVlMTlmMzcyYTQxNWUwNTUyZmMyNDc3NjNmMjg1OWQxIn19fQ==", 10); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWRmMmViMjA1YTIzYzExOTZiM2VjZjIxZTY4YzA3NmI2OTZlNzYxNjNhYzhmYzRmYjlmNTMxOGMyYTVlNWIxYSJ9fX0=", 10); + colors.put(10, "orange"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNmJlY2ZiMzg3OTkzNmI4OTllNDIwYmZjZDNhNzRmOGExYmY5ZGQ1NGM1OGVjN2ZiOWY4MWQ5YTVkOTg4ZSJ9fX0=", 11); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDA4ODM2NTBlYTkyOWRiMGVhYmRmNWJjNzU1OTlkOGVmMDBkNzAzNDBjZDFjZTVlMDRhZDk1ZWY4ZWQ4M2I3MyJ9fX0=", 11); + colors.put(11, "pink"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmE5NGNiMjVkZTYyOGNhMzU5YjJmNmVhNWE4ODY4Y2JlMjY1OTVlZWRiMmJmZmI3NTA5NjdhZDFlZTE4NTAifX19", 12); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODllYzVhMzAyMjJkMDY1OWIwZGJlZTg0NGI4ZjUzZWFlNjJmZTk1YjRhMzQ0OGE5ZWY3OTBhN2FlZGIyOTZkOSJ9fX0=", 12); + colors.put(12, "purple"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODZkMzVhOTYzZDU5ODc4OTRiNmJjMjE0ZTMyOGIzOWNkMjM4MjQyNmZmOWM4ZTA4MmIwYjZhNmUwNDRkM2EzIn19fQ==", 13); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjk1M2IxMmEwOTQ2YjYyOWI0YzA4ODlkNDFmZDI2ZWQyNmZiNzI5ZDRkNTE0YjU5NzI3MTI0YzM3YmI3MGQ4ZCJ9fX0=", 13); + colors.put(13, "red"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTk4YmEyYjM3NGNmYzg5NDU0YzFiOGMzMmRiNDU4YTI3MDY3NTQzOWE0OTU0OTZjOTY3NzFjOTg5MTE2MTYyIn19fQ==", 14); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTUyODhkZGM5MTFhNzVmNzdjM2E1ZDMzNjM2NWE4ZjhiMTM5ZmE1MzkzMGI0YjZlZTEzOTg3NWM4MGNlMzY2YyJ9fX0=", 14); + colors.put(14, "light-gray"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2ZhZjRjMjlmMWU3NDA1ZjQ2ODBjNWMyYjAzZWY5Mzg0ZjFhZWNmZTI5ODZhZDUwMTM4YzYwNWZlZmZmMmYxNSJ9fX0=", 15); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDA4ZGY2MGM1MTA3NGVlZjI1NDRmZjM4Y2VhZDllMTY2NzVhZTQyNTE5MTYxMDUxODBlMWY4Y2UxOTdhYjNiYyJ9fX0=", 15); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTVhZDkzZDU2NTQ2ZjEyZDUzNTZlZmZjYmM2ZWM0Yzg3YmEyNDVkODFlMTY2MmM0YjgzMGY3ZDI5OGU5In19fQ==", 15); + colors.put(15, "white"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDRiMDM3OTRiOWIzZTNiNWQwN2UzYmU2OGI5NmFmODdkZjIxNWMzNzUyZTU0NzM2YzgwZjdkNTBiZDM0MzdhNCJ9fX0=", 16); + colors.put(16, "rainbow"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTkxMjdjYjdiZDNhOTg5ZDcyYzJlNWM0MjZlMWNjMTQ0NmI1ZTZkZTc0MTRkNDI3ODNmMmZlNmJhZGIxNzdkNCJ9fX0=", 17); + colors.put(17, "lilac"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTkxMjdjYjdiZDNhOTg5ZDcyYzJlNWM0MjZlMWNjMTQ0NmI1ZTZkZTc0MTRkNDI3ODNmMmZlNmJhZGIxNzdkNCJ9fX0=", 18); + colors.put(18, "dark-red"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzM4NmY5YjBiMWQ5ODc5YzNkYTMzYzdhOGNhMjQ0MGMxZTQxMWZlOTNjMjdjOWRiYmZmNTZiZDY5N2JiNzM3NSJ9fX0=", 19); + colors.put(19, "i-rainbow"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjdiYmQwYjI5MTFjOTZiNWQ4N2IyZGY3NjY5MWE1MWI4YjEyYzZmZWZkNTIzMTQ2ZDhhYzVlZjFiOGVlIn19fQ==", 20); + colors.put(20, "yellow"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/creeper/CreeperLeftProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/creeper/CreeperLeftProcessor.java new file mode 100644 index 00000000..9b4b3d25 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/creeper/CreeperLeftProcessor.java @@ -0,0 +1,95 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.creeper; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; + +import java.awt.*; + +public class CreeperLeftProcessor extends GeneralDefuseChamberProcessor { + public CreeperLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + poses = new BlockPos[9]; + for (int i = 0; i < 9; i++) { + poses[i] = chamber.getBlockPos(3+(i%3), 1, 1+(i/3)); + } + } + + @Override + public String getName() { + return "creeperLeft"; + } + + + private int answer = -1; + private final BlockPos[] poses; + @Override + public void tick() { + super.tick(); + if (answer != -1) return; + answer = 0; + for (int i = 0; i < poses.length; i++) { + BlockPos pos = poses[i]; + if (getChamber().getRoom().getContext().getWorld().getBlockState(pos).getBlock() == Blocks.air) { + answer |= (1 << i); + } + } + } + + @Override + public void drawScreen(float partialTicks) { + if (answer == -1) return; + drawPressKey(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + for (int i = 0; i < 9; i++) { + if (((answer >> i) & 0x01) != 0) { + RenderUtils.highlightBlock(poses[i], new Color(255,0,0,100), partialTicks, false); + } else { + RenderUtils.highlightBlock(poses[i], new Color(0,255,0,100), partialTicks, false); + } + } + } + + @Override + public void onSendData() { + if (answer == -1) return; + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 2); + nbt.setInteger("b", answer); + getSolver().communicate(nbt); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (2 == compound.getByte("a")) { + answer = compound.getInteger("b"); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/creeper/CreeperProcessorMatcher.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/creeper/CreeperProcessorMatcher.java new file mode 100644 index 00000000..16a95e98 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/creeper/CreeperProcessorMatcher.java @@ -0,0 +1,52 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.creeper; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class CreeperProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + int airs = 0; + for (int x = 0; x < 3; x ++) { + for (int y = 0; y < 3; y++) { + if (right.getBlock(3 + x, 1, y + 1).getBlock() != Blocks.stone) return false; + } + } + return true; + } + + @Override + public String getName() { + return "creeperMatch"; + } + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new CreeperLeftProcessor(solver, left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new CreeperRightProcessor(solver, right); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/creeper/CreeperRightProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/creeper/CreeperRightProcessor.java new file mode 100644 index 00000000..0d99f2bb --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/creeper/CreeperRightProcessor.java @@ -0,0 +1,73 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.creeper; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; + +import java.awt.*; + +public class CreeperRightProcessor extends GeneralDefuseChamberProcessor { + public CreeperRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + poses = new BlockPos[9]; + for (int i = 0; i < 9; i++) { + poses[i] = chamber.getBlockPos(3+(i%3), 1, 1+(i/3)); + } + center = chamber.getBlockPos(4,4,4); + } + + @Override + public String getName() { + return "creeperRight"; + } + + + private int answer = -1; + private final BlockPos[] poses; + private final BlockPos center; + @Override + public void tick() { + super.tick(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(answer == -1 ? "Answer not received yet. Visit left room to obtain solution" : "" , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + if (answer != -1) { + for (int i = 0; i < 9; i++) { + if (((answer >> i) & 0x01) == 0) { + RenderUtils.highlightBlock(poses[i], new Color(0,255,0, 50), partialTicks, false); + } + } + } + } + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (2 == compound.getByte("a")) { + answer = compound.getInteger("b"); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathLeftProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathLeftProcessor.java new file mode 100644 index 00000000..009fba06 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathLeftProcessor.java @@ -0,0 +1,141 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.goldenpath; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class GoldenPathLeftProcessor extends GeneralDefuseChamberProcessor { + public GoldenPathLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + } + + @Override + public String getName() { + return "goldenPathLeft"; + } + + + // 1 up 2 right 3 down 4 left + private static final Point[] vectors = new Point[] { + new Point(0,1), + new Point(-1,0), + new Point(0, -1), + new Point(1, 0) + }; + + private final LinkedList<BlockPos> blocksolution = new LinkedList<BlockPos>(); + private String goldenPathsolution; + @Override + public void tick() { + super.tick(); + if (goldenPathsolution != null) return; + + List<Integer> solution = new ArrayList<Integer>(); + Set<BlockPos> visited = new HashSet<BlockPos>(); + BlockPos lastLoc = new BlockPos(4,0,0); + visited.add(lastLoc); + blocksolution.add(getChamber().getBlockPos(4,1,0)); + BlockPos target = new BlockPos(4,0,5); + while (!lastLoc.equals(target)) { + boolean solution2 = false; + for (int i =0; i<vectors.length; i++) { + BlockPos target2 = lastLoc.add(vectors[i].x, 0, vectors[i].y); + if (visited.contains(target2)) continue; + if (target2.getX() < 0 || target2.getZ() < 0 || target2.getX() > 8 || target2.getZ() > 5) continue; + + visited.add(target2); + if (getChamber().getBlock(target2.getX(), 0, target2.getZ()).getBlock() == Blocks.hardened_clay + || getChamber().getBlock(target2.getX(), 0, target2.getZ()).getBlock() == Blocks.stained_hardened_clay) { + lastLoc = target2; + + blocksolution.add(getChamber().getBlockPos(lastLoc.getX(), 1, lastLoc.getZ())); + solution.add(i); + solution2 = true; + break; + } + } + if (!solution2){ + return; + } + } + + goldenPathsolution = ""; + for (Integer i:solution) + goldenPathsolution += i; + } + + @Override + public void drawScreen(float partialTicks) { + if (goldenPathsolution == null) return; + drawPressKey(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawLines(blocksolution, new AColor(0,0,255,0), 1,partialTicks, false); + } + + @Override + public void onSendData() { + if (goldenPathsolution == null) return; + Minecraft.getMinecraft().thePlayer.sendChatMessage("/pc $DG-BDGP "+goldenPathsolution); + + ChatComponentText text = new ChatComponentText("$DG-BDGP "+goldenPathsolution); + for (RoomProcessorBombDefuseSolver.ChamberSet ch: getSolver().getChambers()) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) + ch.getLeft().getProcessor().chatReceived(text); + if (ch.getRight() != null && ch.getRight().getProcessor() != null) + ch.getRight().getProcessor().chatReceived(text); + } + } + + @Override + public void chatReceived(IChatComponent chat) { + super.chatReceived(chat); + if (chat.getFormattedText().contains("$DG-BDGP ")) { + String data = chat.getFormattedText().substring(chat.getFormattedText().indexOf("$DG-BDGP ")); + String actual = TextUtils.stripColor(data).trim().split(" ")[1].trim(); + + blocksolution.clear(); + BlockPos lastLoc = new BlockPos(4,0,0); + blocksolution.addFirst(getChamber().getBlockPos(4,1,0)); + for (Character c:actual.toCharArray()) { + int dir = Integer.parseInt(c+"") % 4; + lastLoc = lastLoc.add(vectors[dir].x, 0, vectors[dir].y); + blocksolution.add(getChamber().getBlockPos(lastLoc.getX(), 1, lastLoc.getZ())); + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathProcessorMatcher.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathProcessorMatcher.java new file mode 100644 index 00000000..241b8a62 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathProcessorMatcher.java @@ -0,0 +1,47 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.goldenpath; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class GoldenPathProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return left.getBlock(4,0,0).getBlock() == Blocks.hardened_clay + || left.getBlock(4,0,0).getBlock() == Blocks.stained_hardened_clay; + } + + @Override + public String getName() { + return "goldPath"; + } + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new GoldenPathLeftProcessor(solver, left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new GoldenPathRightProcessor(solver, right); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathRightProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathRightProcessor.java new file mode 100644 index 00000000..17f584c5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathRightProcessor.java @@ -0,0 +1,97 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.goldenpath; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.IChatComponent; +import net.minecraft.world.World; + +import java.awt.*; +import java.util.*; + +public class GoldenPathRightProcessor extends GeneralDefuseChamberProcessor { + public GoldenPathRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + center = chamber.getBlockPos(4,4,4); + } + + @Override + public String getName() { + return "goldenPathRight"; + } + + + private final BlockPos center; + // 1 up 2 right 3 down 4 left + private static final Point[] vectors = new Point[] { + new Point(0,1), + new Point(-1,0), + new Point(0, -1), + new Point(1, 0) + }; + + private final LinkedList<BlockPos> blocksolution = new LinkedList<BlockPos>(); + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(blocksolution.size() == 0 ? "Answer not received yet. Visit left room to obtain solution" : "" , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + RenderUtils.drawLines(blocksolution, new AColor(0,0,255,0),1, partialTicks, false); + + } + + @Override + public void chatReceived(IChatComponent chat) { + super.chatReceived(chat); + if (chat.getFormattedText().contains("$DG-BDGP ")) { + String data = chat.getFormattedText().substring(chat.getFormattedText().indexOf("$DG-BDGP")); + String actual = TextUtils.stripColor(data).trim().split(" ")[1].trim(); + + blocksolution.clear(); + BlockPos lastLoc = new BlockPos(4,0,0); + blocksolution.addFirst(getChamber().getBlockPos(4,1,0)); + for (Character c:actual.toCharArray()) { + int dir = Integer.parseInt(c+"") % 4; + lastLoc = lastLoc.add(vectors[dir].x, 0, vectors[dir].y); + blocksolution.add(getChamber().getBlockPos(lastLoc.getX(), 1, lastLoc.getZ())); + } + + World w = getChamber().getRoom().getContext().getWorld(); + for (int x = 0; x <9; x++) { + for (int z =0; z < 6; z++) { + BlockPos pos = getChamber().getBlockPos(x,1,z); + if (blocksolution.contains(pos)) { + w.setBlockState(pos, Blocks.light_weighted_pressure_plate.getDefaultState()); + } else { + w.setBlockState(pos, Blocks.wooden_pressure_plate.getDefaultState()); + } + } + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/maze/MazeLeftProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/maze/MazeLeftProcessor.java new file mode 100644 index 00000000..435b3ef4 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/maze/MazeLeftProcessor.java @@ -0,0 +1,80 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.maze; + +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; +import net.minecraft.util.MovingObjectPosition; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +public class MazeLeftProcessor extends GeneralDefuseChamberProcessor { + public MazeLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + } + + @Override + public String getName() { + return "mazeLeft"; + } + + + @Override + public void drawScreen(float partialTicks) { + if (Minecraft.getMinecraft().objectMouseOver == null ) return; + MovingObjectPosition pos = Minecraft.getMinecraft().objectMouseOver; + if (pos.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) return; + + BlockPos block = pos.getBlockPos(); + Block b = getChamber().getRoom().getContext().getWorld().getBlockState(block).getBlock(); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + String str = "Press "+ GameSettings.getKeyDisplayString(FeatureRegistry.SOLVER_BOMBDEFUSE.<Integer>getParameter("key").getValue()) + " to request open "+b.getLocalizedName(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(str, (sr.getScaledWidth() - fr.getStringWidth(str)) / 2, (sr.getScaledHeight() - fr.FONT_HEIGHT) / 2, 0xFFFFFFFF); + } + + @Override + public void onSendData() { + if (Minecraft.getMinecraft().objectMouseOver == null ) return; + MovingObjectPosition pos = Minecraft.getMinecraft().objectMouseOver; + if (pos.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) return; + + BlockPos block = pos.getBlockPos(); + Block b = getChamber().getRoom().getContext().getWorld().getBlockState(block).getBlock(); + + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 5); + nbt.setInteger("b", Block.getIdFromBlock(b)); + getSolver().communicate(nbt); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/maze/MazeProcessorMatcher.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/maze/MazeProcessorMatcher.java new file mode 100644 index 00000000..a5fe57bc --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/maze/MazeProcessorMatcher.java @@ -0,0 +1,47 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.maze; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class MazeProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return right.getBlock(1,0,1).getBlock() != Blocks.double_stone_slab && + left.getBlock(1,1,1).getBlock() != Blocks.barrier; + } + + @Override + public String getName() { + return "mazeMatch"; + } + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new MazeLeftProcessor(solver, left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new MazeRightProcessor(solver, right); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/maze/MazeRightProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/maze/MazeRightProcessor.java new file mode 100644 index 00000000..5fdf15b9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/maze/MazeRightProcessor.java @@ -0,0 +1,73 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.maze; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.HashMap; +import java.util.Map; + +public class MazeRightProcessor extends GeneralDefuseChamberProcessor { + public MazeRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + center = chamber.getBlockPos(4,4,4); + + for (int x = 0; x < 9; x++) { + for (int y =0; y< 6; y++) { + Block b = chamber.getBlock(x,0,y).getBlock(); + BlockPos pos = chamber.getBlockPos(x,0,y); + blockToBlockPosMap.put(b, pos); + } + } + } + + private final BlockPos center; + private final Map<Block, BlockPos> blockToBlockPosMap = new HashMap<Block, BlockPos>(); + @Override + public String getName() { + return "mazeRight"; + } + + + private Block latestRequest = null; + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(latestRequest == null ? "Request not received yet" : "Requested received "+latestRequest.getLocalizedName() , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + BlockPos pos = blockToBlockPosMap.get(latestRequest); + if (pos == null) return; + RenderUtils.highlightBlock(pos, new Color(0,255,0,100), partialTicks, false); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (5 == compound.getByte("a")) { + int latestRequestid = compound.getInteger("b"); + latestRequest = Block.getBlockById(latestRequestid); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/number/NumberLeftProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/number/NumberLeftProcessor.java new file mode 100644 index 00000000..2a2a42c5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/number/NumberLeftProcessor.java @@ -0,0 +1,125 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.number; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; + +public class NumberLeftProcessor extends GeneralDefuseChamberProcessor { + public NumberLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + d1p = chamber.getBlockPos(1,1,4); + d2p = chamber.getBlockPos(2,1,4); + d3p = chamber.getBlockPos(6,1,4); + d4p = chamber.getBlockPos(7,1,4); + } + + @Override + public String getName() { + return "numberLeft"; + } + + + private int answer = -1, d1, d2, d3 ,d4; + private final BlockPos d1p; + private final BlockPos d2p; + private final BlockPos d3p; + private final BlockPos d4p; + @Override + public void tick() { + super.tick(); + if (answer != -1) return; + d1 = match(getChamber().getEntityAt(EntityArmorStand.class,d1p)); + d2 = match(getChamber().getEntityAt(EntityArmorStand.class,d2p)); + d3 = match(getChamber().getEntityAt(EntityArmorStand.class,d3p)); + d4 = match(getChamber().getEntityAt(EntityArmorStand.class,d4p)); + if (d1 == -1 || d2 == -1 || d3 == -1 || d4 == -1) return; + + answer = d1 * 1000 + d2 * 100 + d3 * 10 + d4; + } + + @Override + public void drawScreen(float partialTicks) { + if (answer == -1) return; + drawPressKey(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(d1+"", d1p.getX()+ 0.5f, d1p.getY()+ 0.5f, d1p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d2+"", d2p.getX()+ 0.5f, d2p.getY()+ 0.5f, d2p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d3+"", d3p.getX()+ 0.5f, d3p.getY()+ 0.5f, d3p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d4+"", d4p.getX()+ 0.5f, d4p.getY()+ 0.5f, d4p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + } + + @Override + public void onSendData() { + if (answer == -1) return; + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 1); + nbt.setInteger("b", answer); + getSolver().communicate(nbt); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (1 == compound.getByte("a")) { + answer = compound.getInteger("b"); + d1 = answer / 1000; + d2 = (answer % 1000) / 100; + d3 = (answer % 100) / 10; + d4 = (answer % 10); + answer = d1 * 1000 + d2 * 100 + d3 * 10 + d4; + } + } + + private int match(EntityArmorStand armorStand) { + if (armorStand == null) return -1; + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return !integers.containsKey(str) ? -1 : integers.get(str); + } + + private static final BiMap<String, Integer> integers = HashBiMap.create(10); + { + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzFhOTQ2M2ZkM2M0MzNkNWUxZDlmZWM2ZDVkNGIwOWE4M2E5NzBiMGI3NGRkNTQ2Y2U2N2E3MzM0OGNhYWIifX19", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWNiNDE5ZDk4NGQ4Nzk2MzczYzk2NDYyMzNjN2EwMjY2NGJkMmNlM2ExZDM0NzZkZDliMWM1NDYzYjE0ZWJlIn19fQ==", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjhlYmFiNTdiNzYxNGJiMjJhMTE3YmU0M2U4NDhiY2QxNGRhZWNiNTBlOGY1ZDA5MjZlNDg2NGRmZjQ3MCJ9fX0=", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjJiZmNmYjQ4OWRhODY3ZGNlOTZlM2MzYzE3YTNkYjdjNzljYWU4YWMxZjlhNWE4YzhhYzk1ZTRiYTMifX19", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWY0ZWNmMTEwYjBhY2VlNGFmMWRhMzQzZmIxMzZmMWYyYzIxNjg1N2RmZGE2OTYxZGVmZGJlZTdiOTUyOCJ9fX0=", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjMzMWE2YTZmY2Q2OTk1YjYyMDg4ZDM1M2JmYjY4ZDliODlhZTI1ODMyNWNhZjNmMjg4NjQ2NGY1NGE3MzI5In19fQ==", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDRiYTZhYzA3ZDQyMjM3N2E4NTU3OTNmMzZkZWEyZWQyNDAyMjNmNTJmZDE2NDgxODE2MTJlY2QxYTBjZmQ1In19fQ==", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzYxYThhNjQxNDM3YmU5YWVhMjA3MjUzZGQzZjI1NDQwZDk1NGVhMmI1ODY2YzU1MmYzODZiMjlhYzRkMDQ5In19fQ==", 8); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTE5MjhlMWJmZDg2YTliNzkzOTdjNGNiNGI2NWVmOTlhZjQ5YjdkNWY3OTU3YWQ2MmMwYzY5OWE2MjJjZmJlIn19fQ==", 9); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTVhMjI0ODA3NjkzOTc4ZWQ4MzQzNTVmOWU1MTQ1ZjljNTZlZjY4Y2Y2ZjJjOWUxNzM0YTQ2ZTI0NmFhZTEifX19", 0); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/number/NumberProcessorMatcher.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/number/NumberProcessorMatcher.java new file mode 100644 index 00000000..4ea82f82 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/number/NumberProcessorMatcher.java @@ -0,0 +1,53 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.number; + +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class NumberProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return left.getBlock(1,1,4).getBlock() == Blocks.stone && + left.getBlock(2,1,4).getBlock() == Blocks.stone && + left.getBlock(6,1,4).getBlock() == Blocks.stone && + left.getBlock(7,1,4).getBlock() == Blocks.stone && + right.getBlock(1,1,4).getBlock() == Blocks.stone && + right.getBlock(2,1,4).getBlock() == Blocks.stone && + right.getBlock(6,1,4).getBlock() == Blocks.stone && + right.getBlock(7,1,4).getBlock() == Blocks.stone; + } + + @Override + public String getName() { + return "numberMatch"; + } + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new NumberLeftProcessor(solver, left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new NumberRightProcessor(solver, right); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/number/NumberRightProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/number/NumberRightProcessor.java new file mode 100644 index 00000000..673d4f22 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bombdefuse/chambers/number/NumberRightProcessor.java @@ -0,0 +1,114 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.number; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; + +public class NumberRightProcessor extends GeneralDefuseChamberProcessor { + public NumberRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + d1p = chamber.getBlockPos(1,1,4); + d2p = chamber.getBlockPos(2,1,4); + d3p = chamber.getBlockPos(6,1,4); + d4p = chamber.getBlockPos(7,1,4); + center = chamber.getBlockPos(4,4,4); + } + + @Override + public String getName() { + return "numberRight"; + } + + + private int answer = -1, d1, d2, d3 ,d4, a1, a2, a3, a4; + private final BlockPos d1p; + private final BlockPos d2p; + private final BlockPos d3p; + private final BlockPos d4p; + private final BlockPos center; + @Override + public void tick() { + super.tick(); + a1 = match(getChamber().getEntityAt(EntityArmorStand.class,d1p)); + a2 = match(getChamber().getEntityAt(EntityArmorStand.class,d2p)); + a3 = match(getChamber().getEntityAt(EntityArmorStand.class,d3p)); + a4 = match(getChamber().getEntityAt(EntityArmorStand.class,d4p)); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(a1+"", d1p.getX()+ 0.5f, d1p.getY()+ 0.6f, d1p.getZ()+ 0.5f, a1 == d1 ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(a2+"", d2p.getX()+ 0.5f, d2p.getY()+ 0.6f, d2p.getZ()+ 0.5f, a2 == d2 ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(a3+"", d3p.getX()+ 0.5f, d3p.getY()+ 0.6f, d3p.getZ()+ 0.5f, a3 == d3 ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(a4+"", d4p.getX()+ 0.5f, d4p.getY()+ 0.6f, d4p.getZ()+ 0.5f, a4 == d4 ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(answer == -1 ? "Answer not received yet. Visit left room to obtain solution" : ("Solution: "+answer) , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d1+"", d1p.getX()+ 0.5f, d1p.getY()+ 0.2f, d1p.getZ()+ 0.5f, 0xFFFFFF00, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d2+"", d2p.getX()+ 0.5f, d2p.getY()+ 0.2f, d2p.getZ()+ 0.5f, 0xFFFFFF00, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d3+"", d3p.getX()+ 0.5f, d3p.getY()+ 0.2f, d3p.getZ()+ 0.5f, 0xFFFFFF00, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d4+"", d4p.getX()+ 0.5f, d4p.getY()+ 0.2f, d4p.getZ()+ 0.5f, 0xFFFFFF00, 0.03F, false, false, partialTicks); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (1 == compound.getByte("a")) { + answer = compound.getInteger("b"); + d1 = answer / 1000; + d2 = (answer % 1000) / 100; + d3 = (answer % 100) / 10; + d4 = (answer % 10); + answer = d4 * 1000 + d3 * 100 + d2 * 10 + d1; + } + } + + private int match(EntityArmorStand armorStand) { + if (armorStand == null) { + return -1; + } + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return !integers.containsKey(str) ? -1 : integers.get(str); + } + + private static final BiMap<String, Integer> integers = HashBiMap.create(10); + { + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzFiYzJiY2ZiMmJkMzc1OWU2YjFlODZmYzdhNzk1ODVlMTEyN2RkMzU3ZmMyMDI4OTNmOWRlMjQxYmM5ZTUzMCJ9fX0=", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGNkOWVlZWU4ODM0Njg4ODFkODM4NDhhNDZiZjMwMTI0ODVjMjNmNzU3NTNiOGZiZTg0ODczNDE0MTk4NDcifX19", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWQ0ZWFlMTM5MzM4NjBhNmRmNWU4ZTk1NTY5M2I5NWE4YzNiMTVjMzZiOGI1ODc1MzJhYzA5OTZiYzM3ZTUifX19", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDJlNzhmYjIyNDI0MjMyZGMyN2I4MWZiY2I0N2ZkMjRjMWFjZjc2MDk4NzUzZjJkOWMyODU5ODI4N2RiNSJ9fX0=", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNmQ1N2UzYmM4OGE2NTczMGUzMWExNGUzZjQxZTAzOGE1ZWNmMDg5MWE2YzI0MzY0M2I4ZTU0NzZhZTIifX19", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzM0YjM2ZGU3ZDY3OWI4YmJjNzI1NDk5YWRhZWYyNGRjNTE4ZjVhZTIzZTcxNjk4MWUxZGNjNmIyNzIwYWIifX19", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNmRiNmViMjVkMWZhYWJlMzBjZjQ0NGRjNjMzYjU4MzI0NzVlMzgwOTZiN2UyNDAyYTNlYzQ3NmRkN2I5In19fQ==", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTkxOTQ5NzNhM2YxN2JkYTk5NzhlZDYyNzMzODM5OTcyMjI3NzRiNDU0Mzg2YzgzMTljMDRmMWY0Zjc0YzJiNSJ9fX0=", 8); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTY3Y2FmNzU5MWIzOGUxMjVhODAxN2Q1OGNmYzY0MzNiZmFmODRjZDQ5OWQ3OTRmNDFkMTBiZmYyZTViODQwIn19fQ==", 9); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMGViZTdlNTIxNTE2OWE2OTlhY2M2Y2VmYTdiNzNmZGIxMDhkYjg3YmI2ZGFlMjg0OWZiZTI0NzE0YjI3In19fQ==", 0); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessor.java new file mode 100644 index 00000000..657ab0d0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessor.java @@ -0,0 +1,33 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessor; + +import java.util.List; + +public interface BossfightProcessor extends RoomProcessor { + List<String> getPhases(); + String getCurrentPhase(); + List<String> getNextPhases(); + + List<HealthData> getHealths(); + + String getBossName(); +}
\ No newline at end of file diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorBonzo.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorBonzo.java new file mode 100644 index 00000000..8c8a3408 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorBonzo.java @@ -0,0 +1,85 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraftforge.event.entity.living.LivingEvent; + +import java.util.ArrayList; +import java.util.List; + +public class BossfightProcessorBonzo extends GeneralBossfightProcessor { + public BossfightProcessorBonzo() { + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("start") + .signatureMsg("§r§c[BOSS] Bonzo §r§f: Gratz for making it this far, but I’m basically unbeatable.§r") + .nextPhase("fight-1").build() + ); + + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-1") + .signatureMsg("§r§c[BOSS] Bonzo §r§f: I can summon lots of undead! Check this out.§r") + .nextPhase("first-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("first-defeat") + .signatureMsg("§r§c[BOSS] Bonzo §r§f: Oh I'm dead!§r").signatureMsg("§r§c[BOSS] Bonzo §r§f: Hoho, looks like you killed me!§r") + .nextPhase("fight-2").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-2") + .signatureMsg("§r§c[BOSS] Bonzo §r§f: Sike§r").signatureMsg("§r§c[BOSS] Bonzo §r§f: I can revive myself and become much stronger!§r") + .nextPhase("final-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("final-defeat") + .signatureMsg("§r§c[BOSS] Bonzo §r§f: Alright, maybe I'm just weak after all..§r").build() + ); + } + + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + long health = 0; + if (bonzoStand != null) { + String name = TextUtils.stripColor(bonzoStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Bonzo", (int) health,250000 , this.getCurrentPhase().startsWith("fight-"))); + return healths; + } + + @Override + public String getBossName() { + return "Bonzo"; + } + + private EntityArmorStand bonzoStand; + @Override + // §e﴾ §c§lBonzo§r §e71k§c❤ §e﴿ + // §e﴾ §c§lBonzo§r §a250k§c❤ §e﴿ + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving.getName().startsWith("§e﴾ §c§lBonzo§r ") && updateEvent.entityLiving instanceof EntityArmorStand) { + bonzoStand = (EntityArmorStand) updateEvent.entityLiving; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorLivid.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorLivid.java new file mode 100644 index 00000000..25570d10 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorLivid.java @@ -0,0 +1,90 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import lombok.Getter; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraftforge.event.entity.living.LivingEvent; + +import java.util.*; + +@Getter +public class BossfightProcessorLivid extends GeneralBossfightProcessor { + private String realLividName; + private String prefix; + private EntityOtherPlayerMP realLivid; + + private final Set<String> knownLivids = new HashSet<String>(); + + private boolean isMasterMode; + + public BossfightProcessorLivid(boolean isMasterMode) { + addPhase(PhaseData.builder().phase("start").build()); + this.isMasterMode = isMasterMode; + } + private static final Map<String, String> lividColorPrefix = new HashMap<String, String>() {{ + put("Vendetta", "§f"); + put("Crossed", "§d"); + put("Hockey", "§c"); + put("Doctor", "§7"); + put("Frog", "§2"); + put("Smile", "§a"); + put("Scream", "§1"); + put("Purple", "§5"); + put("Arcade", "§e"); + }}; + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving.getName().endsWith("Livid") && updateEvent.entityLiving instanceof EntityOtherPlayerMP) { + if (!knownLivids.contains(updateEvent.entityLiving.getName())) { + knownLivids.add(updateEvent.entityLiving.getName()); + realLividName = updateEvent.entityLiving.getName(); + realLivid = (EntityOtherPlayerMP) updateEvent.entityLiving; + prefix = lividColorPrefix.get(realLividName.split(" ")[0]); + } else if (realLividName.equalsIgnoreCase(updateEvent.entityLiving.getName())) { + realLivid = (EntityOtherPlayerMP) updateEvent.entityLiving; + } + } else if (updateEvent.entityLiving.getName().startsWith(prefix+"﴾ ") && updateEvent.entityLiving instanceof EntityArmorStand) { + lividStand = (EntityArmorStand) updateEvent.entityLiving; + } + } + private EntityArmorStand lividStand; + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + long health = 0; + if (lividStand != null) { + try { + String name = TextUtils.stripColor(lividStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } catch (Exception e) {e.printStackTrace();} + } + healths.add(new HealthData(realLividName == null ? "unknown" : realLividName, (int) health,isMasterMode ? 600000000 : 7000000 , true)); + return healths; + } + + @Override + public String getBossName() { + return realLividName == null ? "Livid" : realLividName; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorNecron.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorNecron.java new file mode 100644 index 00000000..16fdb0fa --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorNecron.java @@ -0,0 +1,77 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bossfight; + +import net.minecraft.entity.boss.BossStatus; + +import java.util.ArrayList; +import java.util.List; + +public class BossfightProcessorNecron extends GeneralBossfightProcessor { + // \A7 to § + public BossfightProcessorNecron() { + addPhase(PhaseData.builder() + .phase("crystals") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cFinally, I heard so much about you. The Eye likes you very much.§r") + .nextPhase("laser-attack").nextPhase("lost").build() + ); + addPhase(PhaseData.builder() + .phase("laser-attack") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cYou tricked me!§r") + .nextPhase("fight-1").nextPhase("lost").build() + ); + addPhase(PhaseData.builder() + .phase("fight-1") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cFINE! LET'S MOVE TO SOMEWHERE ELSE!!§r") + .nextPhase("terminals").nextPhase("lost").build() + ); + addPhase(PhaseData.builder() + .phase("terminals") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cCRAP!! IT BROKE THE FLOOR!§r") + .nextPhase("fight-2").nextPhase("lost").build() + ); + addPhase(PhaseData.builder() + .phase("fight-2") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cTHAT'S IT YOU HAVE DONE IT!§r") + .nextPhase("won").nextPhase("lost").build() + ); + addPhase(PhaseData.builder() + .phase("won") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cAll this, for nothing...§r").build() + ); + addPhase(PhaseData.builder() + .phase("lost") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cFINALLY! This took way too long.§r").build() + ); + } + + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + int maxHealth = 1_000_000_000; + healths.add(new HealthData("Necron", (int) (BossStatus.healthScale * maxHealth),maxHealth , this.getCurrentPhase().startsWith("fight-"))); + return healths; + } + + @Override + public String getBossName() { + return "Necron"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorProf.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorProf.java new file mode 100644 index 00000000..bde85c6e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorProf.java @@ -0,0 +1,144 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraftforge.event.entity.living.LivingEvent; + +import java.util.ArrayList; +import java.util.List; + +public class BossfightProcessorProf extends GeneralBossfightProcessor { + public BossfightProcessorProf() { + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("start") + .signatureMsg("§r§c[BOSS] The Professor§r§f: I was burdened with terrible news recently...§r") + .nextPhase("fight-1").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-1") + .signatureMsg("§r§c[BOSS] The Professor§r§f: I'll show you real power!§r") + .nextPhase("first-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("first-defeat") + .signatureMsg("§r§c[BOSS] The Professor§r§f: Oh? You found my Guardians one weakness?§r") + .nextPhase("fight-2").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-2") + .signatureMsg("§r§c[BOSS] The Professor§r§f: This time I'll be your opponent!§r") + .nextPhase("second-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("second-defeat") + .signatureMsg("§r§c[BOSS] The Professor§r§f: I see. You have forced me to use my ultimate technique.§r") + .nextPhase("fight-3").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-3") + .signatureMsg("§r§c[BOSS] The Professor§r§f: The process is irreversible, but I'll be stronger than a Wither now!§r") + .nextPhase("final-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("final-defeat") + .signatureMsg("§r§c[BOSS] The Professor§r§f: What?! My Guardian power is unbeatable!§r").build() + ); + } + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + { + long health = 0; + if (profStand != null) { + String name = TextUtils.stripColor(profStand.getName()); + String healthPart = name.split(" ")[3]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("The Professor", (int) health, 3000000, this.getCurrentPhase().startsWith("fight-") && !this.getCurrentPhase().equals("fight-1"))); + } + if (!getCurrentPhase().equals("second-defeat") && !getCurrentPhase().equals("fight-3") && !getCurrentPhase().equals("final-defeat")) { + { + long health = 0; + if (healthyGuard != null) { + String name = TextUtils.stripColor(healthyGuard.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Healthy Guardian", (int) health, 1000000, this.getCurrentPhase().equals("fight-1"))); + } + { + long health = 0; + if (chaosGuard != null) { + String name = TextUtils.stripColor(chaosGuard.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Chaos Guardian", (int) health, 1000000, this.getCurrentPhase().equals("fight-1"))); + } + { + long health = 0; + if (laserGuard != null) { + String name = TextUtils.stripColor(laserGuard.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Laser Guardian", (int) health, 1000000, this.getCurrentPhase().equals("fight-1"))); + } + { + long health = 0; + if (reinforcedGuard != null) { + String name = TextUtils.stripColor(reinforcedGuard.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Reinforced Guardian", (int) health, 1000000, this.getCurrentPhase().equals("fight-1"))); + } + } + return healths; + } + + @Override + public String getBossName() { + return "The Professor"; + } + + private EntityArmorStand profStand; + private EntityArmorStand laserGuard; + private EntityArmorStand chaosGuard; + private EntityArmorStand reinforcedGuard; + private EntityArmorStand healthyGuard; + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving instanceof EntityArmorStand) { + if (updateEvent.entityLiving.getName().startsWith("§e﴾ §c§lThe Professor§r ")) + profStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§cHealthy Guardian ")) + healthyGuard = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§cChaos Guardian ")) + chaosGuard = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§cLaser Guardian ")) + laserGuard = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§cReinforced Guardian ")) + reinforcedGuard = (EntityArmorStand) updateEvent.entityLiving; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorSadan.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorSadan.java new file mode 100644 index 00000000..0415996d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorSadan.java @@ -0,0 +1,144 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraftforge.event.entity.living.LivingEvent; + +import java.util.ArrayList; +import java.util.List; + +public class BossfightProcessorSadan extends GeneralBossfightProcessor { + public BossfightProcessorSadan() { + addPhase(PhaseData.builder() + .phase("start") + .signatureMsg("So you made it all the way §r§fhere...and§r§f you wish to defy me? Sadan?!§r") + .nextPhase("fight-1").build() + ); + addPhase(PhaseData.builder() + .phase("fight-1") + .signatureMsg("§r§c[BOSS] Sadan §r§f: I am the bridge between this realm and the world below! You shall not pass!§r") + .nextPhase("first-defeat").build() + ); + addPhase(PhaseData.builder() + .phase("first-defeat") + .signatureMsg("§r§c[BOSS] Sadan §r§f: ENOUGH!§r") + .nextPhase("fight-2").build() + ); + addPhase(PhaseData.builder() + .phase("fight-2") + .signatureMsg("§r§c[BOSS] Sadan §r§f: My giants! Unleashed!§r") + .nextPhase("second-defeat").build() + ); + addPhase(PhaseData.builder() + .phase("second-defeat") + .signatureMsg("§r§c[BOSS] Sadan §r§f: You did it. I understand now, you have earned my respect.§r") + .nextPhase("fight-3").build() + ); + addPhase(PhaseData.builder() + .phase("fight-3") + .signatureMsg("§r§c[BOSS] Sadan §r§f: I'm sorry but I need to concentrate. I wish it didn't have to come to this.§r") + .nextPhase("final-defeat").build() + ); + addPhase(PhaseData.builder() + .phase("final-defeat") + .signatureMsg("§r§c[BOSS] Sadan §r§f: NOOOOOOOOO!!! THIS IS IMPOSSIBLE!!§r").build() + ); + } + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + { + long health = 0; + if (sadanStand != null) { + String name = TextUtils.stripColor(sadanStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Sadan", (int) health, 40000000, this.getCurrentPhase().equals("fight-3"))); + } + if (getCurrentPhase().equals("fight-2")) { + { + long health = 0; + if (diamondGiant != null) { + String name = TextUtils.stripColor(diamondGiant.getName()); + String healthPart = name.split(" ")[3]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("The Diamond Giant", (int) health, 25000000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (bigfootGiant != null) { + String name = TextUtils.stripColor(bigfootGiant.getName()); + String healthPart = name.split(" ")[1]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Bigfoot", (int) health, 25000000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (laserGiant != null) { + String name = TextUtils.stripColor(laserGiant.getName()); + String healthPart = name.split(" ")[1]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("L.A.S.R.", (int) health, 25000000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (boulderGiant != null) { + String name = TextUtils.stripColor(boulderGiant.getName()); + String healthPart = name.split(" ")[3]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Jolly Pink Giant", (int) health, 25000000, this.getCurrentPhase().startsWith("fight-"))); + } + } + return healths; + } + + @Override + public String getBossName() { + return "Sadan"; + } + + private EntityArmorStand sadanStand; + private EntityArmorStand diamondGiant; + private EntityArmorStand laserGiant; + private EntityArmorStand bigfootGiant; + private EntityArmorStand boulderGiant; + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving instanceof EntityArmorStand) { + if (updateEvent.entityLiving.getName().startsWith("§e﴾ §c§lSadan§r ")) + sadanStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§c§d§lJolly Pink Giant ")) + boulderGiant = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§c§4§lL.A.S.R. ")) + laserGiant = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§c§3§lThe Diamond Giant ")) + diamondGiant = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§c§c§lBigfoot ")) + bigfootGiant = (EntityArmorStand) updateEvent.entityLiving; + } + } +}
\ No newline at end of file diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorScarf.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorScarf.java new file mode 100644 index 00000000..c1ef8180 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorScarf.java @@ -0,0 +1,134 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraftforge.event.entity.living.LivingEvent; + +import java.util.ArrayList; +import java.util.List; + +public class BossfightProcessorScarf extends GeneralBossfightProcessor { + public BossfightProcessorScarf() { + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("start") + .signatureMsg("§r§c[BOSS] Scarf §r§f: This is where the journey ends for you, Adventurers.§r") + .nextPhase("fight-1").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-1") + .signatureMsg("§r§c[BOSS] Scarf §r§f: ARISE, MY CREATIONS!§r") + .nextPhase("first-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("first-defeat") + .signatureMsg("§r§c[BOSS] Scarf §r§f: Those toys are not strong enough I see.§r") + .nextPhase("fight-2").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-2") + .signatureMsg("§r§c[BOSS] Scarf §r§f: Did you forget? I was taught by the best! Let's dance.§r") + .nextPhase("final-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("final-defeat") + .signatureMsg("§r§c[BOSS] Scarf §r§f: Whatever...§r").build() + ); + } + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + { + long health = 0; + if (scarfStand != null) { + String name = TextUtils.stripColor(scarfStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Scarf", (int) health, 1000000, this.getCurrentPhase().equals("fight-2"))); + } + if (!getCurrentPhase().equals("start") && !getCurrentPhase().equals("final-defeat")) { + { + long health = 0; + if (priestStand != null) { + String name = TextUtils.stripColor(priestStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Undead Priest", (int) health, 600000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (berserkStand != null) { + String name = TextUtils.stripColor(berserkStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Undead Warrior", (int) health, 500000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (mageStand != null) { + String name = TextUtils.stripColor(mageStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Undead Mage", (int) health, 400000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (archerStand != null) { + String name = TextUtils.stripColor(archerStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Undead Archer", (int) health, 400000, this.getCurrentPhase().startsWith("fight-"))); + } + } + return healths; + } + + @Override + public String getBossName() { + return "Scarf"; + } + + private EntityArmorStand scarfStand; + private EntityArmorStand priestStand; + private EntityArmorStand mageStand; + private EntityArmorStand berserkStand; + private EntityArmorStand archerStand; + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving instanceof EntityArmorStand) { + if (updateEvent.entityLiving.getName().startsWith("§e﴾ §c§lScarf§r ")) + scarfStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§6§4§lUndead Archer ")) + archerStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§6§4§lUndead Mage ")) + mageStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§6§4§lUndead Priest ")) + priestStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§6§4§lUndead Warrior ")) + berserkStand = (EntityArmorStand) updateEvent.entityLiving; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorThorn.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorThorn.java new file mode 100644 index 00000000..c7ab91af --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/BossfightProcessorThorn.java @@ -0,0 +1,104 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.entity.boss.BossStatus; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +import java.awt.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class BossfightProcessorThorn extends GeneralBossfightProcessor { + + + public BossfightProcessorThorn() { + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight").build() + ); + + w= DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext().getWorld(); + } + private final Set<BlockPos> progressBar = new HashSet<BlockPos>(); + private final World w; + + private int ticksPassed = 0; + + @Override + public void tick() { + ticksPassed ++; + if (ticksPassed == 20) { + progressBar.clear(); + for (int x = -30; x <= 30; x++) { + for (int y = -30; y <= 30; y++) { + BlockPos newPos = new BlockPos(5 + x, 77, 5 + y); + Block b = w.getBlockState(newPos).getBlock(); + if ((b == Blocks.coal_block || b == Blocks.sea_lantern) && w.getBlockState(newPos.add(0, 1, 0)).getBlock() != Blocks.carpet) + progressBar.add(newPos); + } + } + } + } + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + healths.add(new HealthData("Thorn", Math.round(BossStatus.healthScale * 4),4, true)); + return healths; + } + + @Override + public String getBossName() { + return "Thorn"; + } + + public double calculatePercentage() { + int total = progressBar.size(), lit = 0; + if (total == 0) return 0; + for (BlockPos pos : progressBar) { + if (w.getBlockState(pos).getBlock() == Blocks.sea_lantern ) lit++; + } + + return lit / (double)total; + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.DEBUG.isEnabled()) return; + try { + BlockPos pos = new BlockPos(205,77, 205); + RenderUtils.highlightBlock(pos, new Color(0, 255, 255, 50), partialTicks, false); + for (BlockPos pos2 : progressBar) { + RenderUtils.highlightBlock(pos2, w.getBlockState(pos2).getBlock() == Blocks.sea_lantern ? + new Color(0, 255, 0, 50) : new Color(255,0,0, 50), partialTicks, false); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/GeneralBossfightProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/GeneralBossfightProcessor.java new file mode 100644 index 00000000..10b6fea8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/GeneralBossfightProcessor.java @@ -0,0 +1,155 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.events.BlockUpdateEvent; +import kr.syeyoung.dungeonsguide.events.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent; +import lombok.*; +import net.minecraft.util.IChatComponent; +import net.minecraft.world.World; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +import java.util.*; + +public abstract class GeneralBossfightProcessor implements BossfightProcessor { + private final Map<String, PhaseData> phases = new HashMap<String, PhaseData>(); + private PhaseData currentPhase = null; + + @Getter + @Setter + private String name; + + private World world; + + public void addPhase(PhaseData phaseData) { + if (phaseData == null) return; + if (currentPhase == null) currentPhase = phaseData; + phases.put(phaseData.getPhase(), phaseData); + } + + @Override + public List<String> getPhases() { + List<String> phases = new ArrayList<String>(); + for (PhaseData pd:this.phases.values()) + phases.add(pd.getPhase()); + return phases; + } + + @Override + public List<String> getNextPhases() { + if (currentPhase == null) return Collections.emptyList(); + List<String> phases = new ArrayList<String>(this.currentPhase.getNextPhases()); + return phases; + } + + + @Override + public String getCurrentPhase() { + return currentPhase == null ? "unknown" : currentPhase.getPhase(); + } + + @Override + public void chatReceived(IChatComponent chat) { + if (currentPhase == null) return; + + for (String nextPhase : currentPhase.getNextPhases()) { + PhaseData phaseData = phases.get(nextPhase); + if (phaseData == null) continue; + if (phaseData.signatureMsgs.contains(chat.getFormattedText().replace(" ", ""))) { + currentPhase = phaseData; + onPhaseChange(); + return; + } + } + } + + @Override + public void actionbarReceived(IChatComponent chat) {} + + @Override + public void tick() {} + + @Override + public void drawScreen(float partialTicks) {} + + @Override + public void drawWorld(float partialTicks) {} + + @Override + public boolean readGlobalChat() {return true;} + + @Override + public void onPostGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) { + + } + + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + + } + + @Override + public void onInteract(PlayerInteractEntityEvent event) { + + } + + @Override + public void onKeybindPress(KeyBindPressedEvent keyInputEvent) { + + } + + @Override + public void onInteractBlock(PlayerInteractEvent event) { + + } + @Override + public void onEntityDeath(LivingDeathEvent deathEvent) { + + } + @Override + public void onBlockUpdate(BlockUpdateEvent blockUpdateEvent) { + + } + + public void onPhaseChange() {} + + @Data + @Builder + public static class PhaseData { + private PhaseData(String phase, Set<String> signatureMsgs, Set<String> nextPhase) { + this.phase = phase; + this.nextPhases = new HashSet<>(nextPhase); + this.signatureMsgs = new HashSet<>(); + for (String signatureMsg : signatureMsgs) { + this.signatureMsgs.add(signatureMsg.replace(" ", "")); + } + } + + private String phase; + @Singular + private Set<String> signatureMsgs; + @Singular + private Set<String> nextPhases; + + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/HealthData.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/HealthData.java new file mode 100644 index 00000000..268a4d28 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/bossfight/HealthData.java @@ -0,0 +1,33 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.bossfight; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class HealthData { + private String name; + private int health; + private int maxHealth; + private boolean attackable; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/boxpuzzle/BoxPuzzleSolvingThread.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/boxpuzzle/BoxPuzzleSolvingThread.java new file mode 100755 index 00000000..f1d06554 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/boxpuzzle/BoxPuzzleSolvingThread.java @@ -0,0 +1,182 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.boxpuzzle; + +import lombok.Getter; +import lombok.Setter; + +import java.awt.*; +import java.util.*; +import java.util.List; + +@Getter +@Setter +public class BoxPuzzleSolvingThread extends Thread { + private byte[][] data; + private int playerX; + private int playerY; + private Runnable callback; + + + public BoxPuzzleSolvingThread(byte[][] data, int playerX, int playerY, Runnable onDone) { + this.data = data; + this.playerX = playerX; + this.playerY = playerY; + this.callback = onDone; + } + + Route solution = null; + + private boolean solved = false; + + @Override + public void run() { + solved = false; + solution = solve(data,playerX,playerY, 20); + solved = true; + callback.run(); + } + + + public static String stateString(byte[][] array) { + StringBuilder sb = new StringBuilder(); + for (int y = 0; y < array.length; y++) + for(int x = 0; x < array[y].length; x++) + sb.append(array[y][x]); + + return sb.toString(); + } + + + private static final List<Point> directions = Arrays.asList(new Point(-1,0), new Point(1,0), new Point(0,1), new Point(0,-1)); + private static Route solve(byte[][] boardStart, int playerX, int playerY, int maxRecursion) { // result:: playerY == 0 + Queue<Route> routes = new LinkedList<Route>(); + Set<String> globalStatesBeen = new HashSet<String>(); + + Route r = new Route(); + r.currentState = boardStart; + routes.add(r); + + while (!routes.isEmpty()) { + Route route = routes.poll(); + + if (routes.size() > 3000000) return null; + + String stateId = stateString(route.currentState); + if (maxRecursion < route.boxMoves.size()) continue; + if (globalStatesBeen.contains(stateId)) continue; + + Queue<Point> points = new LinkedList<Point>(); + Set<Point> reached= new HashSet<Point>(); + List<BoxMove> possibleBoxMoves = new ArrayList<BoxMove>(); + points.add(new Point(playerX, playerY)); + + while (!points.isEmpty()) { + Point pt = points.poll(); + if (pt.y == 0) { + return route; + } + if (reached.contains(pt)) continue; + reached.add(pt); + for (Point dir:directions) { + int resX= pt.x + dir.x; + int resY = pt.y + dir.y; + if (resX < 0 || resY < 0 || resX >= route.currentState[0].length || resY >= route.currentState.length) { + continue; + } + if (route.currentState[resY][resX] > 0) { + possibleBoxMoves.add(new BoxMove(resX, resY, dir.x, dir.y)); + continue; + } + points.add(new Point(resX, resY)); + } + } + + globalStatesBeen.add(stateId); + for (BoxMove possibleBoxMove : possibleBoxMoves) { + byte[][] copied = new byte[route.currentState.length][]; + for (int y = 0; y < copied.length; y++) + copied[y] = route.currentState[y].clone(); + + if (push(copied, possibleBoxMove.x, possibleBoxMove.y, possibleBoxMove.dx, possibleBoxMove.dy)){ + String stateId2 = stateString(copied); + if (globalStatesBeen.contains(stateId2)) continue; + + Route route2 = new Route(); + route2.boxMoves = new ArrayList<BoxMove>(route.boxMoves); + route2.boxMoves.add(possibleBoxMove); + route2.currentState = copied; + + routes.add(route2); + } + } + } + + + return null; + } + + + public static boolean push(byte[][] board, int x,int y,int dx,int dy) { + if (board[y][x] != 1) return false; + int resultingX= x + dx; + int resultingY = y +dy; + if (resultingX < 0 || resultingY < 0 || resultingX >= board[0].length || resultingY >= board.length) return false; + if (board[resultingY][resultingX] == 1 || resultingY == 6) return false; + + board[resultingY][resultingX] = 1; + board[y][x] = 0; + return true; + } + + public static class BoxMove { + int x; + int y; + int dx; + int dy; + + public BoxMove(int x, int y, int dx, int dy) { + this.x = x; + this.y = y; + this.dx = dx; + this.dy = dy; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getDx() { + return dx; + } + + public int getDy() { + return dy; + } + } + + public static class Route { + List<BoxMove> boxMoves = new LinkedList<BoxMove>(); + byte[][] currentState; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/boxpuzzle/RoomProcessorBoxSolver.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/boxpuzzle/RoomProcessorBoxSolver.java new file mode 100755 index 00000000..f4eb1d3d --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/boxpuzzle/RoomProcessorBoxSolver.java @@ -0,0 +1,391 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.boxpuzzle; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor; +import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessorGenerator; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Blocks; +import net.minecraft.util.*; +import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class RoomProcessorBoxSolver extends GeneralRoomProcessor { + + + private BlockPos[][] poses = new BlockPos[7][7]; + private boolean bugged= true; + + private BoxPuzzleSolvingThread puzzleSolvingThread; + + public RoomProcessorBoxSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + + OffsetPointSet ops = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("board"); + try { + if (ops != null) { + for (int y = 0; y < 7; y++) { + for (int x = 0; x < 7; x++) { + poses[y][x] = ops.getOffsetPointList().get(y * 7 + x).getBlockPos(dungeonRoom); + } + } + bugged = false; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private byte[][] buildCurrentState() { + World w = getDungeonRoom().getContext().getWorld(); + byte[][] board = new byte[poses.length][poses[0].length]; + for (int y = 0; y < poses.length; y++) { + for (int x = 0; x < poses[0].length; x++) { + if (y == 6) { + board[y][x] = -1; + continue; + } + BlockPos pos = poses[y][x]; + Block b = w.getChunkFromBlockCoords(pos).getBlock(pos); + if (b == Blocks.air) + board[y][x] = 0; + else + board[y][x] = 1; + } + } + return board; + } + + private boolean calcReq = true; + + private boolean calcDone= false; + private boolean calcDone2 = false; + private int step = 0; + private byte[][] lastState; + + @Override + public void tick() { + super.tick(); + if (!FeatureRegistry.SOLVER_BOX.isEnabled()) return; + if (bugged) return; + byte[][] currboard = buildCurrentState(); + if (puzzleSolvingThread == null) { + calcDone = false; + puzzleSolvingThread = new BoxPuzzleSolvingThread(currboard, 0, 6, new Runnable() { + @Override + public void run() { + calcDone = true; + calcDone2 = true; + } + }); + puzzleSolvingThread.start(); + } + if (calcReq) { + OffsetPointSet ops = (OffsetPointSet) getDungeonRoom().getDungeonRoomInfo().getProperties().get("board"); + if (ops != null) { + poses = new BlockPos[7][7]; + for (int y = 0; y < 7; y++) { + for (int x = 0; x < 7; x++) { + poses[y][x] = ops.getOffsetPointList().get(y * 7 + x).getBlockPos(getDungeonRoom()); + } + } + bugged = false; + } + + calcDone = false; + if (puzzleSolvingThread != null) + puzzleSolvingThread.stop(); + puzzleSolvingThread = new BoxPuzzleSolvingThread(currboard, 0, 6, new Runnable() { + @Override + public void run() { + calcDone = true; + calcDone2 = true; + } + }); + puzzleSolvingThread.start(); + calcReq = false; + } + + boolean pathFindReq = false; + if (calcDone2) { + BoxPuzzleSolvingThread.Route semi_solution = puzzleSolvingThread.solution; + if (semi_solution == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §eBox Solver §7:: §cCouldn't find solution involving less than 20 box moves within 3m concurrent possibility")); + step = 0; + calcDone2 = false; + pathFindReq = true; + totalPath = new LinkedList<BlockPos>(); + totalPushedBlocks = new LinkedList<BlockPos>(); + solution = new LinkedList<BoxPuzzleSolvingThread.BoxMove>(); + return; + } else{ + solution = semi_solution.boxMoves; + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §eBox Solver §7:: Solution Found!")); + } + step = 0; + lastState = currboard; + calcDone2 = false; + pathFindReq = true; + + calcTotalPath(); + } + + if (lastState == null) return; + boolean moved = false; + label: + for (int y = 0 ; y < currboard.length; y++) { + for (int x = 0; x < currboard[y].length; x++) { + if (lastState[y][x] != currboard[y][x]) { + moved = true; + lastState = currboard; + break label; + } + } + } + + if (moved) { + step++; + } + + Point player = getPlayerPos(currboard); + boolean currYState = Minecraft.getMinecraft().thePlayer.getPosition().getY() < 68; + if (((currYState && !player.equals(lastPlayer)) || (currYState != yState) || (moved) || pathFindReq) && solution != null) { + Point target = null; + if (step < solution.size()) { + BoxPuzzleSolvingThread.BoxMove boxMove = solution.get(step); + target = new Point(boxMove.x - boxMove.dx, boxMove.y - boxMove.dy); + } + List<Point> semi_pathFound = pathfind(currboard, player, target); + pathFound = new LinkedList<BlockPos>(); + for (Point point : semi_pathFound) { + pathFound.add(poses[point.y][point.x].add(0,-1,0)); + } + + lastPlayer = player; + yState = currYState; + } + + } + + public void calcTotalPath() { + Point player = new Point(0,6); + totalPath = new LinkedList<BlockPos>(); + totalPushedBlocks = new LinkedList<BlockPos>(); + byte[][] currboard = buildCurrentState(); + for (int i = 0; i <= solution.size(); i++) { + Point target = null; + BoxPuzzleSolvingThread.BoxMove boxMove = null; + if (i < solution.size()) { + boxMove = solution.get(i); + target = new Point(boxMove.x - boxMove.dx, boxMove.y - boxMove.dy); + } + List<Point> semi_pathFound = pathfind(currboard, player, target); + for (int i1 = semi_pathFound.size() - 1; i1 >= 0; i1--) { + Point point = semi_pathFound.get(i1); + totalPath.add(poses[point.y][point.x].add(0, -1, 0)); + } + + player = target; + if (boxMove != null) { + BoxPuzzleSolvingThread.push(currboard, boxMove.x, boxMove.y, boxMove.dx, boxMove.dy); + int fromX = boxMove.x - boxMove.dx; + int fromY = boxMove.y - boxMove.dy; + + BlockPos pos = poses[fromY][fromX]; + BlockPos pos2 = poses[boxMove.y][boxMove.x]; + BlockPos dir = pos.subtract(pos2); + dir = new BlockPos(MathHelper.clamp_int(dir.getX(), -1,1), 0, MathHelper.clamp_double(dir.getZ(), -1, 1)); + + BlockPos highlight = pos2.add(dir); + totalPushedBlocks.add(highlight); + } + } + } + + private boolean yState = true; + public Point getPlayerPos(byte[][] map) { + BlockPos playerPos = Minecraft.getMinecraft().thePlayer.getPosition(); + int minDir = Integer.MAX_VALUE; + Point pt = null; + for (int y = 0; y < poses.length; y++) { + for (int x = 0; x < poses[0].length; x++) { + if (map[y][x] == 1) continue; + int dir = (int) poses[y][x].distanceSq(playerPos); + if (dir < minDir) { + minDir = dir; + pt = new Point(x,y); + } + } + } + return pt; + } + + private List<BoxPuzzleSolvingThread.BoxMove> solution; + private List<BlockPos> pathFound; + private List<BlockPos> totalPath; + private List<BlockPos> totalPushedBlocks; + private Point lastPlayer; + + private static final java.util.List<Point> directions = Arrays.asList(new Point(-1,0), new Point(1,0), new Point(0,1), new Point(0,-1)); + public List<Point> pathfind(byte[][] map, Point start, Point target2) { + int[][] distances = new int[map.length][map[0].length]; + + Queue<Point> evalulate = new LinkedList<Point>(); + evalulate.add(start); + Point target = null; + while (!evalulate.isEmpty()) { + Point p = evalulate.poll(); + if (p.equals(target2) || (target2 == null &&p.y == 0)) { + target = p; + break; + } + int max = 0; + for (Point dir:directions) { + int resX= p.x + dir.x; + int resY = p.y + dir.y; + if (resX < 0 || resY < 0 || resX >= distances[0].length || resY >= distances.length) { + continue; + } + + if (max < distances[resY][resX]) { + max = distances[resY][resX]; + } + if (distances[resY][resX] == 0 && (map[resY][resX] == 0 ||map[resY][resX] == -1)) { + evalulate.add(new Point(resX, resY)); + } + } + distances[p.y][p.x] = max + 1; + } + if (target == null) return Collections.emptyList(); + + List<Point> route = new LinkedList<Point>(); + while(!target.equals(start)) { + route.add(target); + int min = Integer.MAX_VALUE; + Point minPoint = null; + for (Point dir:directions) { + int resX= target.x + dir.x; + int resY = target.y + dir.y; + if (resX < 0 || resY < 0 || resX >= distances[0].length || resY >= distances.length) { + continue; + } + + if (min > distances[resY][resX] && distances[resY][resX] != 0) { + min = distances[resY][resX]; + minPoint = new Point(resX, resY); + } + } + target = minPoint; + } + route.add(start); + return route; + } + + @Override + public void chatReceived(IChatComponent chat) { + if (!FeatureRegistry.SOLVER_BOX.isEnabled()) return; + if (chat.getFormattedText().toLowerCase().contains("recalc")) { + if (calcDone) { + calcReq = true; + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide :::: Recalculating Route...")); + } else { + calcReq = true; + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide :::: Currently Calculating Route...")); + } + } + } + + @Override + public void drawScreen(float partialTicks) { + super.drawScreen(partialTicks); + if (!FeatureRegistry.SOLVER_BOX.isEnabled()) return; + if (FeatureRegistry.SOLVER_BOX.disableText()) return; + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Type \"recalc\" in chat to recalculate the solution", 0, 0, 0xFFFFFFFF); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_BOX.isEnabled()) return; + if (bugged) return; + if (!calcDone) return; + if (solution == null) return; + if (Minecraft.getMinecraft().thePlayer.getPosition().getY() < 68) { + if (step < solution.size()) { + BoxPuzzleSolvingThread.BoxMove boxMove = solution.get(step); + int fromX = boxMove.x - boxMove.dx; + int fromY = boxMove.y - boxMove.dy; + + BlockPos pos = poses[fromY][fromX]; + BlockPos pos2 = poses[boxMove.y][boxMove.x]; + BlockPos dir = pos.subtract(pos2); + dir = new BlockPos(MathHelper.clamp_int(dir.getX(), -1, 1), 0, MathHelper.clamp_double(dir.getZ(), -1, 1)); + + BlockPos highlight = pos2.add(dir); + AColor color = FeatureRegistry.SOLVER_BOX.getTargetColor().multiplyAlpha(MathHelper.clamp_double(Minecraft.getMinecraft().thePlayer.getPosition().distanceSq(highlight), 100, 255) / 255); + RenderUtils.highlightBoxAColor(AxisAlignedBB.fromBounds(highlight.getX(), highlight.getY(), highlight.getZ(), highlight.getX()+1, highlight.getY() + 1, highlight.getZ() + 1), color, partialTicks, false); + } + + if (pathFound != null) { + RenderUtils.drawLines(pathFound, FeatureRegistry.SOLVER_BOX.getLineColor(),FeatureRegistry.SOLVER_BOX.getLineWidth(), partialTicks, true); + } + } else { + if (totalPath != null) { + RenderUtils.drawLines(totalPath, FeatureRegistry.SOLVER_BOX.getLineColor(),FeatureRegistry.SOLVER_BOX.getLineWidth(), partialTicks, false); + } + if (totalPushedBlocks != null) { + for (int i = 0; i < totalPushedBlocks.size(); i++) { + BlockPos pos = totalPushedBlocks.get(i); + RenderUtils.highlightBoxAColor(AxisAlignedBB.fromBounds(pos.getX(), pos.getY(), pos.getZ(), pos.getX()+1, pos.getY() + 1, pos.getZ() + 1), FeatureRegistry.SOLVER_BOX.getTargetColor(), partialTicks, false); + RenderUtils.drawTextAtWorld("#"+i, pos.getX()+0.5f, pos.getY() +0.5f, pos.getZ() + 0.5f, i != step ? + RenderUtils.getColorAt(pos.getX(), pos.getY(), pos.getZ(), FeatureRegistry.SOLVER_BOX.getTextColor2()) : RenderUtils.getColorAt(pos.getX(), pos.getY(), pos.getZ(), FeatureRegistry.SOLVER_BOX.getTextColor()), 0.1f, false, false, partialTicks); + } + } + } + + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorBoxSolver> { + @Override + public RoomProcessorBoxSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorBoxSolver defaultRoomProcessor = new RoomProcessorBoxSolver(dungeonRoom); + return defaultRoomProcessor; + } + } + + + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/icefill/RoomProcessorIcePath2.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/icefill/RoomProcessorIcePath2.java new file mode 100755 index 00000000..5cc6a1cb --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/icefill/RoomProcessorIcePath2.java @@ -0,0 +1,158 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.icefill; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor; +import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessorGenerator; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; + +import java.awt.*; +import java.util.Queue; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CopyOnWriteArrayList; + +public class RoomProcessorIcePath2 extends GeneralRoomProcessor { + private final List<List<BlockPos>> solution = new CopyOnWriteArrayList<List<BlockPos>>(); + + private final Queue<String> messageQueue = new ConcurrentLinkedQueue<String>(); + + public RoomProcessorIcePath2(DungeonRoom dungeonRoom) { + + super(dungeonRoom); + + String levels = (String) dungeonRoom.getDungeonRoomInfo().getProperties().get("levels"); + if (levels == null) { + return; + } + + for (final String s : levels.split(",")) { + try { + OffsetPointSet level = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get(s + "-board"); + String data = (String) dungeonRoom.getDungeonRoomInfo().getProperties().get(s + "-level"); + final int width = Integer.parseInt(data.split(":")[0]); + final int height = Integer.parseInt(data.split(":")[1]); + final int startX = Integer.parseInt(data.split(":")[2]); + final int startY = Integer.parseInt(data.split(":")[3]); + final int endX = Integer.parseInt(data.split(":")[4]); + final int endY = Integer.parseInt(data.split(":")[5]); + + final int[][] map = new int[height][width]; + final BlockPos[][] map2 = new BlockPos[height][width]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + map2[y][x] = level.getOffsetPointList().get(y * width + x).getBlockPos(dungeonRoom); + map[y][x] = level.getOffsetPointList().get(y * width + x).getBlock(dungeonRoom) == Blocks.air ? 0 : 1; + } + } + + new Thread() { + public void run() { + List<Point> hamiltonianPath = findFirstHamiltonianPath(map, startX, startY, endX, endY); + if (hamiltonianPath == null) { + messageQueue.add("§eDungeons Guide §7:: §eIcePath §7:: §cCouldn't find solution for floor "+s); + return; + } + hamiltonianPath.add(0,new Point(startX, startY)); + List<BlockPos> poses = new LinkedList<BlockPos>(); + for (int i = 0; i < hamiltonianPath.size(); i++) { + Point p = hamiltonianPath.get(i); + poses.add(map2[p.y][p.x]); + } + solution.add(poses); + } + }.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public void tick() { + super.tick(); + if (!FeatureRegistry.SOLVER_ICEPATH.isEnabled()) return; + while (!messageQueue.isEmpty()){ + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(messageQueue.poll())); + } + } + + @Override + public void drawWorld(float partialTicks) { + if (!FeatureRegistry.SOLVER_ICEPATH.isEnabled()) return; + for (List<BlockPos> solution:this.solution) + RenderUtils.drawLines(solution, FeatureRegistry.SOLVER_ICEPATH.getLineColor(),FeatureRegistry.SOLVER_ICEPATH.getLineWidth(), partialTicks, true); + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorIcePath2> { + @Override + public RoomProcessorIcePath2 createNew(DungeonRoom dungeonRoom) { + RoomProcessorIcePath2 defaultRoomProcessor = new RoomProcessorIcePath2(dungeonRoom); + return defaultRoomProcessor; + } + } + + private static List<Point> findFirstHamiltonianPath(int[][] map, int startX, int startY, int endX, int endY) { + int emptySpace =0; + for (int y = 0; y < map.length; y++) + for (int x = 0; x < map[y].length; x++) + if (map[y][x] == 0) emptySpace++; + + map[startY][startX] = 2; + + return findHamiltonianPath(map, startX, startY, endX, endY, 0, emptySpace-1); + } + + + private static final List<Point> directions = Arrays.asList(new Point(0,-1), new Point(-1,0), new Point(1,0), new Point(0,1)); + private static LinkedList<Point> findHamiltonianPath(int[][] map, int startX, int startY, int endX, int endY, int depth, int reqDepth) { + if (endX == startX && endY == startY) { + if (depth != reqDepth) return null; + LinkedList<Point> path = new LinkedList<Point>(); + path.add(new Point(startX, startY)); + return path; + } + + for (Point p : directions) { + int y = p.y +startY,x=p.x + startX; + if (y <0 || y >= map.length || x <0 || x >= map[0].length || map[y][x] != 0) continue; + + int[][] copiedMap = new int[map.length][map[0].length]; + for (int y2 = 0; y2 < copiedMap.length; y2++) + copiedMap[y2] = map[y2].clone(); + copiedMap[y][x] = 2; + + LinkedList<Point> potentialRoute = findHamiltonianPath(copiedMap, x,y,endX,endY, depth +1, reqDepth); + if (potentialRoute != null) { + potentialRoute.addFirst(new Point(x,y)); + return potentialRoute; + } + } + return null; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/LeverState.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/LeverState.java new file mode 100755 index 00000000..a2acd9c4 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/LeverState.java @@ -0,0 +1,33 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class LeverState { + private String blockId; + private boolean requiredState; + + public LeverState invert() { + return new LeverState(blockId, !requiredState); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/LeverStateContradict.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/LeverStateContradict.java new file mode 100755 index 00000000..71165847 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/LeverStateContradict.java @@ -0,0 +1,25 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle; + +public class LeverStateContradict extends LeverState { + public LeverStateContradict() { + super("contradict", true); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java new file mode 100755 index 00000000..4d51ce4b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java @@ -0,0 +1,124 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor; +import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessorGenerator; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.List; + +public class RoomProcessorWaterPuzzle extends GeneralRoomProcessor { + + private boolean argumentsFulfilled = false; + + private WaterBoard waterBoard; + private final OffsetPointSet doorsClosed; + private final OffsetPointSet levers; + private final OffsetPointSet frontBoard; + private final OffsetPointSet backBoard; + private final OffsetPoint water_lever; + + public RoomProcessorWaterPuzzle(DungeonRoom dungeonRoom) { + super(dungeonRoom); + frontBoard = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("front"); + backBoard = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("back"); + levers = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("levers"); + doorsClosed = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("doors"); + water_lever = (OffsetPoint) dungeonRoom.getDungeonRoomInfo().getProperties().get("water-lever"); + + if (frontBoard == null || backBoard == null || levers == null || doorsClosed == null ||water_lever == null) { + argumentsFulfilled = false; + } else { + argumentsFulfilled = true; + + try { + waterBoard = new WaterBoard(this, frontBoard, backBoard, levers, doorsClosed, water_lever); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public void tick() { + super.tick(); + if (!FeatureRegistry.SOLVER_WATERPUZZLE.isEnabled()) return; + if (!argumentsFulfilled) return; + try { + waterBoard.tick(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void drawScreen(float partialTicks) { + super.drawScreen(partialTicks); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_WATERPUZZLE.isEnabled()) return; + if (!argumentsFulfilled) return; + if (waterBoard == null) return; + + Route route = waterBoard.getCurrentRoute(); + if (route != null) { + int j = 1; + for (int i = 0; i < route.getConditionList().size(); i++) { + LeverState condition = route.getConditionList().get(i); + if (condition == null) continue; + SwitchData switchData = waterBoard.getValidSwitches().get(condition.getBlockId()); + if (switchData.getCurrentState(getDungeonRoom().getContext().getWorld()) != condition.isRequiredState()) { + + RenderUtils.highlightBlock(switchData.getSwitchLoc(), new Color(0,255,0,50), partialTicks, true); + RenderUtils.drawTextAtWorld("#"+j,switchData.getSwitchLoc().getX(), switchData.getSwitchLoc().getY()+1, switchData.getSwitchLoc().getZ(), 0xFF000000,0.1f, false, false, partialTicks); + RenderUtils.drawTextAtWorld(condition.isRequiredState() ? "on":"off",switchData.getSwitchLoc().getX(), switchData.getSwitchLoc().getY(), switchData.getSwitchLoc().getZ(), 0xFF000000,0.1f, false, false, partialTicks); + j++; + } + } + for (WaterNode node : route.getNodes()) { + RenderUtils.highlightBlock(node.getBlockPos(), new Color(0,255,255,50), partialTicks, true); + } + } + List<BlockPos> targets = waterBoard.getTarget(); + if (targets != null) { + for (BlockPos target : targets) { + RenderUtils.highlightBlock(target, new Color(0,255,255,100), partialTicks, true); + } + RenderUtils.highlightBlock(waterBoard.getToggleableMap().get("mainStream").getBlockPos(), new Color(0,255,0,255), partialTicks, true); + } + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorWaterPuzzle> { + @Override + public RoomProcessorWaterPuzzle createNew(DungeonRoom dungeonRoom) { + RoomProcessorWaterPuzzle defaultRoomProcessor = new RoomProcessorWaterPuzzle(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/Route.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/Route.java new file mode 100755 index 00000000..ef6fb6af --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/Route.java @@ -0,0 +1,60 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle; + +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes.WaterNodeEnd; +import lombok.Data; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +@Data +public class Route implements Cloneable, Comparable { + private Set<WaterNode> nodes = new LinkedHashSet<WaterNode>(); + private List<LeverState> conditionList = new ArrayList<LeverState>(); + private Set<WaterNodeEnd> endingNodes = new HashSet<WaterNodeEnd>(); + + + private int matches = 0; + private int stateFlops = 0; + private int notMatches = 0; + + public double calculateCost() { + return (1.0/matches) * 50 + stateFlops * 20 + notMatches * 10000; + } + + @Override + protected Route clone() { + Route r = new Route(); + r.getNodes().addAll(nodes); + r.getConditionList().addAll(conditionList); + r.getEndingNodes().addAll(endingNodes); + return r; + } + + @Override + public int compareTo(@NotNull Object o) { + if (o instanceof Route) { + double var0 = calculateCost(); + double var1 = ((Route)o).calculateCost(); + return Double.compare(var0, var1); + } + return 0; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/SwitchData.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/SwitchData.java new file mode 100755 index 00000000..53bb2bb8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/SwitchData.java @@ -0,0 +1,46 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle; + +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes.WaterNodeStart; +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes.WaterNodeToggleable; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class SwitchData { + private WaterBoard waterBoard; + + private BlockPos switchLoc; + private BlockPos blockLoc; + + private String blockId; + + public boolean getCurrentState(World w) { + WaterNode waterNode = waterBoard.getToggleableMap().get(blockId); + if (waterNode instanceof WaterNodeStart) + return ((WaterNodeStart) waterNode).isTriggered(w); + else if (waterNode instanceof WaterNodeToggleable) + return ((WaterNodeToggleable) waterNode).isTriggered(w); + return false; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterBoard.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterBoard.java new file mode 100755 index 00000000..35979738 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterBoard.java @@ -0,0 +1,424 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes.*; +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes.*; +import lombok.Getter; +import net.minecraft.block.Block; +import net.minecraft.block.BlockLever; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Tuple; +import net.minecraft.world.World; + +import java.util.*; +import java.util.List; + +public class WaterBoard { + @Getter + WaterNode[][] board; + RoomProcessorWaterPuzzle waterPuzzle; + + private final OffsetPointSet frontPlate; + private final OffsetPointSet backPlate; + private final OffsetPointSet levers; + private final OffsetPointSet doors; + private final OffsetPoint lever; + + @Getter + private final List<SwitchData> switchData = new ArrayList<SwitchData>(); + @Getter + private final Map<String, SwitchData> validSwitches = new HashMap<String, SwitchData>(); + + private WaterNodeStart waterNodeStart; + private final Map<String, WaterNodeEnd> waterNodeEndMap = new HashMap<String, WaterNodeEnd>(); + + @Getter + private final Map<String, WaterNode> toggleableMap = new HashMap<String, WaterNode>(); + + @Getter + private Set<String> reqOpen = new HashSet<String>(); + @Getter + private Route currentRoute; + @Getter + private List<BlockPos> target; + @Getter + private List<String> target2; + + public WaterBoard(RoomProcessorWaterPuzzle roomProcessorWaterPuzzle, OffsetPointSet frontPlate, OffsetPointSet backPlate, OffsetPointSet levers, OffsetPointSet doors, OffsetPoint leverMain) { + this.waterPuzzle = roomProcessorWaterPuzzle; + this.frontPlate = frontPlate; + this.backPlate = backPlate; + this.levers = levers; + this.doors = doors; + this.lever = leverMain; + + buildLeverStates(); + buildNodes(); + } + + private void buildLeverStates(){ + for (OffsetPoint offsetPoint : levers.getOffsetPointList()) { + if (offsetPoint.getBlock(waterPuzzle.getDungeonRoom()) == Blocks.lever){ + BlockPos pos = offsetPoint.getBlockPos(waterPuzzle.getDungeonRoom()); + World w= waterPuzzle.getDungeonRoom().getContext().getWorld(); + BlockLever.EnumOrientation enumOrientation = w.getBlockState(pos).getValue(BlockLever.FACING); + EnumFacing enumFacing = enumOrientation.getFacing(); + BlockPos newPos = pos.add(-enumFacing.getDirectionVec().getX(),0,-enumFacing.getDirectionVec().getZ()); + + int id = Block.getIdFromBlock(w.getChunkFromBlockCoords(newPos).getBlock(newPos)); + int data = w.getChunkFromBlockCoords(newPos).getBlockMetadata(newPos); + + SwitchData sw; + switchData.add(sw = new SwitchData(this, pos,newPos,id+":"+data)); + validSwitches.put(id+":"+data, sw); + } + } + SwitchData sw; + switchData.add(sw = new SwitchData(this, lever.getBlockPos(waterPuzzle.getDungeonRoom()),lever.getBlockPos(waterPuzzle.getDungeonRoom()).add(0,-1,0),"mainStream")); + validSwitches.put("mainStream", sw); + } + + public void tick() { + Set<String> doorsToOpen = new HashSet<String>(); + for (OffsetPoint offsetPoint : doors.getOffsetPointList()) { + Block b =offsetPoint.getBlock(waterPuzzle.getDungeonRoom()); + if (b != Blocks.air) { + doorsToOpen.add(Block.getIdFromBlock(b)+":"+offsetPoint.getData(waterPuzzle.getDungeonRoom())); + } + } +// if (!(reqOpen.containsAll(doorsToOpen) && doorsToOpen.containsAll(reqOpen))) { + reqOpen = doorsToOpen; + if (doorsToOpen.size() != 0) { + Set<WaterNodeEnd> ends = new HashSet<WaterNodeEnd>(); + for (String s : doorsToOpen) { + ends.add(waterNodeEndMap.get(s)); + } + currentRoute = getBestRoute(ends); +// { +// +// Set<LeverState> currentState = new HashSet<LeverState>(); +// World w = waterPuzzle.getDungeonRoom().getContext().getWorld(); +// for (SwitchData switchDatum : this.switchData) { +// currentState.add(new LeverState(switchDatum.getBlockId(), switchDatum.getCurrentState(w))); +// } +// currentRoute = simulate(currentState); +// } + + target = new ArrayList<BlockPos>(); + target2 = new ArrayList<String>(); + if (currentRoute != null) { + for (WaterNodeEnd endingNode : currentRoute.getEndingNodes()) { + target.add(endingNode.getBlockPos()); + target2.add(endingNode.getResultId()); + } + } + } +// } + } + + public Route getBestRoute(Set<WaterNodeEnd> potentialEnds) { + int totalStates = (int) Math.pow(2, validSwitches.size() - 1); + List<SwitchData> switchData = new ArrayList<SwitchData>(); + Set<LeverState> currentState = new HashSet<LeverState>(); + World w = waterPuzzle.getDungeonRoom().getContext().getWorld(); + for (SwitchData switchDatum : this.switchData) { + if (!switchDatum.getBlockId().equals("mainStream")) { + switchData.add(switchDatum); + } + currentState.add(new LeverState(switchDatum.getBlockId(), switchDatum.getCurrentState(w))); + } + PriorityQueue<Route> routes = new PriorityQueue<Route>(); + + for (int i = 0; i < totalStates; i++) { + Set<LeverState> states = new HashSet<LeverState>(); + for (int i1 = 0; i1 < switchData.size(); i1++) { + states.add(new LeverState(switchData.get(i1).getBlockId(), ((i >> i1) & 0x1) > 0)); + } + states.add(new LeverState("mainStream", true)); + + Route r = simulate(states); + + for (LeverState leverState : currentState) { + if (!states.contains(leverState)) + r.setStateFlops(r.getStateFlops() + 1); + } + for (WaterNodeEnd potentialEnd : r.getEndingNodes()) { + if (potentialEnds.contains(potentialEnd)) { + r.setMatches(r.getMatches() + 1); + } else { + r.setNotMatches(r.getNotMatches() + 1); + } + } + if (r.getMatches() > 0) + routes.add(r); + } + + + return routes.peek(); + } + + public Route simulate(Set<LeverState> leverStates) { + leverStates.add(null); + Route r = new Route(); + final Queue<WaterNode> toGoDownTo = new LinkedList<WaterNode>(); + Set<WaterNode> searched = new HashSet<WaterNode>(); + Set<LeverState> waterBlockingStates = new HashSet<LeverState>(); + World w = waterPuzzle.getDungeonRoom().getContext().getWorld(); +// toGoDownTo.add(getNodeAt(waterNodeStart.getX(), waterNodeStart.getY() + 1)); + { + Queue<Tuple<WaterNode, Boolean>> toGo = new LinkedList<>(); + toGo.add(new Tuple<>(waterNodeStart, true)); + toGoDownTo.add(getNodeAt(waterNodeStart.getX(), waterNodeStart.getY() + 1)); + Set<WaterNode> visited = new HashSet<>(); + while (!toGo.isEmpty()) { + Tuple<WaterNode, Boolean> waterNode = toGo.poll(); + if (waterNode.getFirst() == null) continue; + if (visited.contains(waterNode.getFirst())) continue; + if (!waterNode.getFirst().canWaterGoThrough()) continue; + if (waterNode.getFirst() instanceof WaterNodeEnd) continue; + visited.add(waterNode.getFirst()); + + boolean water = waterNode.getFirst().isWaterFilled(w); + if (water && !waterNode.getSecond()) { + toGoDownTo.add(getNodeAt(waterNode.getFirst().getX(), waterNode.getFirst().getY())); + } + + int x = waterNode.getFirst().getX(), y = waterNode.getFirst().getY(); + toGo.add(new Tuple<>(getNodeAt(x+1, y), water)); + toGo.add(new Tuple<>(getNodeAt(x-1, y), water)); + toGo.add(new Tuple<>(getNodeAt(x, y+1), water)); + } + } + while (!toGoDownTo.isEmpty()) { + WaterNode asd = toGoDownTo.poll(); + if (asd == null) continue; + if (searched.contains(asd)) continue; + searched.add(asd); + + if (asd instanceof WaterNodeEnd) { + if (!asd.isWaterFilled(w)) + r.getEndingNodes().add((WaterNodeEnd) asd); + continue; + } + + r.getNodes().add(asd); + + if (asd.isWaterFilled(w) && ( + (getNodeAt(asd.getX() + 1, asd.getY()) != null && getNodeAt(asd.getX() + 1, asd.getY()).isWaterFilled(w)) + || (getNodeAt(asd.getX() - 1, asd.getY()) != null && getNodeAt(asd.getX() - 1, asd.getY()).isWaterFilled(w)))) { + boolean followWater = getNodeAt(asd.getX() - 1, asd.getY()) != null && leverStates.contains(getNodeAt(asd.getX() - 1, asd.getY()).getCondition()) + && getNodeAt(asd.getX() - 2, asd.getY()) != null && leverStates.contains(getNodeAt(asd.getX() - 2, asd.getY()).getCondition()); + for (int i = asd.getX(); i < asd.getX() + 8; i++) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere == null) break; + if (followWater && !nodehere.isWaterFilled(w)) break; + if (!nodehere.canWaterGoThrough()) break; + if (!leverStates.contains(nodehere.getCondition()) && !nodehere.isWaterFilled(w)) break; + if (nodehere.getCondition() != null && leverStates.contains(nodehere.getCondition().invert()) && nodehere.isWaterFilled(w)) waterBlockingStates.add(nodehere.getCondition().invert()); + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (i != asd.getX()) + followWater = nodehere.isWaterFilled(w) && (down == null || (down.canWaterGoThrough() && leverStates.contains(down.getCondition()))); + r.getNodes().add(nodehere); + if (down != null && down.canWaterGoThrough() && down.getCondition() != null && leverStates.contains(down.getCondition().invert())) { + waterBlockingStates.add(down.getCondition().invert()); + } + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())) || down.isWaterFilled(w))) { + toGoDownTo.add(down); + if (!followWater) break; + } + } + followWater = getNodeAt(asd.getX() +1, asd.getY()) != null && leverStates.contains(getNodeAt(asd.getX() + 1, asd.getY()).getCondition()) + && getNodeAt(asd.getX() +2, asd.getY()) != null && leverStates.contains(getNodeAt(asd.getX() + 2, asd.getY()).getCondition()); + for (int i = asd.getX(); i > asd.getX() - 8; i--) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere == null) break; + if (followWater && !nodehere.isWaterFilled(w)) break; + if (!nodehere.canWaterGoThrough()) break; + if (!leverStates.contains(nodehere.getCondition()) && !nodehere.isWaterFilled(w)) break; + if (nodehere.getCondition() != null && leverStates.contains(nodehere.getCondition().invert()) && nodehere.isWaterFilled(w)) waterBlockingStates.add(nodehere.getCondition().invert()); + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (i != asd.getX()) + followWater = nodehere.isWaterFilled(w) && (down == null || (down.canWaterGoThrough() && leverStates.contains(down.getCondition()))); + r.getNodes().add(nodehere); + if (down != null && down.canWaterGoThrough() && down.getCondition() != null && leverStates.contains(down.getCondition().invert())) { + waterBlockingStates.add(down.getCondition().invert()); + } + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())) || down.isWaterFilled(w))) { + toGoDownTo.add(down); + if (!followWater) break; + } + } + } else { + int minDistToDropRight = 9999; + for (int i = asd.getX(); i < asd.getX() + 8; i++) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere == null) break; + if (!nodehere.canWaterGoThrough()) break; + if (!leverStates.contains(nodehere.getCondition()) && !nodehere.isWaterFilled(w)) break; + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())))) { + int dist = i - asd.getX(); + if (dist < minDistToDropRight) + minDistToDropRight = dist; + break; + } + } + int minDistToDropLeft = 9999; + for (int i = asd.getX(); i > asd.getX() - 8; i--) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere == null) break; + if (!nodehere.canWaterGoThrough()) break; + if (!leverStates.contains(nodehere.getCondition()) && !nodehere.isWaterFilled(w)) break; + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())))) { + int dist = asd.getX() - i; + if (dist < minDistToDropLeft) + minDistToDropLeft = dist; + break; + } + } + + int min = Math.min(minDistToDropRight, minDistToDropLeft); + if (min == 9999) continue; + if (minDistToDropRight == min) { + for (int i = asd.getX(); i <= asd.getX() + minDistToDropRight; i++) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere.getCondition() != null && leverStates.contains(nodehere.getCondition().invert()) && nodehere.isWaterFilled(w)) waterBlockingStates.add(nodehere.getCondition().invert()); + r.getNodes().add(nodehere); + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())) || down.isWaterFilled(w))) { + toGoDownTo.add(down); + } + if (down != null && down.canWaterGoThrough() && down.getCondition() != null && leverStates.contains(down.getCondition().invert())) { + waterBlockingStates.add(down.getCondition().invert()); + } + } + } + if (minDistToDropLeft == min) { + for (int i = asd.getX(); i >= asd.getX() - minDistToDropLeft; i--) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere.getCondition() != null && leverStates.contains(nodehere.getCondition().invert()) && nodehere.isWaterFilled(w)) waterBlockingStates.add(nodehere.getCondition().invert()); + r.getNodes().add(nodehere); + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())) || down.isWaterFilled(w))) { + toGoDownTo.add(down); + } + if (down != null && down.canWaterGoThrough() && down.getCondition() != null && leverStates.contains(down.getCondition().invert())) { + waterBlockingStates.add(down.getCondition().invert()); + } + } + } + } + } + ArrayList<LeverState> state = new ArrayList<LeverState>(waterBlockingStates); + state.remove(null); + Collections.sort(state, new Comparator<LeverState>() { + @Override + public int compare(LeverState leverState, LeverState t1) { + int var0 = toggleableMap.get(leverState.getBlockId()).getY(); + int var1 = toggleableMap.get(t1.getBlockId()).getY(); + return var0 < var1 ? -1 : (var0 == var1 ? 0 : 1); + } + }); + LinkedList<LeverState> states = new LinkedList<LeverState>(state); + for (LeverState ls : leverStates) { + if (!states.contains(ls)) { + states.add(ls); + } + } + states.remove(null); + + + r.setConditionList(states); + return r; + } + + + public WaterNode getNodeAt(int x, int y) { + if (x < 0 || y < 0) return null; + if (x >= board[0].length || y >= board.length) return null; + return board[y][x]; + } + + private void buildNodes() { + List<OffsetPoint> frontPoints = frontPlate.getOffsetPointList(); + List<OffsetPoint> backPoints = backPlate.getOffsetPointList(); + + board = new WaterNode[25][19]; + for (int x = 0; x < 19; x++) { + for (int y = 0; y < 25; y++) { + OffsetPoint front = frontPoints.get(x *25 +y); + OffsetPoint back = backPoints.get(x * 25 +y); + int frontId = Block.getIdFromBlock(front.getBlock(waterPuzzle.getDungeonRoom())); + int backId = Block.getIdFromBlock(back.getBlock(waterPuzzle.getDungeonRoom())); + int frontData = front.getData(waterPuzzle.getDungeonRoom()); + int backData = back.getData(waterPuzzle.getDungeonRoom()); + WaterNode node; + if (validSwitches.containsKey(backId +":"+backData)) { + String resId = backId + ":"+backData; + node = new WaterNodeToggleable(resId, isSwitchActive(validSwitches.get(resId)), front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y); + + toggleableMap.put(resId, node); + } else if (validSwitches.containsKey(frontId +":"+frontData)) { + String resId = frontId +":"+frontData; + node = new WaterNodeToggleable(resId, !isSwitchActive(validSwitches.get(resId)), front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y); + + toggleableMap.put(resId, node); + } else if (frontId == 0 || frontId == 8 || frontId == 9) { + if (y == 24) { + OffsetPoint pos; + if (x != 0) { + pos = frontPoints.get((x-1)*25+y); + } else { + pos = frontPoints.get((x+1) * 25 +y); + } + + int id = Block.getIdFromBlock(pos.getBlock(waterPuzzle.getDungeonRoom())); + int data= pos.getData(waterPuzzle.getDungeonRoom()); + node = new WaterNodeEnd(id+":"+data, front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y); + waterNodeEndMap.put(id+":"+data, (WaterNodeEnd) node); + } else if (y == 2 && x == 9) { + waterNodeStart = (WaterNodeStart) (node = new WaterNodeStart(front.getBlockPos(waterPuzzle.getDungeonRoom()), + frontId != 0 ^ isSwitchActive(validSwitches.get("mainStream")),x,y)); + } else { + node = new WaterNodeAir(front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y); + } + } else { + node = new WaterNodeWall(front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y); + } + board[y][x] =node; + } + } + toggleableMap.put("mainStream", waterNodeStart); + } + + private boolean isSwitchActive(SwitchData switchData) { + BlockPos switch2 = switchData.getSwitchLoc(); + World w= waterPuzzle.getDungeonRoom().getContext().getWorld(); + boolean bool = w.getBlockState(switch2).getValue(BlockLever.POWERED); + return bool; + } + + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterNode.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterNode.java new file mode 100755 index 00000000..78f3f1ca --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterNode.java @@ -0,0 +1,36 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle; + +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +public interface WaterNode { + boolean canWaterGoThrough(); + + // condition for water go + LeverState getCondition(); + + boolean isWaterFilled(World w); + + BlockPos getBlockPos(); + + int getX(); + int getY(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeAir.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeAir.java new file mode 100755 index 00000000..3c654b12 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeAir.java @@ -0,0 +1,59 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes; + +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.LeverState; +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.WaterNode; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class WaterNodeAir implements WaterNode { + BlockPos blockPos; + @Override + public boolean canWaterGoThrough() { + return true; + } + + @Override + public LeverState getCondition() { + return null; + } + + @Override + public boolean isWaterFilled(World w) { + Block b = w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + return b == Blocks.water || b == Blocks.flowing_water; + } + + public BlockPos getBlockPos() { + return blockPos; + } + + private int x,y; + + public String toString() { + return "A"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeEnd.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeEnd.java new file mode 100755 index 00000000..12e1b608 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeEnd.java @@ -0,0 +1,60 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes; + +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.LeverState; +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.WaterNode; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class WaterNodeEnd implements WaterNode { + private String resultId; + BlockPos blockPos; + + @Override + public boolean canWaterGoThrough() { + return true; + } + + @Override + public LeverState getCondition() { + return null; + } + + @Override + public boolean isWaterFilled(World w) { + Block b = w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + return b == Blocks.water || b == Blocks.flowing_water; + } + + public BlockPos getBlockPos() { + return blockPos; + } + private int x,y; + + public String toString() { + return "E"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeStart.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeStart.java new file mode 100755 index 00000000..b03e3a16 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeStart.java @@ -0,0 +1,66 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes; + +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.LeverState; +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.WaterNode; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class WaterNodeStart implements WaterNode { + + private BlockPos blockPos; + private boolean isReversed; + + @Override + public boolean canWaterGoThrough() { + return true; + } + + @Override + public LeverState getCondition() { + return new LeverState("mainStream", !isReversed); + } + + @Override + public boolean isWaterFilled(World w) { + Block b = w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + return b == Blocks.water || b == Blocks.flowing_water; + } + + public boolean isTriggered(World w) { + return isWaterFilled(w); + } + + + public BlockPos getBlockPos() { + return blockPos; + } + private int x,y; + + public String toString() { + return "S"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeToggleable.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeToggleable.java new file mode 100755 index 00000000..e4459f30 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeToggleable.java @@ -0,0 +1,71 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes; + +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.LeverState; +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.WaterNode; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class WaterNodeToggleable implements WaterNode { + private String blockId; + private boolean invert; + + BlockPos blockPos; + + @Override + public boolean canWaterGoThrough() { + return true; + } + + @Override + public LeverState getCondition() { + return new LeverState(blockId, invert); + } + + + @Override + public boolean isWaterFilled(World w) { + Block b = w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + return b == Blocks.water || b == Blocks.flowing_water; + } + private int x,y; + + public boolean isTriggered(World w) { + Block b= w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + + return !(b == Blocks.air || b == Blocks.water || b == Blocks.flowing_water) ^ invert; + } + + + public BlockPos getBlockPos() { + return blockPos; + } + + + public String toString() { + return "T:"+blockId+(invert ? ":Y":":N"); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeWall.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeWall.java new file mode 100755 index 00000000..7e68bffd --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeWall.java @@ -0,0 +1,62 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes; + +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.LeverState; +import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.WaterNode; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class WaterNodeWall implements WaterNode { + + BlockPos blockPos; + @Override + public boolean canWaterGoThrough() { + return false; + } + + @Override + public LeverState getCondition() { + return null; + } + + + @Override + public boolean isWaterFilled(World w) { + Block b = w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + return b == Blocks.water || b == Blocks.flowing_water; + } + + private int x,y; + + public BlockPos getBlockPos() { + return blockPos; + } + + + public String toString() { + return "W"; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordActivity.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordActivity.java new file mode 100644 index 00000000..f25022f2 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordActivity.java @@ -0,0 +1,72 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.rpc; + +import kr.syeyoung.dungeonsguide.gamesdk.GameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordActivity; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityType; +import lombok.Data; + +@Data +public class JDiscordActivity { + private EDiscordActivityType activityType; + private long applicationId; + private String name, state, details; + private long start, end; + private String largeImage, largeText, smallImage, smallText; + private String partyId; + private int partyCurr, partyMax; + private String matchSecret, joinSecret, spectateSecret; + private boolean instance; + + public static JDiscordActivity fromJNA(DiscordActivity discordActivity) { + if (discordActivity == null) return null; + JDiscordActivity jDiscordActivity = new JDiscordActivity(); + jDiscordActivity.activityType = discordActivity.activityType; + jDiscordActivity.applicationId = discordActivity.applicationId.longValue(); + jDiscordActivity.name = GameSDK.readString(discordActivity.name); + jDiscordActivity.state = GameSDK.readString(discordActivity.state); + jDiscordActivity.details = GameSDK.readString(discordActivity.details); + if (discordActivity.assets != null) { + jDiscordActivity.largeImage = GameSDK.readString(discordActivity.assets.large_image); + jDiscordActivity.largeText = GameSDK.readString(discordActivity.assets.large_text); + jDiscordActivity.smallImage = GameSDK.readString(discordActivity.assets.small_image); + jDiscordActivity.smallText = GameSDK.readString(discordActivity.assets.small_text); + } + if (discordActivity.timestamps != null) { + jDiscordActivity.start = discordActivity.timestamps.start.longValue(); + jDiscordActivity.end = discordActivity.timestamps.end.longValue(); + } + if (discordActivity.secrets != null) { + jDiscordActivity.matchSecret= GameSDK.readString(discordActivity.secrets.match); + jDiscordActivity.joinSecret = GameSDK.readString(discordActivity.secrets.join); + jDiscordActivity.spectateSecret = GameSDK.readString(discordActivity.secrets.spectate); + } + if (discordActivity.party != null) { + jDiscordActivity.partyId = GameSDK.readString(discordActivity.party.id); + if (discordActivity.party.discordActivityParty != null) { + jDiscordActivity.partyCurr = discordActivity.party.discordActivityParty.current_size.intValue(); + jDiscordActivity.partyMax = discordActivity.party.discordActivityParty.max_size.intValue(); + } + } + jDiscordActivity.instance = discordActivity.instance; + + return jDiscordActivity; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordRelation.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordRelation.java new file mode 100644 index 00000000..3086c936 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordRelation.java @@ -0,0 +1,42 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.rpc; + +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordRelationship; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordRelationshipType; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordStatus; +import lombok.Data; + +@Data +public class JDiscordRelation { + private EDiscordRelationshipType discordRelationshipType; + private EDiscordStatus status; + private JDiscordActivity discordActivity; + private JDiscordUser discordUser; + + public static JDiscordRelation fromJNA(DiscordRelationship relationship) { + JDiscordRelation jDiscordRelation = new JDiscordRelation(); + jDiscordRelation.discordUser = JDiscordUser.fromJNA(relationship.user); + jDiscordRelation.discordActivity = JDiscordActivity.fromJNA(relationship.presence.activity); + jDiscordRelation.status = relationship.presence.status; + jDiscordRelation.discordRelationshipType = relationship.type; + return jDiscordRelation; + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordUser.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordUser.java new file mode 100644 index 00000000..635ac405 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordUser.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.rpc; + +import kr.syeyoung.dungeonsguide.gamesdk.GameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordUser; +import lombok.Data; + +@Data +public class JDiscordUser { + private long id; + private String username, discriminator, avatar; + private boolean bot; + + public static JDiscordUser fromJNA(DiscordUser discordUser) { + JDiscordUser jDiscordUser = new JDiscordUser(); + jDiscordUser.id = discordUser.id.longValue(); + jDiscordUser.username = GameSDK.readString(discordUser.username); + jDiscordUser.discriminator = GameSDK.readString(discordUser.discriminator); + jDiscordUser.avatar = GameSDK.readString(discordUser.avatar); + jDiscordUser.bot = discordUser.bot; + return jDiscordUser; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java new file mode 100644 index 00000000..ef794b14 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java @@ -0,0 +1,254 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.rpc; + +import com.sun.jna.Pointer; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.PointerByReference; +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.SkyblockStatus; +import kr.syeyoung.dungeonsguide.chat.PartyContext; +import kr.syeyoung.dungeonsguide.chat.PartyManager; +import kr.syeyoung.dungeonsguide.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.events.DiscordUserJoinRequestEvent; +import kr.syeyoung.dungeonsguide.events.DiscordUserUpdateEvent; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.gamesdk.GameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK; +import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.*; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityJoinRequestReply; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordCreateFlags; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordLogLevel; +import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult; +import kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct.*; +import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.*; +import lombok.Getter; +import net.minecraftforge.common.MinecraftForge; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +public class RichPresenceManager implements Runnable { + public static RichPresenceManager INSTANCE = new RichPresenceManager(); + private Thread t = new Thread(this); + + public RichPresenceManager() { + t.start(); + } + @Getter + private NativeGameSDK nativeGameSDK; + @Getter + private IDiscordCore iDiscordCore; + private IDiscordActivityManager activityManager; + private IDiscordRelationshipManager relationshipManager; + private IDiscordActivityEvents.ByReference callbacks; + private IDiscordRelationshipEvents.ByReference relation_callbacks; + + @Getter + private Map<Long, JDiscordRelation> relationMap = new HashMap<>(); + + private boolean ready = false; + + @Getter + private int lastSetupCode = -99999; + public int setup() { + ready = false; + if (iDiscordCore != null) { + iDiscordCore.Destroy.destroy(iDiscordCore); + iDiscordCore = null; + activityManager = null; callbacks = null; relation_callbacks = null; relationMap.clear(); + } + + nativeGameSDK = GameSDK.getNativeGameSDK(); + if (nativeGameSDK == null) return -9999; + DiscordCreateParams discordCreateParams = new DiscordCreateParams(); + discordCreateParams.flags = new UInt64(EDiscordCreateFlags.DiscordCreateFlags_NoRequireDiscord.getValue()); + discordCreateParams.client_id = new DiscordClientID(816298079732498473L); + + callbacks = new IDiscordActivityEvents.ByReference(); + callbacks.OnActivityInvite = (eventData, type, user, activity) -> { + try { + MinecraftForge.EVENT_BUS.post(new DiscordUserJoinRequestEvent(user, true)); + } catch (Throwable t) { + t.printStackTrace(); + } + System.out.println("Received Join Request from "+user.id.longValue()+" ("+GameSDK.readString(user.username)+")"); + }; + callbacks.OnActivityJoin = (eventData, secret) -> { + PartyManager.INSTANCE.joinWithToken(secret); + System.out.println("Trying to join with token "+secret); + }; + callbacks.OnActivityJoinRequest = (eventData, user) -> { + try { + MinecraftForge.EVENT_BUS.post(new DiscordUserJoinRequestEvent(user, false)); + } catch (Throwable t) { + t.printStackTrace(); + } + System.out.println("Received Join Request from "+user.id.longValue()+" - "+GameSDK.readString(user.username)); + }; + callbacks.OnActivitySpectate = (eventData, secret) -> { + }; + callbacks.write(); + + relation_callbacks = new IDiscordRelationshipEvents.ByReference(); + relation_callbacks.OnRefresh = (p) -> { + try { + ready = true; + IDiscordRelationshipManager iDiscordRelationshipManager = iDiscordCore.GetRelationshipManager.getRelationshipManager(iDiscordCore); + iDiscordRelationshipManager.Filter.filter(iDiscordRelationshipManager, Pointer.NULL, (d, relation) -> true); + IntByReference intByReference = new IntByReference(); + iDiscordRelationshipManager.Count.count(iDiscordRelationshipManager, intByReference); + int count = intByReference.getValue(); + relationMap.clear(); + for (int i = 0; i < count; i++) { + DiscordRelationship discordRelationship = new DiscordRelationship(); + iDiscordRelationshipManager.GetAt.getAt(iDiscordRelationshipManager, new UInt32(i), discordRelationship); + + JDiscordRelation jDiscordRelation = JDiscordRelation.fromJNA(discordRelationship); + relationMap.put(jDiscordRelation.getDiscordUser().getId(), jDiscordRelation); + } + } catch (Throwable e) {e.printStackTrace();} + }; + relation_callbacks.OnRelationshipUpdate = (p, rel) -> { + try { + JDiscordRelation jDiscordRelation = JDiscordRelation.fromJNA(rel); + JDiscordRelation prev = relationMap.put(jDiscordRelation.getDiscordUser().getId(), jDiscordRelation); + MinecraftForge.EVENT_BUS.post(new DiscordUserUpdateEvent(prev, jDiscordRelation)); + } catch (Throwable t) { + t.printStackTrace(); + } + }; + relation_callbacks.write(); + + discordCreateParams.activity_events = callbacks; + discordCreateParams.relationship_events = relation_callbacks; // 96 + + PointerByReference pointerByReference = new PointerByReference(); + discordCreateParams.write(); + + EDiscordResult eDiscordResult = nativeGameSDK.DiscordCreate(new DiscordVersion(NativeGameSDK.DISCORD_VERSION), discordCreateParams, pointerByReference); + if (eDiscordResult != EDiscordResult.DiscordResult_Ok) return eDiscordResult.getValue(); + if (pointerByReference.getValue() == Pointer.NULL) return -9998; + iDiscordCore = new IDiscordCore(pointerByReference.getValue()); + + iDiscordCore.SetLogHook.setLogHook(iDiscordCore, EDiscordLogLevel.DiscordLogLevel_Debug, Pointer.NULL, new IDiscordCore.LogHook() { + @Override + public void hook(Pointer hookData, EDiscordLogLevel level, String message) { + System.out.println(message+" - "+level+" - "+hookData); + } + }); + + activityManager = iDiscordCore.GetActivityManager.getActivityManager(iDiscordCore); + relationshipManager = iDiscordCore.GetRelationshipManager.getRelationshipManager(iDiscordCore); + + return eDiscordResult.getValue(); + } + + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + public void respond(DiscordSnowflake userID, EDiscordActivityJoinRequestReply reply) { + if (activityManager == null) return; + activityManager.SendRequestReply.sendRequestReply(activityManager, userID, reply, Pointer.NULL, (callbackData, result) -> { + System.out.println("Discord Returned "+result+" For Replying "+reply+" To "+userID.longValue()+"L"); + }); + } + + public void accept(DiscordSnowflake userID) { + if (activityManager == null) return; + activityManager.AcceptInvite.acceptInvite(activityManager, userID, Pointer.NULL, (callbackData, result) -> { + System.out.println("Discord Returned "+result+" For Accepting invite from "+userID.longValue()+"L"); + }); + } + public void updatePresence() { + if (!skyblockStatus.isOnHypixel() || !FeatureRegistry.DISCORD_RICHPRESENCE.isEnabled() || (!skyblockStatus.isOnSkyblock() && FeatureRegistry.DISCORD_RICHPRESENCE.<Boolean>getParameter("disablenotskyblock").getValue())) { + activityManager.ClearActivity.clearActivity(activityManager, Pointer.NULL, (callbackData, result) -> { + }); + } else { + String name = skyblockStatus.getDungeonName() == null ? "" : skyblockStatus.getDungeonName(); + if (!skyblockStatus.isOnSkyblock()) name ="Somewhere on Hypixel"; + if (name.trim().equals("Your Island")) name = "Private Island"; + + DiscordActivity latestDiscordActivity = new DiscordActivity(); + latestDiscordActivity.assets = new DiscordActivityAssets(); + latestDiscordActivity.secrets = new DiscordActivitySecrets(); + latestDiscordActivity.party = new DiscordActivityParty(); + latestDiscordActivity.party.discordActivityParty = new DiscordPartySize(); + latestDiscordActivity.timestamps = new DiscordActivityTimestamps(); + GameSDK.writeString(latestDiscordActivity.assets.large_image, "mort"); + GameSDK.writeString(latestDiscordActivity.assets.large_text, "mort"); + GameSDK.writeString(latestDiscordActivity.state, name); + + GameSDK.writeString(latestDiscordActivity.party.id, Optional.ofNullable( PartyManager.INSTANCE.getPartyContext()).map(PartyContext::getPartyID).orElse("")); + latestDiscordActivity.party.discordActivityParty.current_size = new Int32(Optional.ofNullable(PartyManager.INSTANCE.getPartyContext()).map(PartyContext::getPartyRawMembers).map(Set::size).orElse(1)); + latestDiscordActivity.party.discordActivityParty.max_size = new Int32(PartyManager.INSTANCE.getMaxParty()); + + if (skyblockStatus.getContext() != null) { + DungeonContext dungeonContext = skyblockStatus.getContext(); + long init = dungeonContext.getInit(); + latestDiscordActivity.timestamps.start = new DiscordTimestamp(init); + + if (dungeonContext.getBossfightProcessor() != null) { + GameSDK.writeString(latestDiscordActivity.details, "Fighting "+dungeonContext.getBossfightProcessor().getBossName()+": "+dungeonContext.getBossfightProcessor().getCurrentPhase()); + } else { + GameSDK.writeString(latestDiscordActivity.details, "Clearing Rooms"); + } + } else { + latestDiscordActivity.timestamps.start = new DiscordTimestamp(0); + GameSDK.writeString(latestDiscordActivity.details, "Dungeons Guide"); + } + if (PartyManager.INSTANCE.getAskToJoinSecret() != null) { + GameSDK.writeString(latestDiscordActivity.secrets.join, PartyManager.INSTANCE.getAskToJoinSecret()); + } else { + GameSDK.writeString(latestDiscordActivity.secrets.join, ""); + } + activityManager.UpdateActivity.updateActivity(activityManager, latestDiscordActivity, Pointer.NULL, (callbackData, result) -> { + }); + } + } + + @Override + public void run() { + boolean setup = true; + int counter = 0; + while(!Thread.interrupted()) { + try { + if (iDiscordCore == null || setup) { + long lastSetup = lastSetupCode; + lastSetupCode = setup(); + if (lastSetup != lastSetupCode) + System.out.println("Discord returned "+lastSetupCode+" for setup "+EDiscordResult.fromValue(lastSetupCode)); + setup = lastSetupCode != EDiscordResult.DiscordResult_Ok.getValue(); + counter = 0; + } else { + EDiscordResult eDiscordResult = iDiscordCore.RunCallbacks.runCallbacks(iDiscordCore); + if (eDiscordResult != EDiscordResult.DiscordResult_Ok) { + setup = true; + } else if (ready){ + if (counter == 0) + updatePresence(); + if (++counter == 15) counter = 0; + } + } + Thread.sleep(16L); + } catch (Exception e) {e.printStackTrace();} + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/CloseListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/CloseListener.java new file mode 100644 index 00000000..ba156b3b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/CloseListener.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.stomp; + +public interface CloseListener { + void onClose(int code, String reason, boolean remote); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompClient.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompClient.java new file mode 100644 index 00000000..c52a2dd0 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompClient.java @@ -0,0 +1,181 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.stomp; + +import lombok.Getter; +import org.java_websocket.client.WebSocketClient; +import org.java_websocket.handshake.ServerHandshake; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public class StompClient extends WebSocketClient implements StompInterface { + public StompClient(URI serverUri, final String token, CloseListener closeListener) throws Exception { + super(serverUri); + this.closeListener = closeListener; + addHeader("Authorization", token); + + System.out.println("connecting websocket"); + if (!connectBlocking()) { + throw new RuntimeException("Can't connect to ws"); + } + System.out.println("connected, stomp handshake"); + while(this.stompClientStatus == StompClientStatus.CONNECTING); + System.out.println("fully connected"); + } + private final CloseListener closeListener; + + @Getter + private volatile StompClientStatus stompClientStatus = StompClientStatus.CONNECTING; + + @Getter + private StompPayload errorPayload; + + private ScheduledFuture heartbeat = null; + + private static final ScheduledExecutorService ex = Executors.newScheduledThreadPool(1); + + @Override + public void onOpen(ServerHandshake handshakedata) { + send(new StompPayload().method(StompHeader.CONNECT) + .header("accept-version","1.2") + .header("heart-beat", "30000,30000") + .header("host",uri.getHost()).getBuilt() + ); + } + + @Override + public void onMessage(String message) { + try { + StompPayload payload = StompPayload.parse(message); + if (payload.method() == StompHeader.CONNECTED) { + stompClientStatus = StompClientStatus.CONNECTED; + + String heartbeat = payload.headers().get("heart-beat"); + if (heartbeat != null) { +// int sx = Integer.parseInt(heartbeat.split(",")[0]); +// int sy = Integer.parseInt(heartbeat.split(",")[1]); +// +// if (sy == 0) return; + int heartbeatMS = 30000; + this.heartbeat = ex.scheduleAtFixedRate(() -> { + send("\n"); + }, heartbeatMS-1000, heartbeatMS-1000, TimeUnit.MILLISECONDS); + } + + } else if (payload.method() == StompHeader.ERROR) { + errorPayload = payload; + stompClientStatus = StompClientStatus.ERROR; + this.close(); + } else if (payload.method() == StompHeader.MESSAGE) { + // mesage + StompSubscription stompSubscription = stompSubscriptionMap.get(Integer.parseInt(payload.headers().get("subscription"))); + try { + stompSubscription.getStompMessageHandler().handle(this, payload); + if (stompSubscription.getAckMode() != StompSubscription.AckMode.AUTO) { + send(new StompPayload().method(StompHeader.ACK) + .header("id",payload.headers().get("ack")).getBuilt() + ); + } + } catch (Exception e) { + e.printStackTrace(); + if (stompSubscription.getAckMode() != StompSubscription.AckMode.AUTO) { + send(new StompPayload().method(StompHeader.NACK) + .header("id",payload.headers().get("ack")).getBuilt() + ); + } + } + } else if (payload.method() == StompHeader.RECEIPT) { + String receipt_id = payload.headers().get("receipt-id"); + StompPayload payload1 = receiptMap.remove(Integer.parseInt(receipt_id)); + if (payload1.method() == StompHeader.DISCONNECT) { + stompClientStatus = StompClientStatus.DISCONNECTED; + close(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onClose(int code, String reason, boolean remote) { + if (heartbeat != null) heartbeat.cancel(true); + closeListener.onClose(code, reason, remote); + } + + @Override + public void onError(Exception ex) { + ex.printStackTrace(); + } + + private final Map<Integer, StompSubscription> stompSubscriptionMap = new HashMap<Integer, StompSubscription>(); + private final Map<Integer, StompPayload> receiptMap = new HashMap<Integer, StompPayload>(); + + private int idIncrement = 0; + + @Override + public void send(StompPayload payload) { + if (stompClientStatus != StompClientStatus.CONNECTED) throw new IllegalStateException("not connected"); + payload.method(StompHeader.SEND); + if (payload.headers().get("receipt") != null) + receiptMap.put(Integer.parseInt(payload.headers().get("receipt")), payload); + send(payload.getBuilt()); + } + + @Override + public void subscribe(StompSubscription stompSubscription) { + if (stompClientStatus != StompClientStatus.CONNECTED) throw new IllegalStateException("not connected"); + stompSubscription.setId(++idIncrement); + + send(new StompPayload().method(StompHeader.SUBSCRIBE) + .header("id",String.valueOf(stompSubscription.getId())) + .header("destination", stompSubscription.getDestination()) + .header("ack", stompSubscription.getAckMode().getValue()).getBuilt() + ); + + stompSubscriptionMap.put(stompSubscription.getId(), stompSubscription); + } + + @Override + public void unsubscribe(StompSubscription stompSubscription) { + if (stompClientStatus != StompClientStatus.CONNECTED) throw new IllegalStateException("not connected"); + send(new StompPayload().method(StompHeader.UNSUBSCRIBE) + .header("id",String.valueOf(stompSubscription.getId())).getBuilt() + ); + stompSubscriptionMap.remove(stompSubscription.getId()); + } + + @Override + public void disconnect() { + if (stompClientStatus != StompClientStatus.CONNECTED) throw new IllegalStateException("not connected"); + StompPayload stompPayload; + stompClientStatus =StompClientStatus.DISCONNECTING; + send((stompPayload = new StompPayload().method(StompHeader.DISCONNECT) + .header("receipt", String.valueOf(++idIncrement))) + .getBuilt() + ); + receiptMap.put(idIncrement, stompPayload); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompClientStatus.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompClientStatus.java new file mode 100644 index 00000000..9839c61b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompClientStatus.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.stomp; + +public enum StompClientStatus { + CONNECTING, CONNECTED, ERROR, DISCONNECTING, DISCONNECTED +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompHeader.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompHeader.java new file mode 100644 index 00000000..4f00e499 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompHeader.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.stomp; + +public enum StompHeader { + SEND, SUBSCRIBE, UNSUBSCRIBE, BEGIN, COMMIT, ABORT, ACK, NACK, DISCONNECT, CONNECT, STOMP, CONNECTED, MESSAGE, RECEIPT, ERROR +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompInterface.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompInterface.java new file mode 100644 index 00000000..a7410218 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompInterface.java @@ -0,0 +1,26 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.stomp; + +public interface StompInterface { + void send(StompPayload payload); + void subscribe(StompSubscription stompSubscription); + void unsubscribe(StompSubscription stompSubscription); + void disconnect(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompMessageHandler.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompMessageHandler.java new file mode 100644 index 00000000..4610c686 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompMessageHandler.java @@ -0,0 +1,23 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.stomp; + +public interface StompMessageHandler { + void handle(StompInterface stompInterface, StompPayload stompPayload); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompPayload.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompPayload.java new file mode 100644 index 00000000..72eac419 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompPayload.java @@ -0,0 +1,85 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.stomp; + +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.*; + +@Data +@Accessors(chain = true, fluent = true) +public class StompPayload { + private StompHeader method; + private Map<String, String> headers = new HashMap<String, String>(); + private String payload; + + public StompPayload header(String key, String value) { + headers.put(key, value); + return this; + } + + public String getBuilt() { + StringBuilder sb = new StringBuilder(); + sb.append(method.name()); + sb.append("\n"); + for (Map.Entry<String, String> stringStringEntry : headers.entrySet()) { + sb.append(stringStringEntry.getKey()); + sb.append(":"); + sb.append(stringStringEntry.getValue()); + sb.append("\n"); + if (stringStringEntry.getKey().contains(":")) throw new IllegalStateException("Illegal Character : inside headers"); + if (stringStringEntry.getValue().contains(":")) throw new IllegalStateException("Illegal Character : inside headers"); + } + sb.append("\n"); + if (payload != null) + sb.append(payload); + sb.append((char) 0); + if (FeatureRegistry.DEBUG.isEnabled()) System.out.println("Sending.. "+sb.toString()); + return sb.toString(); + } + + public static StompPayload parse(String payload) { + if (FeatureRegistry.DEBUG.isEnabled()) System.out.println("Receving.. "+payload); + + Scanner scanner = new Scanner(payload); + StompPayload stompPayload = new StompPayload(); + stompPayload.method = StompHeader.valueOf(scanner.nextLine()); + String line = ""; + while (!(line = scanner.nextLine()).isEmpty()) { + int index = line.indexOf(":"); + if (index == -1) throw new IllegalArgumentException("No : found in headers section"); + String name = line.substring(0, index); + String value; + if (index == line.length() - 1) + value = ""; + else + value = line.substring(index+1); + stompPayload.headers.put(name, value); + } + + List<String> lines = new ArrayList<String>(); + while (scanner.hasNextLine() && !(line = scanner.nextLine()).equals("\0")) { + lines.add(line); + } + stompPayload.payload = String.join("\n", lines); + return stompPayload; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompSubscription.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompSubscription.java new file mode 100644 index 00000000..b6ce928e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompSubscription.java @@ -0,0 +1,41 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.stomp; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; + +@Data +@Builder +public class StompSubscription { + private int id; + private String destination; + private StompMessageHandler stompMessageHandler; + private AckMode ackMode; + + @AllArgsConstructor + public enum AckMode { + AUTO("auto"), CLIENT("client"), CLIENT_INDIVIDUAL("client-individual"); + + @Getter + private final String value; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/AhUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/AhUtils.java new file mode 100644 index 00000000..a9aea9de --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/AhUtils.java @@ -0,0 +1,87 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils; + +import java.security.*; +import java.security.cert.CertificateException; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import kr.syeyoung.dungeonsguide.DungeonsGuide; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.util.Timer; +import java.util.TimerTask; + +public class AhUtils { + public static volatile Map<String, AuctionData> auctions = new HashMap<String, AuctionData>(); + + public static Timer timer = new Timer(); + + public static int totalAuctions = 0; + + public static void registerTimer() { + timer.schedule(new TimerTask() { + public void run() { + try { + AhUtils.loadAuctions(); + } catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException | InvalidAlgorithmParameterException | NoSuchPaddingException | BadPaddingException | KeyStoreException | IllegalBlockSizeException | KeyManagementException e) { + e.printStackTrace(); + } + } + }, 0L, 1800000L); + } + + public static void loadAuctions() throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchPaddingException, BadPaddingException, KeyStoreException, IllegalBlockSizeException, KeyManagementException { + try { + + Map<String, AuctionData> semi_auctions = new HashMap<String, AuctionData>(); + JsonElement object = DungeonsGuide.getDungeonsGuide().getAuthenticator().getJsonSecured("https://dungeons.guide/resource/keys"); + for (JsonElement element : object.getAsJsonArray()) { + JsonObject object1 = element.getAsJsonObject(); + AuctionData auctionData = new AuctionData(object1.get("id").getAsString()); + auctionData.lowestBin = object1.get("lowestBin").getAsInt(); + auctionData.sellPrice = object1.get("sellPrice").getAsInt(); + auctionData.buyPrice = object1.get("buyPrice").getAsInt(); + semi_auctions.put(auctionData.id, auctionData); + } + auctions = semi_auctions; + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public static class AuctionData { + public String id; + + public long lowestBin = -1; + + public int sellPrice = -1; + + public int buyPrice = -1; + + public AuctionData(String id) { + this.id = id; + } + } +}
\ No newline at end of file diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/ArrayUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/ArrayUtils.java new file mode 100755 index 00000000..1afb8597 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/ArrayUtils.java @@ -0,0 +1,40 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils; + +public class ArrayUtils { + public static int[][] rotateCounterClockwise(int[][] arr) { + int[][] res = new int[arr[0].length][arr.length]; + for(int y=0; y<arr.length; y++) { + for (int x = 0; x< arr[0].length; x++) { + res[res.length - x - 1][y] = arr[y][x]; + } + } + return res; + } + public static int[][] rotateClockwise(int[][] arr) { + int[][] res = new int[arr[0].length][arr.length]; + for(int y=0; y<arr.length; y++) { + for (int x = 0; x< arr[0].length; x++) { + res[x][res[0].length - y - 1] = arr[y][x]; + } + } + return res; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/GlStateUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/GlStateUtils.java new file mode 100644 index 00000000..3ee44888 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/GlStateUtils.java @@ -0,0 +1,68 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils; + +import net.minecraft.client.renderer.GlStateManager; + +import java.lang.reflect.Field; +import java.util.*; + +public class GlStateUtils { + public static Map<String, Object> dumpStates() { + Map<String, Object> primitiveDump = new LinkedHashMap<>(); + try { + recursivelyDump(primitiveDump, "GlStateManager", null, GlStateManager.class); + } catch (IllegalAccessException e) { + e.printStackTrace(); + primitiveDump.put("$ERROR", true); + } + return primitiveDump; + } + + public static void printDump(Map<String, Object> dump) { + for (Map.Entry<String, Object> stringObjectEntry : dump.entrySet()) { + System.out.println(stringObjectEntry+": "+stringObjectEntry.getValue()); + } + } + + public static void compareDump(Map<String, Object> dump1, Map<String,Object> dump2) { + Set<String> set = new HashSet<>(); + set.addAll(dump1.keySet()); + set.addAll(dump2.keySet()); + + for (String s : set) { + Object obj1 = dump1.get(s); + Object obj2 = dump2.get(s); + if (!Objects.equals(obj1, obj2)) System.out.println(s+": Prev {"+obj1+"} New {"+obj2+"}"); + } + } + + public static void recursivelyDump(Map<String, Object> primitiveDump, String objPath, Object obj, Class clazz) throws IllegalAccessException { + primitiveDump.put(objPath+".$class", clazz.getName()); + for (Field declaredField : clazz.getDeclaredFields()) { + declaredField.setAccessible(true); + Object fieldData = declaredField.get(obj); + if (fieldData.getClass().getName().startsWith("java.lang")) { + primitiveDump.put(objPath+"."+declaredField.getName(), fieldData); + } else { + recursivelyDump(primitiveDump, objPath+"."+declaredField.getName(), fieldData, fieldData.getClass()); + } + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/MapUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/MapUtils.java new file mode 100755 index 00000000..3336a6b1 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/MapUtils.java @@ -0,0 +1,176 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils; + +import lombok.Getter; +import net.minecraft.block.material.MapColor; + +import javax.vecmath.Vector2d; +import java.awt.*; +import java.awt.image.BufferedImage; + +public class MapUtils { + + private static Color[] colorMasks = new Color[128 * 128]; + @Getter + private static byte[] colors; + + public static void clearMap() { + colorMasks = new Color[128 * 128]; + colors = null; + } + + public static void record(byte[] colors, int x, int y, Color c) { + MapUtils.colors = colors; + colorMasks[y *128 +x] = c; + } + + public static byte getMapColorAt(byte[] colors, int x, int y) { + if (y <0 || y>= 128 || x < 0 || x >= 128) return 0; + return colors[y * 128 +x]; + } + + public static BufferedImage getImage() { + BufferedImage bufferedImage = new BufferedImage(128, 128,BufferedImage.TYPE_INT_ARGB); + if (colors == null) return bufferedImage; + Graphics graphics = bufferedImage.getGraphics(); + for (int y = 0; y < 128; y++) { + for (int x = 0; x <128; x++) { + bufferedImage.setRGB(x,y, getRGBColorAt(colors, x, y)); + if (colorMasks[y * 128 + x] != null) { + graphics.setColor(colorMasks[y *128 +x]); + graphics.drawLine(x,y,x,y); + } + } + } + return bufferedImage; + } + + public static int getRGBColorAt(byte[] colors, int x, int y) { + if (y <0 || y>= 128 || x < 0 || x >= 128) return 0; + int i = y * 128 +x; + int j = colors[i] & 255; + + int theColor; + if (j / 4 == 0) + { + theColor = (i + i / 128 & 1) * 8 + 16 << 24; + } + else + { + theColor = MapColor.mapColorArray[j / 4].getMapColor(j & 3); + } + + return theColor; + } + + public static Point findFirstColorWithIn(byte[] colors, byte color, Rectangle dimension) { + boolean found = true; + for (int y = dimension.y; y < (dimension.y + dimension.height);y++) { + for (int x = dimension.x; x < (dimension.x + dimension.width); x ++) { + if (getMapColorAt(colors, x ,y) == color && found) { + record(colors, x, y, new Color(255, 0, 0, 40)); + return new Point(x,y); + } + found = getMapColorAt(colors, x,y) == 0; + } + } + return null; + } + + public static Point findFirstColorWithInNegate(byte[] colors, byte color, Rectangle dimension) { + for (int y = dimension.y; y < (dimension.y + dimension.height);y++) { + for (int x = dimension.x; x < (dimension.x + dimension.width); x ++) { + if (getMapColorAt(colors, x ,y) != color) { + record(colors, x, y, new Color(255, 0, 0, 40)); + return new Point(x,y); + } + } + } + return null; + } + + public static int getWidthOfColorAt(byte[] colors, byte color, Point point) { + for (int x = point.x; x < 128; x++) { + record(colors, x, point.y, new Color(0, 255, 0, 40)); + if (getMapColorAt(colors, x, point.y) != color) return x - point.x; + } + return 128 - point.x; + } + public static int getHeightOfColorAt(byte[] colors, byte color, Point point) { + for (int y = point.y; y < 128; y++) { + record(colors, point.x, y, new Color(0, 255, 0, 40)); + if (getMapColorAt(colors, point.x,y) != color) return y - point.y; + } + return 128 - point.y; + } + + public static int getLengthOfColorExtending(byte[] colors, byte color, Point basePoint, Vector2d vector2d) { + for (int i = 0; i < 128; i++) { + int x = (int) (basePoint.x + vector2d.x * i); + int y = (int) (basePoint.y + vector2d.y * i); + record(colors, x, y, new Color(0, 0, 255, 40)); + if (getMapColorAt(colors, x,y) != color) return i; + } + return -1; + } + + + public static boolean matches(byte[] colors, byte[] stencil, int targetColor, int x, int y) { + for (int i = y; i < y + stencil.length; i++) { + for (int j = x; j < x + 8; j++) { + boolean current = getMapColorAt(colors, j, i) == targetColor; + boolean expected = ((stencil[i - y] >> (7-(j-x))) & 0x1) == 1; + if (current != expected) return false; + } + } + return true; + } + + public static int readDigit(byte[] colors, int x, int y) { + for (int i = 0; i < NUMBER_STENCIL.length; i++) { + if (matches(colors, NUMBER_STENCIL[i],34, x, y)) return i; + } + return -1; + } + public static int readNumber(byte[] colors, int x, int y, int gap) { + int number = 0; + for (int i = x; i < 128; i += gap) { + int digit = readDigit(colors, i, y); + if (digit != -1) number = number * 10 + digit; + } + return number; + } + + private static final byte[][] NUMBER_STENCIL = { + {0x0, 0x7F, 0x7F, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7F, 0x7F, 0x0}, + {0x0, 0x1E, 0x1E, 0x1E, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0x0}, + {0x0, 0x7F, 0x7F, 0x7F, 0x77, 0x77, 0x7, 0x7F, 0x7F, 0x70, 0x7F, 0x7F, 0x7F, 0x0}, + {0x0, 0x7F, 0x7F, 0x7F, 0x7, 0x7, 0x1F, 0x1F, 0x7, 0x7, 0x7F, 0x7F, 0x7F, 0x0}, + {0x0, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x7F, 0x7F, 0x7F, 0xE, 0xE, 0xE, 0x0}, + {0x0, 0x7F, 0x7F, 0x7F, 0x70, 0x7F, 0x7F, 0x7, 0x77, 0x77, 0x7F, 0x7F, 0x7F, 0x0}, + {0x0, 0x7F, 0x7F, 0x7F, 0x70, 0x7F, 0x7F, 0x77, 0x77, 0x77, 0x77, 0x7F, 0x7F, 0x0}, + {0x0, 0x7F, 0x7F, 0x7F, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x0}, + {0x0, 0x7F, 0x7F, 0x77, 0x77, 0x77, 0x3E, 0x77, 0x77, 0x77, 0x77, 0x7F, 0x7F, 0x0}, + {0x0, 0x7F, 0x7F, 0x77, 0x77, 0x77, 0x77, 0x7F, 0x7F, 0x7, 0x7F, 0x7F, 0x7F, 0x0} + }; + + + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/RenderUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/RenderUtils.java new file mode 100755 index 00000000..fef599dc --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/RenderUtils.java @@ -0,0 +1,1372 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils; + +import kr.syeyoung.dungeonsguide.config.types.AColor; +import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonDoor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.entity.passive.EntityBat; +import net.minecraft.util.*; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import javax.vecmath.Vector3f; +import java.awt.*; +import java.util.List; + +public class RenderUtils { + public static final ResourceLocation icons = new ResourceLocation("textures/gui/icons.png"); + private static final ResourceLocation beaconBeam = new ResourceLocation("textures/entity/beacon_beam.png"); + + /** + * Taken from NotEnoughUpdates under Creative Commons Attribution-NonCommercial 3.0 + * And modified to fit out need. + * https://github.com/Moulberry/NotEnoughUpdates/blob/master/LICENSE + * @author Moulberry + */ + public static void renderBeaconBeam(double x, double y, double z, AColor aColor, float partialTicks) { + Entity player = Minecraft.getMinecraft().thePlayer; + double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks; + double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks; + double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks; +//because of the way 3D rendering is done, all coordinates are relative to the camera. This "resets" the "0,0,0" position to the location that is (0,0,0) in the world. + + + GlStateManager.pushMatrix(); + GlStateManager.translate(-playerX, -playerY, -playerZ); + int height = 300; + int bottomOffset = 0; + int topOffset = bottomOffset + height; + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + + Minecraft.getMinecraft().getTextureManager().bindTexture(beaconBeam); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, 10497.0F); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, 10497.0F); + GlStateManager.disableLighting(); + GlStateManager.disableDepth(); + GlStateManager.enableTexture2D(); + GlStateManager.tryBlendFuncSeparate(770, 1, 1, 0); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + + double time = Minecraft.getMinecraft().theWorld.getTotalWorldTime() + (double)partialTicks; + double d1 = MathHelper.func_181162_h(-time * 0.2D - (double)MathHelper.floor_double(-time * 0.1D)); + + int c = getColorAt(x,y,z, aColor); + float alpha = ((c >> 24) & 0xFF) / 255.0f; + + float r = ((c >> 16) & 0xFF) / 255f; + float g = ((c >> 8) & 0xFF) / 255f; + float b = (c & 0xFF) / 255f; + double d2 = time * 0.025D * -1.5D; + double d4 = 0.5D + Math.cos(d2 + 2.356194490192345D) * 0.2D; + double d5 = 0.5D + Math.sin(d2 + 2.356194490192345D) * 0.2D; + double d6 = 0.5D + Math.cos(d2 + (Math.PI / 4D)) * 0.2D; + double d7 = 0.5D + Math.sin(d2 + (Math.PI / 4D)) * 0.2D; + double d8 = 0.5D + Math.cos(d2 + 3.9269908169872414D) * 0.2D; + double d9 = 0.5D + Math.sin(d2 + 3.9269908169872414D) * 0.2D; + double d10 = 0.5D + Math.cos(d2 + 5.497787143782138D) * 0.2D; + double d11 = 0.5D + Math.sin(d2 + 5.497787143782138D) * 0.2D; + double d14 = -1.0D + d1; + double d15 = (double)(height) * 2.5D + d14; + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); + worldrenderer.pos(x + d4, y + topOffset, z + d5).tex(1.0D, d15).color(r, g, b, alpha).endVertex(); + worldrenderer.pos(x + d4, y + bottomOffset, z + d5).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d6, y + bottomOffset, z + d7).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d6, y + topOffset, z + d7).tex(0.0D, d15).color(r, g, b, alpha).endVertex(); + worldrenderer.pos(x + d10, y + topOffset, z + d11).tex(1.0D, d15).color(r, g, b, alpha).endVertex(); + worldrenderer.pos(x + d10, y + bottomOffset, z + d11).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d8, y + bottomOffset, z + d9).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d8, y + topOffset, z + d9).tex(0.0D, d15).color(r, g, b, alpha).endVertex(); + worldrenderer.pos(x + d6, y + topOffset, z + d7).tex(1.0D, d15).color(r, g, b, alpha).endVertex(); + worldrenderer.pos(x + d6, y + bottomOffset, z + d7).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d10, y + bottomOffset, z + d11).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d10, y + topOffset, z + d11).tex(0.0D, d15).color(r, g, b, alpha).endVertex(); + worldrenderer.pos(x + d8, y + topOffset, z + d9).tex(1.0D, d15).color(r, g, b, alpha).endVertex(); + worldrenderer.pos(x + d8, y + bottomOffset, z + d9).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d4, y + bottomOffset, z + d5).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex(); + worldrenderer.pos(x + d4, y + topOffset, z + d5).tex(0.0D, d15).color(r, g, b, alpha).endVertex(); + tessellator.draw(); + + double d12 = -1.0D + d1; + double d13 = height + d12; + + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); + worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.2D).tex(1.0D, d13).color(r, g, b, 0.25F*alpha).endVertex(); + worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.2D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.2D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.2D).tex(0.0D, d13).color(r, g, b, 0.25F*alpha).endVertex(); + worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.8D).tex(1.0D, d13).color(r, g, b, 0.25F*alpha).endVertex(); + worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.8D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.8D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.8D).tex(0.0D, d13).color(r, g, b, 0.25F*alpha).endVertex(); + worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.2D).tex(1.0D, d13).color(r, g, b, 0.25F*alpha).endVertex(); + worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.2D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.8D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.8D, y + topOffset, z + 0.8D).tex(0.0D, d13).color(r, g, b, 0.25F*alpha).endVertex(); + worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.8D).tex(1.0D, d13).color(r, g, b, 0.25F*alpha).endVertex(); + worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.8D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.2D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex(); + worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.2D).tex(0.0D, d13).color(r, g, b, 0.25F*alpha).endVertex(); + tessellator.draw(); + + GlStateManager.enableDepth(); + + GlStateManager.popMatrix(); + } + + + public static void drawTexturedRect(float x, float y, float width, float height, int filter) { + drawTexturedRect(x, y, width, height, 0.0F, 1.0F, 0.0F, 1.0F, filter); + } + private static float zLevel = 0; + public static int scrollY = 0; + public static boolean allowScrolling; + public static int scrollX = 0; + + public static void drawGradientRect(int left, int top, int right, int bottom, int startColor, int endColor) + { + float f = (float)(startColor >> 24 & 255) / 255.0F; + float f1 = (float)(startColor >> 16 & 255) / 255.0F; + float f2 = (float)(startColor >> 8 & 255) / 255.0F; + float f3 = (float)(startColor & 255) / 255.0F; + float f4 = (float)(endColor >> 24 & 255) / 255.0F; + float f5 = (float)(endColor >> 16 & 255) / 255.0F; + float f6 = (float)(endColor >> 8 & 255) / 255.0F; + float f7 = (float)(endColor & 255) / 255.0F; + GlStateManager.disableTexture2D(); + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.shadeModel(7425); + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); + worldrenderer.pos((double)right, (double)top, (double)0).color(f1, f2, f3, f).endVertex(); + worldrenderer.pos((double)left, (double)top, (double)0).color(f1, f2, f3, f).endVertex(); + worldrenderer.pos((double)left, (double)bottom, (double)0).color(f5, f6, f7, f4).endVertex(); + worldrenderer.pos((double)right, (double)bottom, (double)0).color(f5, f6, f7, f4).endVertex(); + tessellator.draw(); + GlStateManager.shadeModel(7424); + GlStateManager.enableAlpha(); + GlStateManager.enableTexture2D(); + } + + public static void drawRect(int left, int top, int right, int bottom, AColor color) + { + if (left < right) + { + int i = left; + left = right; + right = i; + } + + if (top < bottom) + { + int j = top; + top = bottom; + bottom = j; + } + + float f3 = (float)(color.getRGB() >> 24 & 255) / 255.0F; + float f = (float)(color.getRGB() >> 16 & 255) / 255.0F; + float f1 = (float)(color.getRGB() >> 8 & 255) / 255.0F; + float f2 = (float)(color.getRGB() & 255) / 255.0F; + if (!color.isChroma() && f3 == 0) return; + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + if (!color.isChroma()) { + GlStateManager.color(f, f1, f2, f3); + worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); + worldrenderer.pos(left, bottom, 0.0D).endVertex(); + worldrenderer.pos(right, bottom, 0.0D).endVertex(); + worldrenderer.pos(right, top, 0.0D).endVertex(); + worldrenderer.pos(left, top, 0.0D).endVertex(); + } else { + worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + color(worldrenderer.pos(left, bottom, 0.0D), getColorAt(left, bottom, color)).endVertex(); + color(worldrenderer.pos(right, bottom, 0.0D), getColorAt(right, bottom, color)).endVertex(); + color(worldrenderer.pos(right, top, 0.0D), getColorAt(right, top, color)).endVertex(); + color(worldrenderer.pos(left, top, 0.0D), getColorAt(left, top, color)).endVertex(); + } + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } + + + public static void drawRoundedRectangle(int x, int y, int width, int height, int radius, double delta, int color) { + GlStateManager.pushMatrix(); + GlStateManager.translate(width/2.0+x, height/2.0+y, 0); + Tessellator t = Tessellator.getInstance(); + GlStateManager.disableTexture2D(); + RenderUtils.GL_SETCOLOR(color); + WorldRenderer wr = t.getWorldRenderer(); + wr.begin(GL11.GL_POLYGON, DefaultVertexFormats.POSITION); + for (double i = 0.1; i < Math.PI*2; i+= delta) { + double cos = MathHelper.cos((float) i); + double sin = MathHelper.sin((float) i); + if (cos * MathHelper.cos((float) (i + delta)) <= 0) { + wr.pos(sin * radius + (sin > 0 ? 1 : -1) * (width/2.0 - radius), + cos * radius + (cos > 0 ? 1 : -1) * (height/2.0 - radius),0).endVertex(); + wr.pos(sin * radius + (sin > 0 ? 1 : -1) * (width/2.0 - radius), + cos * radius + (cos > 0 ? -1 : 1) * (height/2.0 - radius),0).endVertex(); + } else if (sin * MathHelper.sin((float) (i+delta)) <= 0) { + wr.pos(sin * radius + (sin > 0 ? 1 : -1) * (width/2.0 - radius), + cos * radius + (cos > 0 ? 1 : -1) * (height/2.0 - radius), 0).endVertex(); + wr.pos(sin * radius + (sin > 0 ? -1 : 1) * (width/2.0 - radius), + cos * radius + (cos > 0 ? 1 : -1) * (height/2.0 - radius), 0).endVertex(); + } else { + wr.pos(sin * radius + (sin > 0 ? 1 : -1) * (width/2.0 - radius), + cos * radius + (cos > 0 ? 1 : -1) * (height/2.0 - radius), 0).endVertex(); + } + } + t.draw(); + GlStateManager.popMatrix(); + } + + public static void GL_SETCOLOR(int color) { + float f3 = (float)(color >> 24 & 255) / 255.0F; + float f = (float)(color >> 16 & 255) / 255.0F; + float f1 = (float)(color >> 8 & 255) / 255.0F; + float f2 = (float)(color & 255) / 255.0F; + GlStateManager.color(f, f1, f2, f3); + } + + public static int blendTwoColors(int background, int newColor) { + float alpha = ((newColor >> 24) & 0xFF) /255.0f; + int r1 = (background >> 16) & 0xFF, r2 = (newColor >> 16) & 0xFF; + int g1 = (background >> 8) & 0xFF, g2 = (newColor >> 8) & 0xFF; + int b1 = (background) & 0xFF, b2 = (newColor) & 0xFF; + + int rr = (int) (r1 + (r2-r1) * alpha) & 0xFF; + int rg = (int) (g1 + (g2-g1) * alpha) & 0xFF; + int rb = (int) (b1 + (b2-b1) * alpha) & 0xFF; + return 0xFF000000 | ((rr << 16) & 0xFF0000) | ((rg << 8) & 0xFF00) | (rb & 0xFF); + } + + public static int blendAlpha(int origColor, float alphaPerc) { + return blendTwoColors(origColor, (int)(alphaPerc*255) << 24 | 0xFFFFFF); + } + + public static void drawTexturedRect(float x, float y, float width, float height, float uMin, float uMax, float vMin, float vMax, int filter) { + GlStateManager.enableTexture2D(); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 771); + GL11.glTexParameteri(3553, 10241, filter); + GL11.glTexParameteri(3553, 10240, filter); + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer.pos(x, y + height, 0.0D).tex(uMin, vMax).endVertex(); + worldrenderer.pos(x + width, y + height, 0.0D).tex(uMax, vMax).endVertex(); + worldrenderer.pos(x + width, y, 0.0D).tex(uMax, vMin).endVertex(); + worldrenderer.pos(x, y, 0.0D).tex(uMin, vMin).endVertex(); + tessellator.draw(); + GL11.glTexParameteri(3553, 10241, 9728); + GL11.glTexParameteri(3553, 10240, 9728); + GlStateManager.disableBlend(); + } + public static void renderBar(float x, float y, float xSize, float completed) { + Minecraft.getMinecraft().getTextureManager().bindTexture(icons); + completed = (float)Math.round(completed / 0.05F) * 0.05F; + float notcompleted = 1.0F - completed; + int displayNum = 0; + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + float width = 0.0F; + if (completed < 0.5F && (displayNum == 1 || displayNum == 0)) { + width = (0.5F - completed) * xSize; + drawTexturedRect(x + xSize * completed, y, width, 5.0F, xSize * completed / 256.0F, xSize / 2.0F / 256.0F, 0.2890625F, 0.30859375F, 9728); + } + + if (completed < 1.0F && (displayNum == 2 || displayNum == 0)) { + width = Math.min(xSize * notcompleted, xSize / 2.0F); + drawTexturedRect(x + xSize / 2.0F + Math.max(xSize * (completed - 0.5F), 0.0F), y, width, 5.0F, (182.0F - xSize / 2.0F + Math.max(xSize * (completed - 0.5F), 0.0F)) / 256.0F, 0.7109375F, 0.2890625F, 0.30859375F, 9728); + } + + if (completed > 0.0F && (displayNum == 3 || displayNum == 0)) { + width = Math.min(xSize * completed, xSize / 2.0F); + drawTexturedRect(x, y, width, 5.0F, 0.0F, width / 256.0F, 0.30859375F, 0.328125F, 9728); + } + + if (completed > 0.5F && (displayNum == 4 || displayNum == 0)) { + width = Math.min(xSize * (completed - 0.5F), xSize / 2.0F); + drawTexturedRect(x + xSize / 2.0F, y, width, 5.0F, (182.0F - xSize / 2.0F) / 256.0F, (182.0F - xSize / 2.0F + width) / 256.0F, 0.30859375F, 0.328125F, 9728); + } + + } + + public static void drawUnfilledBox(int left, int top, int right, int bottom, int color, boolean chroma) + { + if (left < right) + { + int i = left; + left = right; + right = i; + } + + if (top < bottom) + { + int j = top; + top = bottom; + bottom = j; + } + + float f3 = (float)(color >> 24 & 255) / 255.0F; + float f = (float)(color >> 16 & 255) / 255.0F; + float f1 = (float)(color >> 8 & 255) / 255.0F; + float f2 = (float)(color & 255) / 255.0F; + if (!chroma && f3 == 0) return; + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + if (!chroma) { + GlStateManager.color(f, f1, f2, f3); + worldrenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION); + worldrenderer.pos(left, bottom, 0.0D).endVertex(); + worldrenderer.pos(right, bottom, 0.0D).endVertex(); + worldrenderer.pos(right, top, 0.0D).endVertex(); + worldrenderer.pos(left, top, 0.0D).endVertex(); + } else { + worldrenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION_COLOR); + float blah = (System.currentTimeMillis() / 10) % 360; + GlStateManager.shadeModel(GL11.GL_SMOOTH); + color(worldrenderer.pos(left, bottom, 0.0D), Color.HSBtoRGB((((blah + 20) % 360) / 360.0f), 1, 1)).endVertex(); + color(worldrenderer.pos(right, bottom, 0.0D), Color.HSBtoRGB((((blah + 40) % 360) / 360.0f), 1, 1)).endVertex(); + color(worldrenderer.pos(right, top, 0.0D), Color.HSBtoRGB((((blah + 20) % 360) / 360.0f), 1, 1)).endVertex(); + color(worldrenderer.pos(left, top, 0.0D), Color.HSBtoRGB(blah / 360.0f, 1, 1)).endVertex(); + } + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } + + + public static void drawUnfilledBox(int left, int top, int right, int bottom, AColor color) + { + if (left < right) + { + int i = left; + left = right; + right = i; + } + + if (top < bottom) + { + int j = top; + top = bottom; + bottom = j; + } + + float f3 = (float)(color.getRGB() >> 24 & 255) / 255.0F; + float f = (float)(color.getRGB() >> 16 & 255) / 255.0F; + float f1 = (float)(color.getRGB() >> 8 & 255) / 255.0F; + float f2 = (float)(color.getRGB() & 255) / 255.0F; + if (!color.isChroma() && f3 == 0) return; + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + if (!color.isChroma()) { + GlStateManager.color(f, f1, f2, f3); + worldrenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION); + worldrenderer.pos(left, bottom, 0.0D).endVertex(); + worldrenderer.pos(right, bottom, 0.0D).endVertex(); + worldrenderer.pos(right, top, 0.0D).endVertex(); + worldrenderer.pos(left, top, 0.0D).endVertex(); + } else { + worldrenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION_COLOR); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + color(worldrenderer.pos(left, bottom, 0.0D), getColorAt(left, bottom, color)).endVertex(); + color(worldrenderer.pos(right, bottom, 0.0D), getColorAt(right, bottom, color)).endVertex(); + color(worldrenderer.pos(right, top, 0.0D), getColorAt(right, top, color)).endVertex(); + color(worldrenderer.pos(left, top, 0.0D), getColorAt(left, top, color)).endVertex(); + } + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } + + public static int getChromaColorAt(int x, int y, float speed, float s, float b, float alpha) { + double blah = ((double)(speed) * (System.currentTimeMillis() / 2)) % 360; + return (Color.HSBtoRGB((float) (((blah - (x + y) / 2.0f) % 360) / 360.0f), s,b) & 0xffffff) + | (((int)(alpha * 255)<< 24) & 0xff000000); + } + public static int getColorAt(double x, double y, AColor color) { + if (!color.isChroma()) + return color.getRGB(); + + double blah = ((double)(color.getChromaSpeed()) * (System.currentTimeMillis() / 2)) % 360; + float[] hsv = new float[3]; + Color.RGBtoHSB(color.getRed(), color.getBlue(), color.getGreen(), hsv); + + + return (Color.HSBtoRGB((float) (((blah - (x + y) / 2.0f) % 360) / 360.0f), hsv[1],hsv[2]) & 0xffffff) + | ((color.getAlpha() << 24) & 0xff000000); + } + public static int getColorAt(double x, double y,double z, AColor color) { + if (!color.isChroma()) + return color.getRGB(); + + double blah = ((double)(color.getChromaSpeed()) * (System.currentTimeMillis() / 2)) % 360; + float[] hsv = new float[3]; + Color.RGBtoHSB(color.getRed(), color.getBlue(), color.getGreen(), hsv); + + + return (Color.HSBtoRGB((float) (((blah - ((x + y+z) / 2.0f) % 360)) / 360.0f), hsv[1],hsv[2]) & 0xffffff) + | ((color.getAlpha() << 24) & 0xff000000); + } + + public static WorldRenderer color(WorldRenderer worldRenderer, int color ){ + return worldRenderer.color(((color >> 16) & 0xFF) / 255.0f, ((color >> 8) & 0xFF) / 255.0f, (color &0xFF) / 255.0f, ((color >> 24) & 0xFF) / 255.0f); + } + + public static void renderDoor(DungeonDoor dungeonDoor, float partialTicks) { + Entity player = Minecraft.getMinecraft().thePlayer; + double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks; + double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks; + double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks; + + GlStateManager.pushMatrix(); + GlStateManager.translate(-playerX, -playerY, -playerZ); + GlStateManager.disableTexture2D(); + GlStateManager.enableAlpha(); + + if (dungeonDoor.getType().isExist()) + GlStateManager.color(0,1,0,1); + else + GlStateManager.color(1,0,0,1); + + double x = dungeonDoor.getPosition().getX() + 0.5; + double y = dungeonDoor.getPosition().getY() -0.99; + double z = dungeonDoor.getPosition().getZ() + 0.5; + GL11.glBegin(GL11.GL_QUADS); + + GL11.glVertex3d(x - 2.5, y, z - 2.5); + GL11.glVertex3d(x - 2.5, y, z + 2.5); + GL11.glVertex3d(x + 2.5, y, z + 2.5); + GL11.glVertex3d(x + 2.5, y, z - 2.5); + + GL11.glEnd(); + + if (dungeonDoor.getType().isExist()) { + GL11.glBegin(GL11.GL_QUADS); + + GlStateManager.color(0,0,1,1); + if (dungeonDoor.isZDir()) { + GL11.glVertex3d(x - 0.5, y + 0.1, z - 2.5); + GL11.glVertex3d(x - 0.5, y+ 0.1, z + 2.5); + GL11.glVertex3d(x + 0.5, y+ 0.1, z + 2.5); + GL11.glVertex3d(x + 0.5, y+ 0.1, z - 2.5); + } else { + GL11.glVertex3d(x - 2.5, y+ 0.1, z - 0.5); + GL11.glVertex3d(x - 2.5, y+ 0.1, z + 0.5); + GL11.glVertex3d(x + 2.5, y+ 0.1, z + 0.5); + GL11.glVertex3d(x + 2.5, y+ 0.1, z - 0.5); + } + + GL11.glEnd(); + } else { + GL11.glLineWidth(5); + GL11.glBegin(GL11.GL_LINE_LOOP); + GL11.glVertex3d(x - 2.5, y, z - 2.5); + GL11.glVertex3d(x + 2.5, y + 5, z - 2.5); + GL11.glVertex3d(x + 2.5, y, z + 2.5); + GL11.glVertex3d(x - 2.5, y + 5, z + 2.5); + GL11.glEnd(); + GL11.glBegin(GL11.GL_LINE_LOOP); + GL11.glVertex3d(x - 2.5, y +5, z - 2.5); + GL11.glVertex3d(x + 2.5, y, z - 2.5); + GL11.glVertex3d(x + 2.5, y + 5, z + 2.5); + GL11.glVertex3d(x - 2.5, y, z + 2.5); + GL11.glEnd(); + GL11.glLineWidth(1); + } +// GlStateManager.disableAlpha(); + GlStateManager.disableBlend(); + + GlStateManager.enableTexture2D(); + + + RenderManager renderManager = Minecraft.getMinecraft().getRenderManager(); + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj; + + GlStateManager.translate( dungeonDoor.getPosition().getX(), dungeonDoor.getPosition().getY(), dungeonDoor.getPosition().getZ()); + GlStateManager.rotate(-renderManager.playerViewY, 0.0f, 1.0f, 0.0f); + GlStateManager.rotate(renderManager.playerViewX, 1.0f, 0.0f, 0.0f); + + float lScale = 0.02f; + GlStateManager.scale(-lScale, -lScale, lScale); + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + String text = "Type: "+dungeonDoor.getType(); + int textWidth = fontRenderer.getStringWidth(text); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldRenderer = tessellator.getWorldRenderer(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fontRenderer.drawString(text, -textWidth / 2, 0, 0xFF00FFFF); + + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.popMatrix(); + } + + public static void drawLine(Vec3 pos1, Vec3 pos2, Color colour, float partialTicks , boolean depth) { + Entity render = Minecraft.getMinecraft().getRenderViewEntity(); + WorldRenderer worldRenderer = Tessellator.getInstance().getWorldRenderer(); + + double realX = render.lastTickPosX + (render.posX - render.lastTickPosX) * partialTicks; + double realY = render.lastTickPosY + (render.posY - render.lastTickPosY) * partialTicks; + double realZ = render.lastTickPosZ + (render.posZ - render.lastTickPosZ) * partialTicks; + + GlStateManager.pushMatrix(); + GlStateManager.translate(-realX, -realY, -realZ); + GlStateManager.disableTexture2D(); + if (!depth) { + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + } + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GL11.glLineWidth(2); + GlStateManager.color(colour.getRed() / 255f, colour.getGreen() / 255f, colour.getBlue()/ 255f, colour.getAlpha() / 255f); + worldRenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + + worldRenderer.pos(pos1.xCoord, pos1.yCoord, pos1.zCoord).endVertex(); + worldRenderer.pos(pos2.xCoord, pos2.yCoord, pos2.zCoord).endVertex(); + Tessellator.getInstance().draw(); + + GlStateManager.translate(realX, realY, realZ); + GlStateManager.disableBlend(); + if (!depth) { + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + } + GlStateManager.enableAlpha(); + GlStateManager.enableTexture2D(); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.popMatrix(); + } + + public static void drawLinesVec3(List<Vec3> poses, AColor colour, float thickness, float partialTicks, boolean depth) { + Entity render = Minecraft.getMinecraft().getRenderViewEntity(); + WorldRenderer worldRenderer = Tessellator.getInstance().getWorldRenderer(); + + double realX = render.lastTickPosX + (render.posX - render.lastTickPosX) * partialTicks; + double realY = render.lastTickPosY + (render.posY - render.lastTickPosY) * partialTicks; + double realZ = render.lastTickPosZ + (render.posZ - render.lastTickPosZ) * partialTicks; + + GlStateManager.pushMatrix(); + GlStateManager.translate(-realX, -realY, -realZ); + GlStateManager.disableTexture2D(); + GlStateManager.disableLighting(); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GL11.glLineWidth(thickness); + if (!depth) { + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + } + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + +// GlStateManager.color(colour.getRed() / 255f, colour.getGreen() / 255f, colour.getBlue()/ 255f, colour.getAlpha() / 255f); + GlStateManager.color(1,1,1,1); + worldRenderer.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION_COLOR); + int num = 0; + for (Vec3 pos:poses) { + int i = getColorAt(num++ * 10,0, colour); + worldRenderer.pos(pos.xCoord, pos.yCoord, pos.zCoord).color( + ((i >> 16) &0xFF)/255.0f, + ((i >> 8) &0xFF)/255.0f, + (i &0xFF)/255.0f, + ((i >> 24) &0xFF)/255.0f + ).endVertex(); + } + Tessellator.getInstance().draw(); + + GlStateManager.translate(realX, realY, realZ); + GlStateManager.disableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.enableTexture2D(); + if (!depth) { + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + } + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.popMatrix(); + GL11.glLineWidth(1); + } + public static void drawLines(List<BlockPos> poses, AColor colour, float thickness, float partialTicks, boolean depth) { + Entity render = Minecraft.getMinecraft().getRenderViewEntity(); + WorldRenderer worldRenderer = Tessellator.getInstance().getWorldRenderer(); + + double realX = render.lastTickPosX + (render.posX - render.lastTickPosX) * partialTicks; + double realY = render.lastTickPosY + (render.posY - render.lastTickPosY) * partialTicks; + double realZ = render.lastTickPosZ + (render.posZ - render.lastTickPosZ) * partialTicks; + + GlStateManager.pushMatrix(); + GlStateManager.translate(-realX, -realY, -realZ); + GlStateManager.disableTexture2D(); + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GL11.glLineWidth(thickness); + if (!depth) { + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + } + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + +// GlStateManager.color(colour.getRed() / 255f, colour.getGreen() / 255f, colour.getBlue()/ 255f, colour.getAlpha() / 255f); + GlStateManager.color(1,1,1,1); + worldRenderer.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION_COLOR); + int num = 0; + for (BlockPos pos:poses) { + int i = getColorAt(num++ * 10,0, colour); + worldRenderer.pos(pos.getX() +0.5, pos.getY() +0.5, pos.getZ() +0.5).color( + ((i >> 16) &0xFF)/255.0f, + ((i >> 8) &0xFF)/255.0f, + (i &0xFF)/255.0f, + ((i >> 24) &0xFF)/255.0f + ).endVertex(); + } + Tessellator.getInstance().draw(); + + GlStateManager.translate(realX, realY, realZ); + GlStateManager.disableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.enableTexture2D(); + if (!depth) { + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + } + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.popMatrix(); + GL11.glLineWidth(1); + } + + public static void drawLines(List<BlockPos> poses, Color colour, float thickness, float partialTicks, boolean depth) { + if (colour instanceof AColor) drawLines(poses, (AColor)colour, thickness, partialTicks,depth); + Entity render = Minecraft.getMinecraft().getRenderViewEntity(); + WorldRenderer worldRenderer = Tessellator.getInstance().getWorldRenderer(); + + double realX = render.lastTickPosX + (render.posX - render.lastTickPosX) * partialTicks; + double realY = render.lastTickPosY + (render.posY - render.lastTickPosY) * partialTicks; + double realZ = render.lastTickPosZ + (render.posZ - render.lastTickPosZ) * partialTicks; + + GlStateManager.pushMatrix(); + GlStateManager.translate(-realX, -realY, -realZ); + GlStateManager.disableTexture2D(); + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GL11.glLineWidth(thickness); + if (!depth) { + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + } + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + + GlStateManager.color(colour.getRed() / 255f, colour.getGreen() / 255f, colour.getBlue()/ 255f, colour.getAlpha() / 255f); + worldRenderer.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION); + for (BlockPos pos:poses) { + worldRenderer.pos(pos.getX() +0.5, pos.getY() +0.5, pos.getZ() +0.5).endVertex(); + } + Tessellator.getInstance().draw(); + + GlStateManager.translate(realX, realY, realZ); + GlStateManager.disableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.enableTexture2D(); + if (!depth) { + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + } + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.popMatrix(); + } + + public static void highlightBlock(BlockPos blockpos, Color c, float partialTicks) { + highlightBlock(blockpos,c,partialTicks,false); + } + public static void highlightBlock(BlockPos blockpos, Color c, float partialTicks, boolean depth) { + Entity viewing_from = Minecraft.getMinecraft().getRenderViewEntity(); + + double x_fix = viewing_from.lastTickPosX + ((viewing_from.posX - viewing_from.lastTickPosX) * partialTicks); + double y_fix = viewing_from.lastTickPosY + ((viewing_from.posY - viewing_from.lastTickPosY) * partialTicks); + double z_fix = viewing_from.lastTickPosZ + ((viewing_from.posZ - viewing_from.lastTickPosZ) * partialTicks); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.disableTexture2D(); + + if (!depth) { + GlStateManager.disableDepth(); GL11.glDisable(GL11.GL_DEPTH_TEST); + GlStateManager.depthMask(false); + } + GlStateManager.color(c.getRed() /255.0f, c.getGreen() / 255.0f, c.getBlue()/ 255.0f, c.getAlpha()/ 255.0f); + + GlStateManager.translate(blockpos.getX(), blockpos.getY(), blockpos.getZ()); + + GL11.glBegin(GL11.GL_QUADS); + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, 0, 1); + GL11.glVertex3d(0, 1, 1); + GL11.glVertex3d(0, 1, 0); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(1, 0, 1); + GL11.glVertex3d(1, 0, 0); + GL11.glVertex3d(1, 1, 0); + GL11.glVertex3d(1, 1, 1); + + GL11.glVertex3d(0, 1, 1); + GL11.glVertex3d(0, 0, 1); + GL11.glVertex3d(1, 0, 1); + GL11.glVertex3d(1, 1, 1); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, 1, 0); + GL11.glVertex3d(1, 1, 0); + GL11.glVertex3d(1, 0, 0); + + GL11.glVertex3d(0,1,0); + GL11.glVertex3d(0,1,1); + GL11.glVertex3d(1,1,1); + GL11.glVertex3d(1,1,0); + + GL11.glVertex3d(0,0,1); + GL11.glVertex3d(0,0,0); + GL11.glVertex3d(1,0,0); + GL11.glVertex3d(1,0,1); + + + + GL11.glEnd(); + + + if (!depth) { + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + } + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + + + +//... + + } + + public static void highlightBox(AxisAlignedBB axisAlignedBB, Color c, float partialTicks, boolean depth) { + Entity viewing_from = Minecraft.getMinecraft().getRenderViewEntity(); + + double x_fix = viewing_from.lastTickPosX + ((viewing_from.posX - viewing_from.lastTickPosX) * partialTicks); + double y_fix = viewing_from.lastTickPosY + ((viewing_from.posY - viewing_from.lastTickPosY) * partialTicks); + double z_fix = viewing_from.lastTickPosZ + ((viewing_from.posZ - viewing_from.lastTickPosZ) * partialTicks); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.disableTexture2D(); + + if (!depth) { + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + } + int rgb = c.getRGB(); + GlStateManager.color(((rgb >> 16) &0XFF)/ 255.0f, ((rgb>>8) &0XFF)/ 255.0f, (rgb & 0xff)/ 255.0f, ((rgb >> 24) & 0xFF) / 255.0f); + + GlStateManager.translate(axisAlignedBB.minX, axisAlignedBB.minY, axisAlignedBB.minZ); + + double x = axisAlignedBB.maxX - axisAlignedBB.minX; + double y = axisAlignedBB.maxY - axisAlignedBB.minY; + double z = axisAlignedBB.maxZ - axisAlignedBB.minZ; + GL11.glBegin(GL11.GL_QUADS); + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, y, 0); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, 0, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, y, z); + + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, y, z); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, y, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, 0, 0); + + GL11.glVertex3d(0,y,0); + GL11.glVertex3d(0,y,z); + GL11.glVertex3d(x,y,z); + GL11.glVertex3d(x,y,0); + + GL11.glVertex3d(0,0,z); + GL11.glVertex3d(0,0,0); + GL11.glVertex3d(x,0,0); + GL11.glVertex3d(x,0,z); + + + + GL11.glEnd(); + + + if (!depth) { + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + } + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + + } + public static void highlightBoxAColor(AxisAlignedBB axisAlignedBB, AColor c, float partialTicks, boolean depth) { + Entity viewing_from = Minecraft.getMinecraft().getRenderViewEntity(); + + double x_fix = viewing_from.lastTickPosX + ((viewing_from.posX - viewing_from.lastTickPosX) * partialTicks); + double y_fix = viewing_from.lastTickPosY + ((viewing_from.posY - viewing_from.lastTickPosY) * partialTicks); + double z_fix = viewing_from.lastTickPosZ + ((viewing_from.posZ - viewing_from.lastTickPosZ) * partialTicks); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.disableTexture2D(); + + if (!depth) { + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + } + int rgb = RenderUtils.getColorAt(axisAlignedBB.minX, axisAlignedBB.minY, axisAlignedBB.minZ, c); + GlStateManager.color(((rgb >> 16) &0XFF)/ 255.0f, ((rgb>>8) &0XFF)/ 255.0f, (rgb & 0xff)/ 255.0f, ((rgb >> 24) & 0xFF) / 255.0f); + + GlStateManager.translate(axisAlignedBB.minX, axisAlignedBB.minY, axisAlignedBB.minZ); + + double x = axisAlignedBB.maxX - axisAlignedBB.minX; + double y = axisAlignedBB.maxY - axisAlignedBB.minY; + double z = axisAlignedBB.maxZ - axisAlignedBB.minZ; + GL11.glBegin(GL11.GL_QUADS); + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, y, 0); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, 0, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, y, z); + + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, y, z); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, y, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, 0, 0); + + GL11.glVertex3d(0,y,0); + GL11.glVertex3d(0,y,z); + GL11.glVertex3d(x,y,z); + GL11.glVertex3d(x,y,0); + + GL11.glVertex3d(0,0,z); + GL11.glVertex3d(0,0,0); + GL11.glVertex3d(x,0,0); + GL11.glVertex3d(x,0,z); + + + + GL11.glEnd(); + + + if (!depth) { + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + } + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + + } + public static void highlightBox(Entity entity, AxisAlignedBB axisAlignedBB, AColor c, float partialTicks, boolean depth) { + Entity viewing_from = Minecraft.getMinecraft().getRenderViewEntity(); + + double x_fix = viewing_from.lastTickPosX + ((viewing_from.posX - viewing_from.lastTickPosX) * partialTicks); + double y_fix = viewing_from.lastTickPosY + ((viewing_from.posY - viewing_from.lastTickPosY) * partialTicks); + double z_fix = viewing_from.lastTickPosZ + ((viewing_from.posZ - viewing_from.lastTickPosZ) * partialTicks); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.disableTexture2D(); + + if (!depth) { + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + } + int rgb = RenderUtils.getColorAt(entity.posX * 10,entity.posY * 10,c); + GlStateManager.color(((rgb >> 16) &0XFF)/ 255.0f, ((rgb>>8) &0XFF)/ 255.0f, (rgb & 0xff)/ 255.0f, ((rgb >> 24) & 0xFF) / 255.0f); + if (axisAlignedBB == null) { + if (entity instanceof EntityArmorStand) { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.5, -0.4, 0.4, 0, 0.4); + } else if (entity instanceof EntityBat) { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.4, -0.4, 0.4, 0.4, 0.4); + } else { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.5, -0.4, 0.4, 0, 0.4); + } + } + + Vec3 renderPos = new Vec3( + (float) (entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks), + (float) (entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks), + (float) (entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks) + ); + GlStateManager.translate(axisAlignedBB.minX + renderPos.xCoord, axisAlignedBB.minY + renderPos.yCoord, axisAlignedBB.minZ + renderPos.zCoord); + + double x = axisAlignedBB.maxX - axisAlignedBB.minX; + double y = axisAlignedBB.maxY - axisAlignedBB.minY; + double z = axisAlignedBB.maxZ - axisAlignedBB.minZ; + GL11.glBegin(GL11.GL_QUADS); + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, y, 0); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, 0, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, y, z); + + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, y, z); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, y, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, 0, 0); + + GL11.glVertex3d(0,y,0); + GL11.glVertex3d(0,y,z); + GL11.glVertex3d(x,y,z); + GL11.glVertex3d(x,y,0); + + GL11.glVertex3d(0,0,z); + GL11.glVertex3d(0,0,0); + GL11.glVertex3d(x,0,0); + GL11.glVertex3d(x,0,z); + + + + GL11.glEnd(); + + + if (!depth) { + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + } + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + + } + + public static void highlightBox(Entity entity, AxisAlignedBB axisAlignedBB, Color c, float partialTicks, boolean depth) { + Entity viewing_from = Minecraft.getMinecraft().getRenderViewEntity(); + + double x_fix = viewing_from.lastTickPosX + ((viewing_from.posX - viewing_from.lastTickPosX) * partialTicks); + double y_fix = viewing_from.lastTickPosY + ((viewing_from.posY - viewing_from.lastTickPosY) * partialTicks); + double z_fix = viewing_from.lastTickPosZ + ((viewing_from.posZ - viewing_from.lastTickPosZ) * partialTicks); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.disableTexture2D(); + + if (!depth) { + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + } + GlStateManager.color(c.getRed()/ 255.0f, c.getGreen()/ 255.0f, c.getBlue()/ 255.0f, c.getAlpha()/ 255.0f); + if (axisAlignedBB == null) { + if (entity instanceof EntityArmorStand) { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.5, -0.4, 0.4, 0, 0.4); + } else if (entity instanceof EntityBat) { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.4, -0.4, 0.4, 0.4, 0.4); + } else { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.5, -0.4, 0.4, 0, 0.4); + } + } + + Vec3 renderPos = new Vec3( + (float) (entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks), + (float) (entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks), + (float) (entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks) + ); + GlStateManager.translate(axisAlignedBB.minX + renderPos.xCoord, axisAlignedBB.minY + renderPos.yCoord, axisAlignedBB.minZ + renderPos.zCoord); + + double x = axisAlignedBB.maxX - axisAlignedBB.minX; + double y = axisAlignedBB.maxY - axisAlignedBB.minY; + double z = axisAlignedBB.maxZ - axisAlignedBB.minZ; + GL11.glBegin(GL11.GL_QUADS); + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, y, 0); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, 0, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, y, z); + + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, y, z); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, y, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, 0, 0); + + GL11.glVertex3d(0,y,0); + GL11.glVertex3d(0,y,z); + GL11.glVertex3d(x,y,z); + GL11.glVertex3d(x,y,0); + + GL11.glVertex3d(0,0,z); + GlStateManager.disableDepth(); + GL11.glVertex3d(0,0,0); + GL11.glVertex3d(x,0,0); + GL11.glVertex3d(x,0,z); + + + + GL11.glEnd(); + + + if (!depth) { + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + } + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + + } + public static void highlightBox(Entity entity, Color c, float partialTicks, boolean depth) { + Entity viewing_from = Minecraft.getMinecraft().getRenderViewEntity(); + + double x_fix = viewing_from.lastTickPosX + ((viewing_from.posX - viewing_from.lastTickPosX) * partialTicks); + double y_fix = viewing_from.lastTickPosY + ((viewing_from.posY - viewing_from.lastTickPosY) * partialTicks); + double z_fix = viewing_from.lastTickPosZ + ((viewing_from.posZ - viewing_from.lastTickPosZ) * partialTicks); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.disableTexture2D(); + + if (!depth) { + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + } + GlStateManager.color(c.getRed()/ 255.0f, c.getGreen()/ 255.0f, c.getBlue()/ 255.0f, c.getAlpha()/ 255.0f); + AxisAlignedBB axisAlignedBB; + if (entity instanceof EntityArmorStand) { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.5, -0.4, 0.4, 0, 0.4); + } else if (entity instanceof EntityBat) { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.4, -0.4, 0.4, 0.4, 0.4); + } else { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.5, -0.4, 0.4, 0, 0.4); + } + + Vec3 renderPos = new Vec3( + (float) (entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks), + (float) (entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks), + (float) (entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks) + ); + GlStateManager.translate(axisAlignedBB.minX + renderPos.xCoord, axisAlignedBB.minY + renderPos.yCoord, axisAlignedBB.minZ + renderPos.zCoord); + + double x = axisAlignedBB.maxX - axisAlignedBB.minX; + double y = axisAlignedBB.maxY - axisAlignedBB.minY; + double z = axisAlignedBB.maxZ - axisAlignedBB.minZ; + GL11.glBegin(GL11.GL_QUADS); + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, y, 0); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, 0, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, y, z); + + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, y, z); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, y, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, 0, 0); + + GL11.glVertex3d(0,y,0); + GL11.glVertex3d(0,y,z); + GL11.glVertex3d(x,y,z); + GL11.glVertex3d(x,y,0); + + GL11.glVertex3d(0,0,z); + GL11.glVertex3d(0,0,0); + GL11.glVertex3d(x,0,0); + GL11.glVertex3d(x,0,z); + + + + GL11.glEnd(); + + + if (!depth) { + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + } + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + + + +//... + + } + + public static void highlightBox(Entity entity, AColor c, float partialTicks, boolean depth) { + Entity viewing_from = Minecraft.getMinecraft().getRenderViewEntity(); + + double x_fix = viewing_from.lastTickPosX + ((viewing_from.posX - viewing_from.lastTickPosX) * partialTicks); + double y_fix = viewing_from.lastTickPosY + ((viewing_from.posY - viewing_from.lastTickPosY) * partialTicks); + double z_fix = viewing_from.lastTickPosZ + ((viewing_from.posZ - viewing_from.lastTickPosZ) * partialTicks); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.disableTexture2D(); + + if (!depth) { + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + } + + int rgb = RenderUtils.getColorAt(entity.posX % 20,entity.posY % 20,c); + GlStateManager.color(((rgb >> 16) &0XFF)/ 255.0f, ((rgb>>8) &0XFF)/ 255.0f, (rgb & 0xff)/ 255.0f, ((rgb >> 24) & 0xFF) / 255.0f); + + AxisAlignedBB axisAlignedBB; + if (entity instanceof EntityArmorStand) { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.5, -0.4, 0.4, 0, 0.4); + } else if (entity instanceof EntityBat) { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.4, -0.4, 0.4, 0.4, 0.4); + } else { + axisAlignedBB = AxisAlignedBB.fromBounds(-0.4, -1.5, -0.4, 0.4, 0, 0.4); + } + + Vec3 renderPos = new Vec3( + (float) (entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks), + (float) (entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks), + (float) (entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks) + ); + GlStateManager.translate(axisAlignedBB.minX + renderPos.xCoord, axisAlignedBB.minY + renderPos.yCoord, axisAlignedBB.minZ + renderPos.zCoord); + + double x = axisAlignedBB.maxX - axisAlignedBB.minX; + double y = axisAlignedBB.maxY - axisAlignedBB.minY; + double z = axisAlignedBB.maxZ - axisAlignedBB.minZ; + GL11.glBegin(GL11.GL_QUADS); + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, y, 0); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, 0, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, y, z); + + GL11.glVertex3d(0, y, z); + GL11.glVertex3d(0, 0, z); + GL11.glVertex3d(x, 0, z); + GL11.glVertex3d(x, y, z); // TOP LEFT / BOTTOM LEFT / TOP RIGHT/ BOTTOM RIGHT + + GL11.glVertex3d(0, 0, 0); + GL11.glVertex3d(0, y, 0); + GL11.glVertex3d(x, y, 0); + GL11.glVertex3d(x, 0, 0); + + GL11.glVertex3d(0,y,0); + GL11.glVertex3d(0,y,z); + GL11.glVertex3d(x,y,z); + GL11.glVertex3d(x,y,0); + + GL11.glVertex3d(0,0,z); + GL11.glVertex3d(0,0,0); + GL11.glVertex3d(x,0,0); + GL11.glVertex3d(x,0,z); + + + + GL11.glEnd(); + + + if (!depth) { + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + } + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + + + +//... + + } + public static void drawTextAtWorld(String text, float x, float y, float z, int color, float scale, boolean increase, boolean renderBlackBox, float partialTicks) { + float lScale = scale; + + RenderManager renderManager = Minecraft.getMinecraft().getRenderManager(); + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj; + + Vector3f renderPos = getRenderPos(x, y, z, partialTicks); + + if (increase) { + double distance = Math.sqrt(renderPos.x * renderPos.x + renderPos.y * renderPos.y + renderPos.z * renderPos.z); + double multiplier = distance / 120f; //mobs only render ~120 blocks away + lScale *= 0.45f * multiplier; + } + + GlStateManager.color(1f, 1f, 1f, 0.5f); + GlStateManager.pushMatrix(); + GlStateManager.translate(renderPos.x, renderPos.y, renderPos.z); + GlStateManager.rotate(-renderManager.playerViewY, 0.0f, 1.0f, 0.0f); + GlStateManager.rotate(renderManager.playerViewX, 1.0f, 0.0f, 0.0f); + GlStateManager.scale(-lScale, -lScale, lScale); + GlStateManager.disableLighting(); + GlStateManager.depthMask(false); GL11.glDisable(GL11.GL_DEPTH_TEST); + GlStateManager.disableDepth(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + int textWidth = fontRenderer.getStringWidth(text); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldRenderer = tessellator.getWorldRenderer(); + if (renderBlackBox) { + double j = textWidth / 2; + GlStateManager.disableTexture2D(); + worldRenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); + worldRenderer.pos(-j - 1, -1, 0.0).color(0.0f, 0.0f, 0.0f, 0.25f).endVertex(); + worldRenderer.pos(-j - 1, 8, 0.0).color(0.0f, 0.0f, 0.0f, 0.25f).endVertex(); + worldRenderer.pos(j + 1, 8, 0.0).color(0.0f, 0.0f, 0.0f, 0.25f).endVertex(); + worldRenderer.pos(j + 1, -1, 0.0).color(0.0f, 0.0f, 0.0f, 0.25f).endVertex(); + tessellator.draw(); + GlStateManager.enableTexture2D(); + } + + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fontRenderer.drawString(text, -textWidth / 2, 0, color); + + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.depthMask(true); + GlStateManager.enableDepth(); + GlStateManager.popMatrix(); + } + + public static Vector3f getRenderPos(float x, float y, float z, float partialTicks) { + EntityPlayerSP sp = Minecraft.getMinecraft().thePlayer; + return new Vector3f( + x - (float) (sp.lastTickPosX + (sp.posX - sp.lastTickPosX) * partialTicks), + y - (float) (sp.lastTickPosY + (sp.posY - sp.lastTickPosY) * partialTicks), + z - (float) (sp.lastTickPosZ + (sp.posZ - sp.lastTickPosZ) * partialTicks) + ); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/ShortUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/ShortUtils.java new file mode 100755 index 00000000..134f4089 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/ShortUtils.java @@ -0,0 +1,47 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils; + +public class ShortUtils { + public static short rotateCounterClockwise(short integer) { + int res = 0; + for(int i=0; i<16; i++){ + int x = i % 4; + int y = i / 4; + res |= (integer >> i & 0x1) << ((4-x-1)*4 + y); + } + return (short) (res & 0xFFFF); + } + public static short rotateClockwise(short integer) { + int res = 0; + for(int i=0; i<16; i++){ + int x = i % 4; + int y = i / 4; + res |= (integer >> i & 0x1) << (x *4 +(4 - y - 1)); + } + return (short) (res & 0xFFFF); + } + + public static short topLeftifyInt(short integer) { + int it = integer & 0xFFFF; + while ((it & (0x1111)) == 0) it >>= 1; + while ((it & (0xF)) == 0) it >>= 4; + return (short) (it & 0xFFFF); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/SkyblockUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/SkyblockUtils.java new file mode 100755 index 00000000..6a349f6e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/SkyblockUtils.java @@ -0,0 +1,52 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class SkyblockUtils { + public static long getSkyblockYear() throws IOException { + URL url = new URL("https://hypixel-api.inventivetalent.org/api/skyblock/calendar"); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setRequestProperty("User-Agent", "DungeonsGuide/1.0"); + InputStreamReader inputStreamReader = new InputStreamReader(connection.getInputStream()); + JsonObject object = (JsonObject) new JsonParser().parse(inputStreamReader); + if (!object.get("success").getAsBoolean()) { + return -1; + } + long now = System.currentTimeMillis() / 1000; + + JsonObject real = object.getAsJsonObject("real"); + long secondsPerYear = real.get("SECONDS_PER_MONTH").getAsLong() * 12; + JsonObject lastLog = object.getAsJsonObject("lastLog"); + long lastTime = lastLog.get("time").getAsLong(); + long year = lastLog.get("year").getAsLong(); + + long passedTime = now - lastTime; + year += passedTime / secondsPerYear; + return year; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/TextUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/TextUtils.java new file mode 100755 index 00000000..846a8052 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/TextUtils.java @@ -0,0 +1,121 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.regex.Pattern; + +public class TextUtils { + private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)§[0-9A-FK-OR]"); + + private static final Pattern SCOREBOARD_CHARACTERS = Pattern.compile("[^a-z A-Z:0-9/'.]"); + + private static final Pattern INTEGER_CHARACTERS = Pattern.compile("[^0-9]"); + + public static String stripColor(String input) { + return STRIP_COLOR_PATTERN.matcher(input).replaceAll(""); + } + + public static String keepScoreboardCharacters(String text) { + return SCOREBOARD_CHARACTERS.matcher(text).replaceAll(""); + } + + public static String keepIntegerCharactersOnly(String text) { + return INTEGER_CHARACTERS.matcher(text).replaceAll(""); + } + + public static String join(List list, String delimeter) { + if (list.isEmpty()) return ""; + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < list.size() - 1; i++) { + stringBuilder.append(list.get(i).toString()).append(delimeter); + } + stringBuilder.append(list.get(list.size() - 1).toString()); + return stringBuilder.toString(); + } + + + private static final TreeMap<Long, String> suffixes = new TreeMap<Long, String>(); + + static { + suffixes.put(1000L, "k"); + suffixes.put(1000000L, "m"); + suffixes.put(1000000000L, "b"); + } + + public static String format(long value) { +// return String.valueOf(value); + if (value == Long.MIN_VALUE) + return format(-9223372036854775807L); + if (value < 0L) + return "-" + format(-value); + if (value < 1000L) + return Long.toString(value); + Map.Entry<Long, String> e = suffixes.floorEntry(value); + Long divideBy = e.getKey(); + String suffix = e.getValue(); + long truncated = value * 10 / divideBy ; + boolean hasDecimal = (truncated < 100L && (truncated / 10.0D) != (truncated / 10L)); + return hasDecimal ? ((truncated / 10.0D) + suffix) : ((truncated / 10L) + suffix); + } + public static long reverseFormat(String str2) { + String str = str2.toLowerCase(); + String integerPart = str.substring(0, str.length() - 1); + long multiplier = 1; + if (str.endsWith("k")) multiplier = 1000; + else if (str.endsWith("m")) multiplier = 1000000; + else if (str.endsWith("b")) multiplier = 1000000000; + else integerPart = str; + return (long) (Double.parseDouble(integerPart) * multiplier); + } + + public static String formatTime(long ms) { + long seconds = (long) Math.ceil(ms / 1000.0); + long hr = seconds / (60 * 60); seconds -= hr * 60 * 60; + long min = seconds / 60; seconds -= min * 60; + + StringBuilder stringBuilder = new StringBuilder(); + if (hr > 0) { + stringBuilder.append(hr).append("h "); + } + if (hr > 0 || min > 0) { + stringBuilder.append(min).append("m "); + } + if (hr > 0 || min > 0 || seconds > 0) { + stringBuilder.append(seconds).append("s "); + } + + return stringBuilder.toString(); + } + public static String insertDashUUID(String uuid) { + StringBuilder sb = new StringBuilder(uuid); + sb.insert(8, "-"); + sb = new StringBuilder(sb.toString()); + sb.insert(13, "-"); + sb = new StringBuilder(sb.toString()); + sb.insert(18, "-"); + sb = new StringBuilder(sb.toString()); + sb.insert(23, "-"); + + return sb.toString(); + } + +}
\ No newline at end of file diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/TimeScoreUtil.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/TimeScoreUtil.java new file mode 100644 index 00000000..d874de00 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/TimeScoreUtil.java @@ -0,0 +1,82 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils; + +import kr.syeyoung.dungeonsguide.launcher.Main; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +public class TimeScoreUtil { + private static final TreeMap<Integer, Integer> min8 = new TreeMap<Integer, Integer>(); + private static final TreeMap<Integer, Integer> min10 = new TreeMap<Integer, Integer>(); + private static final TreeMap<Integer, Integer> min12 = new TreeMap<Integer, Integer>(); + public static void init() { + try { + load("8.csv", min8); + } catch (IOException e) { + e.printStackTrace(); + } + try { + load("10.csv", min10); + } catch (IOException e) { + e.printStackTrace(); + } + try { + load("12.csv", min12); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static void load(String name, TreeMap<Integer, Integer> minutes) throws IOException { + minutes.clear(); + List<String> lines = IOUtils.readLines(Main.class.getResourceAsStream("/timescore/"+name)); + for (String line:lines) { + String[] split = line.split(","); + minutes.put(Integer.parseInt(split[0]), Integer.parseInt(split[1])); + } + } + + public static int estimate(int mills, int drop) { + if (drop == 600) return estimate(mills, min10); + if (drop == 480) return estimate(mills, min8); + if (drop == 720) return estimate(mills, min12); + return -1; + } + + private static int estimate(int mills, TreeMap<Integer, Integer> lookup_table){ + Map.Entry<Integer, Integer> high = lookup_table.ceilingEntry(mills); + Map.Entry<Integer, Integer> low = lookup_table.floorEntry(mills); + + + if (low == null && high == null) return 0; + if (low == null) return high.getValue(); + if (high == null) return low.getValue(); + + int distHigh = high.getKey() - mills; + int distLow = mills - low.getKey(); + + if (distHigh > distLow) return high.getValue(); + else return low.getValue(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/VectorUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/VectorUtils.java new file mode 100755 index 00000000..6f667f03 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/VectorUtils.java @@ -0,0 +1,51 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils; + +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.util.Vec3; + +import javax.vecmath.Vector2d; + +public class VectorUtils { + // Ior rooms, different coordinate system is used. Y Increses as marker goes down. X is same. + + + public static Vector2d rotateCounterClockwise(Vector2d vector2d) { + return new Vector2d(vector2d.y, -vector2d.x); + } + public static Vector2d rotateClockwise(Vector2d vector2d) { + return new Vector2d(-vector2d.y, vector2d.x); + } + + @Data @AllArgsConstructor + public static class ProjectionResult { + private float x; + private float y; + private boolean back; + } + + public static double distSquared(Vec3 lookVec, Vec3 posVec, Vec3 objectVec) { + Vec3 v = objectVec.subtract(posVec); + double t = v.dotProduct(lookVec); + Vec3 p = posVec.addVector(lookVec.xCoord * t, lookVec.yCoord * t, lookVec.zCoord * t); + return p.squareDistanceTo(objectVec) / p.squareDistanceTo(posVec); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/XPUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/XPUtils.java new file mode 100644 index 00000000..8e5bb3ad --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/XPUtils.java @@ -0,0 +1,222 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils; + +import kr.syeyoung.dungeonsguide.features.impl.party.api.Skill; +import lombok.Data; + +import java.util.Map; +import java.util.TreeMap; + +public class XPUtils { + @Data + public static class XPCalcResult { + private int level; + private double remainingXp; + private double nextLvXp; + } + + private static final TreeMap<Double, Integer> catacombXp = new TreeMap<>(); + private static final TreeMap<Double, Integer> skillXp = new TreeMap<>(); + private static final TreeMap<Double, Integer> skillXp2 = new TreeMap<>(); + static { + catacombXp.put(50.0, 1); + catacombXp.put(125.0, 2); + catacombXp.put(235.0, 3); + catacombXp.put(395.0, 4); + catacombXp.put(625.0, 5); + catacombXp.put(955.0, 6); + catacombXp.put(1425.0, 7); + catacombXp.put(2095.0, 8); + catacombXp.put(3045.0, 9); + catacombXp.put(4385.0, 10); + catacombXp.put(6275.0, 11); + catacombXp.put(8940.0, 12); + catacombXp.put(12700.0, 13); + catacombXp.put(17960.0, 14); + catacombXp.put(25340.0, 15); + catacombXp.put(35640.0, 16); + catacombXp.put(50040.0, 17); + catacombXp.put(70040.0, 18); + catacombXp.put(97640.0, 19); + catacombXp.put(135640.0, 20); + catacombXp.put(188140.0, 21); + catacombXp.put(259640.0, 22); + catacombXp.put(356640.0, 23); + catacombXp.put(488640.0, 24); + catacombXp.put(668640.0, 25); + catacombXp.put(911640.0, 26); + catacombXp.put(1239640.0, 27); + catacombXp.put(1684640.0, 28); + catacombXp.put(2284640.0, 29); + catacombXp.put(3084640.0, 30); + catacombXp.put(4149640.0, 31); + catacombXp.put(5559640.0, 32); + catacombXp.put(7459640.0, 33); + catacombXp.put(9959640.0, 34); + catacombXp.put(13259640.0, 35); + catacombXp.put(17559640.0, 36); + catacombXp.put(23159640.0, 37); + catacombXp.put(30359640.0, 38); + catacombXp.put(39559640.0, 39); + catacombXp.put(51559640.0, 40); + catacombXp.put(66559640.0, 41); + catacombXp.put(85559640.0, 42); + catacombXp.put(109559640.0, 43); + catacombXp.put(139559640.0, 44); + catacombXp.put(177559640.0, 45); + catacombXp.put(225559640.0, 46); + catacombXp.put(285559640.0, 47); + catacombXp.put(360559640.0, 48); + catacombXp.put(453559640.0, 49); + catacombXp.put(569809640.0, 50); + skillXp.put(0.0, 0); + skillXp.put(50.0, 1); + skillXp.put(175.0, 2); + skillXp.put(375.0, 3); + skillXp.put(675.0, 4); + skillXp.put(1175.0, 5); + skillXp.put(1925.0, 6); + skillXp.put(2925.0, 7); + skillXp.put(4425.0, 8); + skillXp.put(6425.0, 9); + skillXp.put(9925.0, 10); + skillXp.put(14925.0, 11); + skillXp.put(22425.0, 12); + skillXp.put(32425.0, 13); + skillXp.put(47425.0, 14); + skillXp.put(67425.0, 15); + skillXp.put(97425.0, 16); + skillXp.put(147425.0, 17); + skillXp.put(222425.0, 18); + skillXp.put(322425.0, 19); + skillXp.put(522425.0, 20); + skillXp.put(822425.0, 21); + skillXp.put(1222425.0, 22); + skillXp.put(1722425.0, 23); + skillXp.put(2322425.0, 24); + skillXp.put(3022425.0, 25); + skillXp.put(3822425.0, 26); + skillXp.put(4722425.0, 27); + skillXp.put(5722425.0, 28); + skillXp.put(6822425.0, 29); + skillXp.put(8022425.0, 30); + skillXp.put(9322425.0, 31); + skillXp.put(10722425.0, 32); + skillXp.put(12222425.0, 33); + skillXp.put(13722425.0, 34); + skillXp.put(15522425.0, 35); + skillXp.put(17322425.0, 36); + skillXp.put(19222425.0, 37); + skillXp.put(21222425.0, 38); + skillXp.put(23322425.0, 39); + skillXp.put(25522425.0, 40); + skillXp.put(27822425.0, 41); + skillXp.put(30222425.0, 42); + skillXp.put(32722425.0, 43); + skillXp.put(35322425.0, 44); + skillXp.put(38072425.0, 45); + skillXp.put(40972425.0, 46); + skillXp.put(44072425.0, 47); + skillXp.put(47472425.0, 48); + skillXp.put(51172425.0, 49); + skillXp.put(55172425.0, 50); + skillXp.put(59472425.0, 51); + skillXp.put(64072425.0, 52); + skillXp.put(68972425.0, 53); + skillXp.put(74172425.0, 54); + skillXp.put(79672425.0, 55); + skillXp.put(85472425.0, 56); + skillXp.put(91572425.0, 57); + skillXp.put(97972425.0, 58); + skillXp.put(104672425.0, 59); + skillXp.put(111672425.0, 60); + skillXp2.put(0.0, 0); + skillXp2.put(50.0, 1); + skillXp2.put(150.0, 2); + skillXp2.put(275.0, 3); + skillXp2.put(435.0, 4); + skillXp2.put(635.0, 5); + skillXp2.put(885.0, 6); + skillXp2.put(1200.0, 7); + skillXp2.put(1600.0, 8); + skillXp2.put(2100.0, 9); + skillXp2.put(2725.0, 10); + skillXp2.put(3510.0, 11); + skillXp2.put(4510.0, 12); + skillXp2.put(5760.0, 13); + skillXp2.put(7324.0, 14); + skillXp2.put(9325.0, 15); + skillXp2.put(11825.0, 16); + skillXp2.put(14950.0, 17); + skillXp2.put(18950.0, 18); + skillXp2.put(23950.0, 19); + skillXp2.put(30200.0, 20); + skillXp2.put(38050.0, 21); + skillXp2.put(47850.0, 22); + skillXp2.put(60100.0, 23); + skillXp2.put(75400.0, 24); + skillXp2.put(94450.0, 25); + } + + public static XPCalcResult getCataXp(double totalXp) { + Map.Entry<Double, Integer> totalXpEn = catacombXp.floorEntry(totalXp); + XPCalcResult xpCalcResult = new XPCalcResult(); + if (totalXpEn == null) { + xpCalcResult.setLevel(0); + xpCalcResult.remainingXp = totalXp; + } else { + xpCalcResult.level = totalXpEn.getValue(); + xpCalcResult.remainingXp = totalXp - totalXpEn.getKey(); + } + Map.Entry<Double, Integer> asdasd = catacombXp.ceilingEntry(totalXp); + xpCalcResult.nextLvXp = asdasd == null ? 0 : (asdasd.getKey() - (totalXpEn != null ? totalXpEn.getKey() : 0)); + return xpCalcResult; + } + public static XPCalcResult getSkillXp(Skill skill, double totalXp) { + switch(skill) { + case RUNECRAFTING: + Map.Entry<Double, Integer> totalXpEn = skillXp2.floorEntry(totalXp); + XPCalcResult xpCalcResult = new XPCalcResult(); + if (totalXpEn == null) { + xpCalcResult.setLevel(0); + xpCalcResult.remainingXp = totalXp; + } else { + xpCalcResult.level = totalXpEn.getValue(); + xpCalcResult.remainingXp = totalXp - totalXpEn.getKey(); + } + Map.Entry<Double, Integer> asdasd = catacombXp.ceilingEntry(totalXp); + xpCalcResult.nextLvXp = asdasd == null ? 0 : (asdasd.getKey() - (totalXpEn != null ? totalXpEn.getKey() : 0)); + return xpCalcResult; + default: + totalXpEn = skillXp.floorEntry(totalXp); + xpCalcResult = new XPCalcResult(); + if (totalXpEn == null) { + xpCalcResult.setLevel(0); + xpCalcResult.remainingXp = totalXp; + } else { + xpCalcResult.level = totalXpEn.getValue(); + xpCalcResult.remainingXp = totalXp - totalXpEn.getKey(); + } + asdasd = catacombXp.ceilingEntry(totalXp); + xpCalcResult.nextLvXp = asdasd == null ? 0 : (asdasd.getKey() - (totalXpEn != null ? totalXpEn.getKey() : 0)); + return xpCalcResult; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/CursorReader.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/CursorReader.java new file mode 100644 index 00000000..eec09a6a --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/CursorReader.java @@ -0,0 +1,94 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils.cursor; + +import com.google.common.io.LittleEndianDataInputStream; +import com.twelvemonkeys.imageio.plugins.bmp.CURImageReader; +import lombok.Data; + +import javax.imageio.ImageIO; +import javax.imageio.stream.ImageInputStream; +import java.awt.image.BufferedImage; +import java.io.*; +import java.util.ArrayList; +import java.util.List; + +public class CursorReader { + public static List<CursorData> readFromInputStream(InputStream inputStream) throws IOException { + System.out.println(inputStream); + LittleEndianDataInputStream dataInputStream = new LittleEndianDataInputStream(new BufferedInputStream(inputStream)); + dataInputStream.mark(Integer.MAX_VALUE); + + + int magicValue = dataInputStream.readUnsignedShort(); + if (magicValue != 0) throw new RuntimeException("Invalid Cursor file"); + int type = dataInputStream.readUnsignedShort(); + if (type != 2) throw new RuntimeException("not cursor"); + int size = dataInputStream.readShort(); + + List<CursorData> directoryList = new ArrayList<>(); + for (int i = 0; i < size; i++) { + + CursorData directory = new CursorData(); + directory.setWidth((short) dataInputStream.readUnsignedByte()); + directory.setHeight((short) dataInputStream.readUnsignedByte()); + directory.setColorCnt((short) dataInputStream.readUnsignedByte()); + directory.setMagicValue(dataInputStream.readByte()); + directory.setXHotSpot(dataInputStream.readShort()); + directory.setYHotSpot(dataInputStream.readShort()); + directory.setSizeBitmap(dataInputStream.readInt() & 0x00000000ffffffffL); + directory.setOffset(dataInputStream.readInt() & 0x00000000ffffffffL); + + directoryList.add(directory); + } + dataInputStream.reset(); + + try (ImageInputStream imageInputStream = ImageIO.createImageInputStream(dataInputStream)) { + CURImageReader imageReader = new CURImageReader(); + imageReader.setInput(imageInputStream); + + for (int i = 0; i < directoryList.size(); i++) { + directoryList.get(i).setBufferedImage(imageReader.read(i)); + } + } + inputStream.close(); + + return directoryList; + } + + private static void setIntLittleEndian(byte[] bytes, int index, int value) { + byte[] ins = new byte[] { + (byte) ((value >> 24)& 0xFF), (byte) ((value >> 16)& 0xFF), (byte) ((value >> 8)& 0xFF), (byte) (value & 0xFF) + }; + bytes[index+3] = ins[0]; + bytes[index+2] = ins[1]; + bytes[index+1] = ins[2]; + bytes[index] = ins[3]; + } + + + @Data + public static class CursorData { + private short width, height, colorCnt, magicValue; + private int xHotSpot, yHotSpot; + private long sizeBitmap; + private long offset; + private BufferedImage bufferedImage; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/EnumCursor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/EnumCursor.java new file mode 100644 index 00000000..20cccef7 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/EnumCursor.java @@ -0,0 +1,54 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils.cursor; + +import lombok.AllArgsConstructor; +import lombok.Getter; + + +@AllArgsConstructor +@Getter +public enum EnumCursor { + DEFAULT(32512,68,"arrowCursor","arrowCursor.cur"), + POINTING_HAND(32649,60,"pointingHandCursor", "pointingHandCursor.cur"), + OPEN_HAND(32646,58,"openHandCursor","openHandCursor.cur"), + CLOSED_HAND(32646,52,"closedHandCursor","closedHandCursor.cur"), + BEAM_CURSOR(32513, 152, "IBeamCursor", "IBeamCursor.cur"), + RESIZE_LEFT(32644, 70,"resizeLeftCursor", "resizeLeftCursor.cur"), + RESIZE_RIGHT(32644, 96,"resizeRightCursor", "resizeRightCursor.cur"), + RESIZE_LEFT_RIGHT(32644, 108, "resizeLeftRightCursor", "resizeLeftRightCursor.cur"), + RESIZE_UP(32645,138,"resizeUpCursor", "resizeUpCursor.cur"), + RESIZE_DOWN(32645,16,"resizeDownCursor", "resizeDownCursor.cur"), + RESIZE_UP_DOWN(32645,116,"resizeUpDownCursor", "resizeUpDownCursor.cur"), + RESIZE_TL(32642, 134, null, "resizeNW.cur"), + RESIZE_DR(32642, 14, null, "resizeSE.cur"), + RESIZE_TLDR(32642, 14, null, "resizeNWSE.cur"), + RESIZE_TR(32643, 136, null, "resizeNE.cur"), + RESIZE_DL(32643, 12, null, "resizeSW.cur"), + RESIZE_TRDL(32643, 12, null, "resizeNESW.cur"), + CROSS(32515, 34,"crosshairCursor", "crosshairCursor.cur"), + NOT_ALLOWED(32648, -1,"operationNotAllowedCursor", "operationNotAllowedCursor.cur"), + TEST(-1, -1, null, "testnonexistant.cur"); + + + private int windows; + private int linux; + private String macos; + private String altFileName; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/Foundation.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/Foundation.java new file mode 100644 index 00000000..9eab9b84 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/Foundation.java @@ -0,0 +1,33 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils.cursor; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Pointer; + + +public interface Foundation extends Library { + Foundation INSTANCE = (Foundation) Native.loadLibrary("Foundation", + Foundation.class); + + Pointer objc_getClass(String className); + Pointer sel_registerName(String selectorName); + Pointer objc_msgSend(Pointer receiver, Pointer selector, Object... args); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/GLCursors.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/GLCursors.java new file mode 100644 index 00000000..9cffc8b4 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/GLCursors.java @@ -0,0 +1,219 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils.cursor; + +import com.sun.jna.Pointer; +import kr.syeyoung.dungeonsguide.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.BufferUtils; +import org.lwjgl.LWJGLException; +import org.lwjgl.LWJGLUtil; +import org.lwjgl.input.Cursor; +import sun.misc.Unsafe; + +import java.awt.image.BufferedImage; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +public class GLCursors { + private static Unsafe unsafe; + private static Class cursorElement; + private static Constructor constructor; + private static Field cursorField; + + private static Map<EnumCursor, Cursor> enumCursorCursorMap = new HashMap<>(); + + + static { + try { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe) f.get(null); + cursorElement = Class.forName("org.lwjgl.input.Cursor$CursorElement"); + constructor = cursorElement.getDeclaredConstructor(Object.class, long.class, long.class); + constructor.setAccessible(true); + cursorField = Cursor.class.getDeclaredField("cursors"); + cursorField.setAccessible(true); + } catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException e) { + e.printStackTrace(); + } + } + + public static void setupCursors() { + if (enumCursorCursorMap.size() != 0) return; + int platform = LWJGLUtil.getPlatform(); + for (EnumCursor value : EnumCursor.values()) { + Cursor c = null; + try { + switch(platform) { + case LWJGLUtil.PLATFORM_WINDOWS: + if (value.getWindows() != -1) + c = createCursorWindows(value.getWindows()); + break; + case LWJGLUtil.PLATFORM_LINUX: + if (value.getLinux() != -1) + c = createCursorLinux(value.getLinux()); + break; + case LWJGLUtil.PLATFORM_MACOSX: + if (value.getMacos() != null) + c = createCursorMac(value.getMacos()); + break; + } + } catch (Throwable e) { + System.out.println("Error occured while loading cursor: "+value); + e.printStackTrace(); + } + try { + if (c == null) { + int hotspotX = 0, hotspotY = 0; + BufferedImage bufferedImage = null; + int minC = Cursor.getMinCursorSize(), maxC = Cursor.getMaxCursorSize(); + try { + ResourceLocation cursorinfo = new ResourceLocation("dungeonsguide:cursors/"+value.getAltFileName()); + List<CursorReader.CursorData> cursorDataList = CursorReader.readFromInputStream(Minecraft.getMinecraft().getResourceManager().getResource(cursorinfo).getInputStream()); + List<CursorReader.CursorData> cursorDataList2 = cursorDataList.stream() + .filter(cdata -> cdata.getBufferedImage() != null) + .filter(cdata -> minC <= cdata.getHeight() && cdata.getHeight() <= maxC && minC <= cdata.getWidth() && cdata.getWidth() <= maxC) + .sorted(Comparator.comparingInt(CursorReader.CursorData::getWidth)).collect(Collectors.toList()); + + CursorReader.CursorData cursorData = + cursorDataList2.size() == 0 ? cursorDataList.get(0) : cursorDataList2.get(0); + System.out.println(cursorData); + bufferedImage = cursorData.getBufferedImage(); + hotspotX = cursorData.getXHotSpot(); + hotspotY = cursorData.getYHotSpot(); + } catch (Throwable t) {t.printStackTrace();} + + + int width = bufferedImage == null ? 16 : bufferedImage.getWidth(); + int height = bufferedImage == null ? 16 : bufferedImage.getHeight(); + int effWidth = MathHelper.clamp_int(width, Cursor.getMinCursorSize(), Cursor.getMaxCursorSize()); + int effHeight = MathHelper.clamp_int(height, Cursor.getMinCursorSize(), Cursor.getMaxCursorSize()); + int length = effHeight * effWidth; + IntBuffer intBuffer = BufferUtils.createIntBuffer(length); + for (int i = 0; i < length; i++) { + int x = i % effWidth; + int y = i / effWidth; + if (bufferedImage == null) { + intBuffer.put(RenderUtils.getChromaColorAt(x,y,1.0f, 1.0f, 1.0f, 1.0f)); + } else if (x >= width || y >= height) { + intBuffer.put(0); + } else { + intBuffer.put(bufferedImage.getRGB(x, height - y - 1)); + } + } + intBuffer.flip(); + c = new Cursor(effWidth, effHeight, hotspotX, height - hotspotY - 1,1,intBuffer, null); + } + } catch (Throwable e) { + System.out.println("Error occured while loading cursor from resource: "+value); + e.printStackTrace(); + } + if (c != null) { + try { + Object arr = cursorField.get(c); + Object cursor = Array.get(arr, 0); + for (Field declaredField : cursor.getClass().getDeclaredFields()) { + declaredField.setAccessible(true); + Object obj = declaredField.get(cursor); + System.out.println(declaredField.getName()+": "+obj+" - "+(obj instanceof ByteBuffer)); + if (obj instanceof ByteBuffer) { + ByteBuffer b = (ByteBuffer) declaredField.get(cursor); + StringBuilder sb = new StringBuilder("Contents: "); + for (int i = 0; i < b.limit(); i++) { + sb.append(Integer.toHexString(b.get(i) & 0xFF)).append(" "); + } + System.out.println(sb.toString()); + } + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + + enumCursorCursorMap.put(value, c); + } + } + } + + public static Cursor getCursor(EnumCursor enumCursor) { + return enumCursorCursorMap.get(enumCursor); + } + + private static Cursor createCursorWindows(int cursor) throws LWJGLException, InstantiationException, InvocationTargetException, IllegalAccessException { + User32 user32 = User32.INSTANCE; + Pointer hIcon = user32 + .LoadCursorW(Pointer.NULL, cursor); + long ptrVal = Pointer.nativeValue(hIcon); + ByteBuffer handle = BufferUtils.createByteBuffer(Pointer.SIZE); // Why does it have to be direct? well it crashes without it. + if (handle.order() == ByteOrder.LITTLE_ENDIAN) { + for (int i = 0; i < Pointer.SIZE; i++) { + byte value = (byte) ((ptrVal >> i * 8) & 0xFF); + handle.put(value); + } + } else { + for (int i = Pointer.SIZE; i >= 0; i++) { + byte value = (byte) ((ptrVal >> i * 8) & 0xFF); + handle.put(value); + } + } + handle.position(0); + return createCursor(handle); + } + private static Cursor createCursorLinux(int cursor) throws LWJGLException, InstantiationException, InvocationTargetException, IllegalAccessException { + X11.Display display = X11.INSTANCE.XOpenDisplay(null); + Pointer fontCursor = X11.INSTANCE.XCreateFontCursor(display, cursor); + long iconPtr = Pointer.nativeValue(fontCursor); + + return createCursor(iconPtr); + } + private static Cursor createCursorMac(String cursor) throws LWJGLException, InstantiationException, InvocationTargetException, IllegalAccessException { + // trust me, it's horrible. + Foundation foundation = Foundation.INSTANCE; + Pointer nsCursor = foundation.objc_getClass("NSCursor"); + Pointer selector = foundation.sel_registerName(cursor); + Pointer thePointer = foundation.objc_msgSend(nsCursor, selector); + long iconPtr = Pointer.nativeValue(thePointer); + + return createCursor(iconPtr); + } + + + private static Cursor createCursor(Object handle) throws IllegalAccessException, InvocationTargetException, InstantiationException { + // Yes. I had no way. + Cursor ADANGEROUSOBJECT = (Cursor) unsafe.allocateInstance(Cursor.class); + Object cursorElement = constructor.newInstance(handle, 0, LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_LINUX ? -1 : System.currentTimeMillis()); + Object array = Array.newInstance(GLCursors.cursorElement, 1); + Array.set(array, 0, cursorElement); + cursorField.set(ADANGEROUSOBJECT, array); + return ADANGEROUSOBJECT; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/User32.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/User32.java new file mode 100644 index 00000000..0577ebab --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/User32.java @@ -0,0 +1,67 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils.cursor; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Pointer; + +public interface User32 extends Library { + + public static User32 INSTANCE = (User32) Native + .loadLibrary("User32", User32.class); + + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_ARROW = 32512; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_IBEAM = 32513; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_WAIT = 32514; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_CROSS = 32515; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_UPARROW = 32516; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_SIZENWSE = 32642; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_SIZENESW = 32643; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_SIZEWE = 32644; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_SIZENS = 32645; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_SIZEALL = 32646; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_NO = 32648; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_HAND = 32649; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_APPSTARTING = 32650; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_HELP = 32651; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_ICON = 32641; + /** @see #LoadCursorW(Pointer, int) */ + public static final int IDC_SIZE = 32640; + + /** http://msdn.microsoft.com/en-us/library/ms648391(VS.85).aspx */ + public Pointer LoadCursorW(Pointer hInstance, + int lpCursorName); + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/X11.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/X11.java new file mode 100644 index 00000000..caf8ae10 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/utils/cursor/X11.java @@ -0,0 +1,37 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.utils.cursor; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.PointerType; + +public interface X11 extends Library { + X11 INSTANCE = (X11) Native.loadLibrary("X11", X11.class); + public Pointer XCreateFontCursor(Display display, + int shape); + public Display XOpenDisplay(String var1); + + public static class Display extends PointerType { + public Display() { + } + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/wsresource/StaticResource.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/wsresource/StaticResource.java new file mode 100644 index 00000000..814fb8c8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/wsresource/StaticResource.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.wsresource; + +import lombok.Data; + +import java.util.UUID; + +@Data +public class StaticResource { + private UUID resourceID; + private String value; + private boolean exists; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/wsresource/StaticResourceCache.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/wsresource/StaticResourceCache.java new file mode 100644 index 00000000..db781844 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/wsresource/StaticResourceCache.java @@ -0,0 +1,83 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.wsresource; + +import kr.syeyoung.dungeonsguide.DungeonsGuide; +import kr.syeyoung.dungeonsguide.events.StompConnectedEvent; +import kr.syeyoung.dungeonsguide.stomp.StompInterface; +import kr.syeyoung.dungeonsguide.stomp.StompMessageHandler; +import kr.syeyoung.dungeonsguide.stomp.StompPayload; +import kr.syeyoung.dungeonsguide.stomp.StompSubscription; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class StaticResourceCache implements StompMessageHandler { + public static final StaticResourceCache INSTANCE = new StaticResourceCache(); + + private Map<UUID, StaticResource> staticResourceMap = new HashMap<>(); + + private Map<UUID, CompletableFuture<StaticResource>> staticResourceRequest = new HashMap<>(); + + public void purgeCache() { + staticResourceRequest.clear(); + staticResourceMap.clear(); + } + + public CompletableFuture<StaticResource> getResource(UUID resourceID) { + if (staticResourceMap.containsKey(resourceID)) return CompletableFuture.completedFuture(staticResourceMap.get(resourceID)); + if (staticResourceRequest.containsKey(resourceID)) return staticResourceRequest.get(resourceID); + + DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().header("destination", "/app/staticresource.get").payload(resourceID.toString())); + CompletableFuture<StaticResource> comp = new CompletableFuture<>(); + staticResourceRequest.put(resourceID, comp); + return comp; + } + + @Override + public void handle(StompInterface stompInterface, StompPayload stompPayload) { + JSONObject object = new JSONObject(stompPayload.payload()); + StaticResource staticResource = new StaticResource(); + staticResource.setResourceID(UUID.fromString(object.getString("resourceID"))); + staticResource.setExists(object.getBoolean("exists")); + staticResource.setValue((!object.has("value") || object.isNull("value")) ? null : object.getString("value")); + + staticResourceMap.put(staticResource.getResourceID(), staticResource); + CompletableFuture<StaticResource> completed = staticResourceRequest.remove(staticResource.getResourceID()); + if (completed != null) completed.complete(staticResource); + } + + @SubscribeEvent + public void stompConnect(StompConnectedEvent stompConnectedEvent) { + stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder() + .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/staticresource.get").build()); + + getResource(BONUS_SCORE); + getResource(TRIVIA_ANSWERS); + getResource(DATA_COLLECTION); + } + + public static final UUID BONUS_SCORE = UUID.fromString("13f10001-66b5-46e5-94f9-1a5161a23429"); + public static final UUID TRIVIA_ANSWERS = UUID.fromString("5657f2cc-2bb8-4fcd-b55c-ffc0a35b9349"); + public static final UUID DATA_COLLECTION = UUID.fromString("c11f026f-9f26-4d14-8d52-88325dd6397a"); +} diff --git a/mod/src/main/resources/assets/dg/cursors/IBeamCursor.cur b/mod/src/main/resources/assets/dg/cursors/IBeamCursor.cur Binary files differnew file mode 100755 index 00000000..19f162df --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/IBeamCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/arrowCursor.cur b/mod/src/main/resources/assets/dg/cursors/arrowCursor.cur Binary files differnew file mode 100755 index 00000000..7d58eec1 --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/arrowCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/closedHandCursor.cur b/mod/src/main/resources/assets/dg/cursors/closedHandCursor.cur Binary files differnew file mode 100644 index 00000000..26d6ba9f --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/closedHandCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/crosshairCursor.cur b/mod/src/main/resources/assets/dg/cursors/crosshairCursor.cur Binary files differnew file mode 100755 index 00000000..7d4589af --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/crosshairCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/openHandCursor.cur b/mod/src/main/resources/assets/dg/cursors/openHandCursor.cur Binary files differnew file mode 100644 index 00000000..26d6ba9f --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/openHandCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/operationNotAllowedCursor.cur b/mod/src/main/resources/assets/dg/cursors/operationNotAllowedCursor.cur Binary files differnew file mode 100755 index 00000000..1bb62ed5 --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/operationNotAllowedCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/pointingHandCursor.cur b/mod/src/main/resources/assets/dg/cursors/pointingHandCursor.cur Binary files differnew file mode 100755 index 00000000..77313176 --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/pointingHandCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeDownCursor.cur b/mod/src/main/resources/assets/dg/cursors/resizeDownCursor.cur Binary files differnew file mode 100755 index 00000000..bae2c237 --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeDownCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeLeftCursor.cur b/mod/src/main/resources/assets/dg/cursors/resizeLeftCursor.cur Binary files differnew file mode 100755 index 00000000..b904bc5c --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeLeftCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeLeftRightCursor.cur b/mod/src/main/resources/assets/dg/cursors/resizeLeftRightCursor.cur Binary files differnew file mode 100755 index 00000000..b904bc5c --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeLeftRightCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeNE.cur b/mod/src/main/resources/assets/dg/cursors/resizeNE.cur Binary files differnew file mode 100755 index 00000000..ccaac220 --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeNE.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeNESW.cur b/mod/src/main/resources/assets/dg/cursors/resizeNESW.cur Binary files differnew file mode 100755 index 00000000..ccaac220 --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeNESW.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeNW.cur b/mod/src/main/resources/assets/dg/cursors/resizeNW.cur Binary files differnew file mode 100755 index 00000000..f67aa78d --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeNW.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeNWSE.cur b/mod/src/main/resources/assets/dg/cursors/resizeNWSE.cur Binary files differnew file mode 100755 index 00000000..f67aa78d --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeNWSE.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeRightCursor.cur b/mod/src/main/resources/assets/dg/cursors/resizeRightCursor.cur Binary files differnew file mode 100755 index 00000000..b904bc5c --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeRightCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeSE.cur b/mod/src/main/resources/assets/dg/cursors/resizeSE.cur Binary files differnew file mode 100755 index 00000000..f67aa78d --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeSE.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeSW.cur b/mod/src/main/resources/assets/dg/cursors/resizeSW.cur Binary files differnew file mode 100755 index 00000000..ccaac220 --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeSW.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeUpCursor.cur b/mod/src/main/resources/assets/dg/cursors/resizeUpCursor.cur Binary files differnew file mode 100755 index 00000000..bae2c237 --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeUpCursor.cur diff --git a/mod/src/main/resources/assets/dg/cursors/resizeUpDownCursor.cur b/mod/src/main/resources/assets/dg/cursors/resizeUpDownCursor.cur Binary files differnew file mode 100755 index 00000000..bae2c237 --- /dev/null +++ b/mod/src/main/resources/assets/dg/cursors/resizeUpDownCursor.cur diff --git a/mod/src/main/resources/assets/dg/models/penguin.mtl b/mod/src/main/resources/assets/dg/models/penguin.mtl new file mode 100644 index 00000000..1fc14a2f --- /dev/null +++ b/mod/src/main/resources/assets/dg/models/penguin.mtl @@ -0,0 +1,4 @@ +# Made in Blockbench 3.8.4 +newmtl m_2 +map_Kd dungeonsguide:penguin +newmtl none
\ No newline at end of file diff --git a/mod/src/main/resources/assets/dg/models/penguin.obj b/mod/src/main/resources/assets/dg/models/penguin.obj new file mode 100644 index 00000000..29fe4680 --- /dev/null +++ b/mod/src/main/resources/assets/dg/models/penguin.obj @@ -0,0 +1,1685 @@ +# Made in Blockbench 3.8.4 +mtllib penguin.mtl +o cube +v -0.09375 0.17922794117647123 -0.04411764705882426 +v -0.09375 0.17922794117647123 -0.41911764705882437 +v -0.09375 -0.008272058823528772 -0.04411764705882426 +v -0.09375 -0.008272058823528772 -0.41911764705882437 +v -0.28125 0.17922794117647123 -0.41911764705882437 +v -0.28125 0.17922794117647123 -0.04411764705882426 +v -0.28125 -0.008272058823528772 -0.41911764705882437 +v -0.28125 -0.008272058823528772 -0.04411764705882426 +vt 0.875 0.0625 +vt 0.875 0 +vt 1 0.0625 +vt 0.875 0 +vt 1 0 +vt 1 0.0625 +vt 0.875 0.0625 +vt 0.875 0 +vt 1 0.0625 +vt 0.875 0 +vt 1 0 +vt 1 0.0625 +vt 0.875 0.0625 +vt 0.875 0 +vt 1 0.0625 +vt 0.875 0 +vt 1 0 +vt 1 0.0625 +vt 0.875 0.0625 +vt 0.875 0 +vt 1 0.0625 +vt 0.875 0 +vt 1 0 +vt 1 0.0625 +vt 0.875 0.0625 +vt 0.875 0 +vt 1 0.0625 +vt 0.875 0 +vt 1 0 +vt 1 0.0625 +vt 0.875 0.0625 +vt 0.875 0 +vt 1 0.0625 +vt 0.875 0 +vt 1 0 +vt 1 0.0625 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 1/1/1 3/2/2 2/3/3 +f 3/4/4 4/5/5 2/6/6 +usemtl m_2 +f 5/7/7 7/8/8 6/9/9 +f 7/10/10 8/11/11 6/12/12 +usemtl m_2 +f 5/13/13 6/14/14 2/15/15 +f 6/16/16 1/17/17 2/18/18 +usemtl m_2 +f 8/19/19 7/20/20 3/21/21 +f 7/22/22 4/23/23 3/24/24 +usemtl m_2 +f 6/25/25 8/26/26 1/27/27 +f 8/28/28 3/29/29 1/30/30 +usemtl m_2 +f 2/31/31 4/32/32 5/33/33 +f 4/34/34 7/35/35 5/36/36 +o cube +v 0.28125 0.17922794117647123 -0.04411764705882426 +v 0.28125 0.17922794117647123 -0.41911764705882437 +v 0.28125 -0.008272058823528772 -0.04411764705882426 +v 0.28125 -0.008272058823528772 -0.41911764705882437 +v 0.09375 0.17922794117647123 -0.41911764705882437 +v 0.09375 0.17922794117647123 -0.04411764705882426 +v 0.09375 -0.008272058823528772 -0.41911764705882437 +v 0.09375 -0.008272058823528772 -0.04411764705882426 +vt 0.9375 0.0625 +vt 0.9375 0 +vt 1 0.0625 +vt 0.9375 0 +vt 1 0 +vt 1 0.0625 +vt 0.9375 0.0625 +vt 0.9375 0 +vt 1 0.0625 +vt 0.9375 0 +vt 1 0 +vt 1 0.0625 +vt 0.9375 0.0625 +vt 0.9375 0 +vt 1 0.0625 +vt 0.9375 0 +vt 1 0 +vt 1 0.0625 +vt 0.9375 0.0625 +vt 0.9375 0 +vt 1 0.0625 +vt 0.9375 0 +vt 1 0 +vt 1 0.0625 +vt 0.9375 0.0625 +vt 0.9375 0 +vt 1 0.0625 +vt 0.9375 0 +vt 1 0 +vt 1 0.0625 +vt 0.9375 0.0625 +vt 0.9375 0 +vt 1 0.0625 +vt 0.9375 0 +vt 1 0 +vt 1 0.0625 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 9/37/37 11/38/38 10/39/39 +f 11/40/40 12/41/41 10/42/42 +usemtl m_2 +f 13/43/43 15/44/44 14/45/45 +f 15/46/46 16/47/47 14/48/48 +usemtl m_2 +f 13/49/49 14/50/50 10/51/51 +f 14/52/52 9/53/53 10/54/54 +usemtl m_2 +f 16/55/55 15/56/56 11/57/57 +f 15/58/58 12/59/59 11/60/60 +usemtl m_2 +f 14/61/61 16/62/62 9/63/63 +f 16/64/64 11/65/65 9/66/66 +usemtl m_2 +f 10/67/67 12/68/68 13/69/69 +f 12/70/70 15/71/71 13/72/72 +o cube +v 0.09375 0.17922794117647123 0.8933823529411757 +v 0.09375 0.17922794117647123 -0.04411764705882426 +v 0.09375 -0.008272058823528772 0.8933823529411757 +v 0.09375 -0.008272058823528772 -0.04411764705882426 +v -0.09375 0.17922794117647123 -0.04411764705882426 +v -0.09375 0.17922794117647123 0.8933823529411757 +v -0.09375 -0.008272058823528772 -0.04411764705882426 +v -0.09375 -0.008272058823528772 0.8933823529411757 +vt 0 0.5625 +vt 0 0.5 +vt 0.3125 0.5625 +vt 0 0.5 +vt 0.3125 0.5 +vt 0.3125 0.5625 +vt 0 0.5625 +vt 0 0.5 +vt 0.3125 0.5625 +vt 0 0.5 +vt 0.3125 0.5 +vt 0.3125 0.5625 +vt 0 0.5625 +vt 0 0.5 +vt 0.3125 0.5625 +vt 0 0.5 +vt 0.3125 0.5 +vt 0.3125 0.5625 +vt 0 0.5625 +vt 0 0.5 +vt 0.3125 0.5625 +vt 0 0.5 +vt 0.3125 0.5 +vt 0.3125 0.5625 +vt 0 0.5625 +vt 0 0.5 +vt 0.3125 0.5625 +vt 0 0.5 +vt 0.3125 0.5 +vt 0.3125 0.5625 +vt 0 0.5625 +vt 0 0.5 +vt 0.3125 0.5625 +vt 0 0.5 +vt 0.3125 0.5 +vt 0.3125 0.5625 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 17/73/73 19/74/74 18/75/75 +f 19/76/76 20/77/77 18/78/78 +usemtl m_2 +f 21/79/79 23/80/80 22/81/81 +f 23/82/82 24/83/83 22/84/84 +usemtl m_2 +f 21/85/85 22/86/86 18/87/87 +f 22/88/88 17/89/89 18/90/90 +usemtl m_2 +f 24/91/91 23/92/92 19/93/93 +f 23/94/94 20/95/95 19/96/96 +usemtl m_2 +f 22/97/97 24/98/98 17/99/99 +f 24/100/100 19/101/101 17/102/102 +usemtl m_2 +f 18/103/103 20/104/104 21/105/105 +f 20/106/106 23/107/107 21/108/108 +o cube +v 0.09375 0.3667279411764711 0.5183823529411757 +v 0.09375 0.3667279411764711 -0.04411764705882426 +v 0.09375 0.17922794117647123 0.5183823529411757 +v 0.09375 0.17922794117647123 -0.04411764705882426 +v -0.09375 0.3667279411764711 -0.04411764705882426 +v -0.09375 0.3667279411764711 0.5183823529411757 +v -0.09375 0.17922794117647123 -0.04411764705882426 +v -0.09375 0.17922794117647123 0.5183823529411757 +vt 0.25 0.75 +vt 0.25 0.5625 +vt 0.3125 0.75 +vt 0.25 0.5625 +vt 0.3125 0.5625 +vt 0.3125 0.75 +vt 0.25 0.75 +vt 0.25 0.5625 +vt 0.3125 0.75 +vt 0.25 0.5625 +vt 0.3125 0.5625 +vt 0.3125 0.75 +vt 0.25 0.75 +vt 0.25 0.5625 +vt 0.3125 0.75 +vt 0.25 0.5625 +vt 0.3125 0.5625 +vt 0.3125 0.75 +vt 0.25 0.75 +vt 0.25 0.5625 +vt 0.3125 0.75 +vt 0.25 0.5625 +vt 0.3125 0.5625 +vt 0.3125 0.75 +vt 0.25 0.75 +vt 0.25 0.5625 +vt 0.3125 0.75 +vt 0.25 0.5625 +vt 0.3125 0.5625 +vt 0.3125 0.75 +vt 0.25 0.75 +vt 0.25 0.5625 +vt 0.3125 0.75 +vt 0.25 0.5625 +vt 0.3125 0.5625 +vt 0.3125 0.75 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 25/109/109 27/110/110 26/111/111 +f 27/112/112 28/113/113 26/114/114 +usemtl m_2 +f 29/115/115 31/116/116 30/117/117 +f 31/118/118 32/119/119 30/120/120 +usemtl m_2 +f 29/121/121 30/122/122 26/123/123 +f 30/124/124 25/125/125 26/126/126 +usemtl m_2 +f 32/127/127 31/128/128 27/129/129 +f 31/130/130 28/131/131 27/132/132 +usemtl m_2 +f 30/133/133 32/134/134 25/135/135 +f 32/136/136 27/137/137 25/138/138 +usemtl m_2 +f 26/139/139 28/140/140 29/141/141 +f 28/142/142 31/143/143 29/144/144 +o cube +v 0.28125 1.679227941176471 0.33088235294117574 +v 0.28125 1.679227941176471 0.14338235294117574 +v 0.28125 0.17922794117647123 0.33088235294117574 +v 0.28125 0.17922794117647123 0.14338235294117574 +v -0.28125 1.679227941176471 0.14338235294117574 +v -0.28125 1.679227941176471 0.33088235294117574 +v -0.28125 0.17922794117647123 0.14338235294117574 +v -0.28125 0.17922794117647123 0.33088235294117574 +vt 0.8125 0.875 +vt 0.8125 0.375 +vt 0.875 0.875 +vt 0.8125 0.375 +vt 0.875 0.375 +vt 0.875 0.875 +vt 0.8125 0.875 +vt 0.8125 0.375 +vt 0.875 0.875 +vt 0.8125 0.375 +vt 0.875 0.375 +vt 0.875 0.875 +vt 0.8125 0.875 +vt 0.8125 0.8125 +vt 1 0.875 +vt 0.8125 0.8125 +vt 1 0.8125 +vt 1 0.875 +vt 0 0.625 +vt 0 0.5625 +vt 0.1875 0.625 +vt 0 0.5625 +vt 0.1875 0.5625 +vt 0.1875 0.625 +vt 0.4375 0.6875 +vt 0.4375 0.1875 +vt 0.625 0.6875 +vt 0.4375 0.1875 +vt 0.625 0.1875 +vt 0.625 0.6875 +vt 0 1 +vt 0 0.5 +vt 0.1875 1 +vt 0 0.5 +vt 0.1875 0.5 +vt 0.1875 1 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 33/145/145 35/146/146 34/147/147 +f 35/148/148 36/149/149 34/150/150 +usemtl m_2 +f 37/151/151 39/152/152 38/153/153 +f 39/154/154 40/155/155 38/156/156 +usemtl m_2 +f 37/157/157 38/158/158 34/159/159 +f 38/160/160 33/161/161 34/162/162 +usemtl m_2 +f 40/163/163 39/164/164 35/165/165 +f 39/166/166 36/167/167 35/168/168 +usemtl m_2 +f 38/169/169 40/170/170 33/171/171 +f 40/172/172 35/173/173 33/174/174 +usemtl m_2 +f 34/175/175 36/176/176 37/177/177 +f 36/178/178 39/179/179 37/180/180 +o cube +v 0.28125 1.3042279411764715 0.14338235294117574 +v 0.28125 1.3042279411764715 -0.04411764705882426 +v 0.28125 0.17922794117647123 0.14338235294117574 +v 0.28125 0.17922794117647123 -0.04411764705882426 +v -0.28125 1.3042279411764715 -0.04411764705882426 +v -0.28125 1.3042279411764715 0.14338235294117574 +v -0.28125 0.17922794117647123 -0.04411764705882426 +v -0.28125 0.17922794117647123 0.14338235294117574 +vt 0.1875 1 +vt 0.1875 0.625 +vt 0.25 1 +vt 0.1875 0.625 +vt 0.25 0.625 +vt 0.25 1 +vt 0.1875 1 +vt 0.1875 0.625 +vt 0.25 1 +vt 0.1875 0.625 +vt 0.25 0.625 +vt 0.25 1 +vt 0.1875 1 +vt 0.1875 0.625 +vt 0.25 1 +vt 0.1875 0.625 +vt 0.25 0.625 +vt 0.25 1 +vt 0.1875 1 +vt 0.1875 0.625 +vt 0.25 1 +vt 0.1875 0.625 +vt 0.25 0.625 +vt 0.25 1 +vt 0.1875 1 +vt 0.1875 0.625 +vt 0.25 1 +vt 0.1875 0.625 +vt 0.25 0.625 +vt 0.25 1 +vt 0.1875 1 +vt 0.1875 0.625 +vt 0.25 1 +vt 0.1875 0.625 +vt 0.25 0.625 +vt 0.25 1 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 41/181/181 43/182/182 42/183/183 +f 43/184/184 44/185/185 42/186/186 +usemtl m_2 +f 45/187/187 47/188/188 46/189/189 +f 47/190/190 48/191/191 46/192/192 +usemtl m_2 +f 45/193/193 46/194/194 42/195/195 +f 46/196/196 41/197/197 42/198/198 +usemtl m_2 +f 48/199/199 47/200/200 43/201/201 +f 47/202/202 44/203/203 43/204/204 +usemtl m_2 +f 46/205/205 48/206/206 41/207/207 +f 48/208/208 43/209/209 41/210/210 +usemtl m_2 +f 42/211/211 44/212/212 45/213/213 +f 44/214/214 47/215/215 45/216/216 +o cube +v 0.28125 1.3042279411764715 -0.04411764705882426 +v 0.28125 1.3042279411764715 -0.23161764705882426 +v 0.28125 0.17922794117647123 -0.04411764705882426 +v 0.28125 0.17922794117647123 -0.23161764705882426 +v -0.28125 1.3042279411764715 -0.23161764705882426 +v -0.28125 1.3042279411764715 -0.04411764705882426 +v -0.28125 0.17922794117647123 -0.23161764705882426 +v -0.28125 0.17922794117647123 -0.04411764705882426 +vt 0 1 +vt 0 0.625 +vt 0.0625 1 +vt 0 0.625 +vt 0.0625 0.625 +vt 0.0625 1 +vt 0 1 +vt 0 0.625 +vt 0.0625 1 +vt 0 0.625 +vt 0.0625 0.625 +vt 0.0625 1 +vt 0 1 +vt 0 0.9375 +vt 0.1875 1 +vt 0 0.9375 +vt 0.1875 0.9375 +vt 0.1875 1 +vt 0 1 +vt 0 0.9375 +vt 0.1875 1 +vt 0 0.9375 +vt 0.1875 0.9375 +vt 0.1875 1 +vt 0 1 +vt 0 0.625 +vt 0.1875 1 +vt 0 0.625 +vt 0.1875 0.625 +vt 0.1875 1 +vt 0 1 +vt 0 0.625 +vt 0.1875 1 +vt 0 0.625 +vt 0.1875 0.625 +vt 0.1875 1 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 49/217/217 51/218/218 50/219/219 +f 51/220/220 52/221/221 50/222/222 +usemtl m_2 +f 53/223/223 55/224/224 54/225/225 +f 55/226/226 56/227/227 54/228/228 +usemtl m_2 +f 53/229/229 54/230/230 50/231/231 +f 54/232/232 49/233/233 50/234/234 +usemtl m_2 +f 56/235/235 55/236/236 51/237/237 +f 55/238/238 52/239/239 51/240/240 +usemtl m_2 +f 54/241/241 56/242/242 49/243/243 +f 56/244/244 51/245/245 49/246/246 +usemtl m_2 +f 50/247/247 52/248/248 53/249/249 +f 52/250/250 55/251/251 53/252/252 +o cube +v 0.28125 1.679227941176471 0.14338235294117574 +v 0.28125 1.679227941176471 -0.23161764705882426 +v 0.28125 1.491727941176471 0.14338235294117574 +v 0.28125 1.491727941176471 -0.23161764705882426 +v -0.28125 1.679227941176471 -0.23161764705882426 +v -0.28125 1.679227941176471 0.14338235294117574 +v -0.28125 1.491727941176471 -0.23161764705882426 +v -0.28125 1.491727941176471 0.14338235294117574 +vt 0.8125 1 +vt 0.8125 0.9375 +vt 1 1 +vt 0.8125 0.9375 +vt 1 0.9375 +vt 1 1 +vt 0.875 1 +vt 0.875 0.9375 +vt 1 1 +vt 0.875 0.9375 +vt 1 0.9375 +vt 1 1 +vt 0.8125 1 +vt 0.8125 0.875 +vt 1 1 +vt 0.8125 0.875 +vt 1 0.875 +vt 1 1 +vt 0 1 +vt 0 0.875 +vt 0.1875 1 +vt 0 0.875 +vt 0.1875 0.875 +vt 0.1875 1 +vt 0 1 +vt 0 0.9375 +vt 0.1875 1 +vt 0 0.9375 +vt 0.1875 0.9375 +vt 0.1875 1 +vt 0.8125 1 +vt 0.8125 0.9375 +vt 1 1 +vt 0.8125 0.9375 +vt 1 0.9375 +vt 1 1 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 57/253/253 59/254/254 58/255/255 +f 59/256/256 60/257/257 58/258/258 +usemtl m_2 +f 61/259/259 63/260/260 62/261/261 +f 63/262/262 64/263/263 62/264/264 +usemtl m_2 +f 61/265/265 62/266/266 58/267/267 +f 62/268/268 57/269/269 58/270/270 +usemtl m_2 +f 64/271/271 63/272/272 59/273/273 +f 63/274/274 60/275/275 59/276/276 +usemtl m_2 +f 62/277/277 64/278/278 57/279/279 +f 64/280/280 59/281/281 57/282/282 +usemtl m_2 +f 58/283/283 60/284/284 61/285/285 +f 60/286/286 63/287/287 61/288/288 +o cube +v 0.28125 1.679227941176471 0.5183823529411757 +v 0.28125 1.679227941176471 0.33088235294117574 +v 0.28125 1.491727941176471 0.5183823529411757 +v 0.28125 1.491727941176471 0.33088235294117574 +v 0.09375 1.679227941176471 0.33088235294117574 +v 0.09375 1.679227941176471 0.5183823529411757 +v 0.09375 1.491727941176471 0.33088235294117574 +v 0.09375 1.491727941176471 0.5183823529411757 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 65/289/289 67/290/290 66/291/291 +f 67/292/292 68/293/293 66/294/294 +usemtl m_2 +f 69/295/295 71/296/296 70/297/297 +f 71/298/298 72/299/299 70/300/300 +usemtl m_2 +f 69/301/301 70/302/302 66/303/303 +f 70/304/304 65/305/305 66/306/306 +usemtl m_2 +f 72/307/307 71/308/308 67/309/309 +f 71/310/310 68/311/311 67/312/312 +usemtl m_2 +f 70/313/313 72/314/314 65/315/315 +f 72/316/316 67/317/317 65/318/318 +usemtl m_2 +f 66/319/319 68/320/320 69/321/321 +f 68/322/322 71/323/323 69/324/324 +o cube +v -0.09375 1.679227941176471 0.5183823529411757 +v -0.09375 1.679227941176471 0.33088235294117574 +v -0.09375 1.491727941176471 0.5183823529411757 +v -0.09375 1.491727941176471 0.33088235294117574 +v -0.28125 1.679227941176471 0.33088235294117574 +v -0.28125 1.679227941176471 0.5183823529411757 +v -0.28125 1.491727941176471 0.33088235294117574 +v -0.28125 1.491727941176471 0.5183823529411757 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vt 0.9375 0.75 +vt 0.9375 0.6875 +vt 1 0.75 +vt 0.9375 0.6875 +vt 1 0.6875 +vt 1 0.75 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 73/325/325 75/326/326 74/327/327 +f 75/328/328 76/329/329 74/330/330 +usemtl m_2 +f 77/331/331 79/332/332 78/333/333 +f 79/334/334 80/335/335 78/336/336 +usemtl m_2 +f 77/337/337 78/338/338 74/339/339 +f 78/340/340 73/341/341 74/342/342 +usemtl m_2 +f 80/343/343 79/344/344 75/345/345 +f 79/346/346 76/347/347 75/348/348 +usemtl m_2 +f 78/349/349 80/350/350 73/351/351 +f 80/352/352 75/353/353 73/354/354 +usemtl m_2 +f 74/355/355 76/356/356 77/357/357 +f 76/358/358 79/359/359 77/360/360 +o cube +v 0.09375 1.491727941176471 -0.23161764705882426 +v 0.09375 1.491727941176471 -0.41911764705882437 +v 0.09375 1.3042279411764715 -0.23161764705882426 +v 0.09375 1.3042279411764715 -0.41911764705882437 +v -0.09375 1.491727941176471 -0.41911764705882437 +v -0.09375 1.491727941176471 -0.23161764705882426 +v -0.09375 1.3042279411764715 -0.41911764705882437 +v -0.09375 1.3042279411764715 -0.23161764705882426 +vt 0.9375 1 +vt 0.9375 0.9375 +vt 1 1 +vt 0.9375 0.9375 +vt 1 0.9375 +vt 1 1 +vt 0.9375 1 +vt 0.9375 0.9375 +vt 1 1 +vt 0.9375 0.9375 +vt 1 0.9375 +vt 1 1 +vt 0.9375 1 +vt 0.9375 0.9375 +vt 1 1 +vt 0.9375 0.9375 +vt 1 0.9375 +vt 1 1 +vt 0.9375 1 +vt 0.9375 0.9375 +vt 1 1 +vt 0.9375 0.9375 +vt 1 0.9375 +vt 1 1 +vt 0.9375 1 +vt 0.9375 0.9375 +vt 1 1 +vt 0.9375 0.9375 +vt 1 0.9375 +vt 1 1 +vt 0.9375 1 +vt 0.9375 0.9375 +vt 1 1 +vt 0.9375 0.9375 +vt 1 0.9375 +vt 1 1 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 81/361/361 83/362/362 82/363/363 +f 83/364/364 84/365/365 82/366/366 +usemtl m_2 +f 85/367/367 87/368/368 86/369/369 +f 87/370/370 88/371/371 86/372/372 +usemtl m_2 +f 85/373/373 86/374/374 82/375/375 +f 86/376/376 81/377/377 82/378/378 +usemtl m_2 +f 88/379/379 87/380/380 83/381/381 +f 87/382/382 84/383/383 83/384/384 +usemtl m_2 +f 86/385/385 88/386/386 81/387/387 +f 88/388/388 83/389/389 81/390/390 +usemtl m_2 +f 82/391/391 84/392/392 85/393/393 +f 84/394/394 87/395/395 85/396/396 +o cube +v 0.09375 1.3979779411764715 -0.41911764705882437 +v 0.09375 1.3979779411764715 -0.6066176470588244 +v 0.09375 1.2104779411764715 -0.41911764705882437 +v 0.09375 1.2104779411764715 -0.6066176470588244 +v -0.09375 1.3979779411764715 -0.6066176470588244 +v -0.09375 1.3979779411764715 -0.41911764705882437 +v -0.09375 1.2104779411764715 -0.6066176470588244 +v -0.09375 1.2104779411764715 -0.41911764705882437 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 89/397/397 91/398/398 90/399/399 +f 91/400/400 92/401/401 90/402/402 +usemtl m_2 +f 93/403/403 95/404/404 94/405/405 +f 95/406/406 96/407/407 94/408/408 +usemtl m_2 +f 93/409/409 94/410/410 90/411/411 +f 94/412/412 89/413/413 90/414/414 +usemtl m_2 +f 96/415/415 95/416/416 91/417/417 +f 95/418/418 92/419/419 91/420/420 +usemtl m_2 +f 94/421/421 96/422/422 89/423/423 +f 96/424/424 91/425/425 89/426/426 +usemtl m_2 +f 90/427/427 92/428/428 93/429/429 +f 92/430/430 95/431/431 93/432/432 +o cube +v 0.09375 1.3042279411764715 -0.23161764705882426 +v 0.09375 1.3042279411764715 -0.41911764705882437 +v 0.09375 1.2104779411764715 -0.23161764705882426 +v 0.09375 1.2104779411764715 -0.41911764705882437 +v -0.09375 1.3042279411764715 -0.41911764705882437 +v -0.09375 1.3042279411764715 -0.23161764705882426 +v -0.09375 1.2104779411764715 -0.41911764705882437 +v -0.09375 1.2104779411764715 -0.23161764705882426 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vt 0 0.5 +vt 0 0.4375 +vt 0.0625 0.5 +vt 0 0.4375 +vt 0.0625 0.4375 +vt 0.0625 0.5 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 97/433/433 99/434/434 98/435/435 +f 99/436/436 100/437/437 98/438/438 +usemtl m_2 +f 101/439/439 103/440/440 102/441/441 +f 103/442/442 104/443/443 102/444/444 +usemtl m_2 +f 101/445/445 102/446/446 98/447/447 +f 102/448/448 97/449/449 98/450/450 +usemtl m_2 +f 104/451/451 103/452/452 99/453/453 +f 103/454/454 100/455/455 99/456/456 +usemtl m_2 +f 102/457/457 104/458/458 97/459/459 +f 104/460/460 99/461/461 97/462/462 +usemtl m_2 +f 98/463/463 100/464/464 101/465/465 +f 100/466/466 103/467/467 101/468/468 +o cube +v -0.28125 1.1167279411764715 0.14338235294117574 +v -0.28125 1.1167279411764715 -0.04411764705882426 +v -0.28125 0.3667279411764711 0.14338235294117574 +v -0.28125 0.3667279411764711 -0.04411764705882426 +v -0.46875 1.1167279411764715 -0.04411764705882426 +v -0.46875 1.1167279411764715 0.14338235294117574 +v -0.46875 0.3667279411764711 -0.04411764705882426 +v -0.46875 0.3667279411764711 0.14338235294117574 +vt 0 1 +vt 0 0.75 +vt 0.0625 1 +vt 0 0.75 +vt 0.0625 0.75 +vt 0.0625 1 +vt 0.0625 0.4375 +vt 0.0625 0.1875 +vt 0.125 0.4375 +vt 0.0625 0.1875 +vt 0.125 0.1875 +vt 0.125 0.4375 +vt 0 0.625 +vt 0 0.5625 +vt 0.0625 0.625 +vt 0 0.5625 +vt 0.0625 0.5625 +vt 0.0625 0.625 +vt 0.1875 0.375 +vt 0.1875 0.3125 +vt 0.3125 0.375 +vt 0.1875 0.3125 +vt 0.3125 0.3125 +vt 0.3125 0.375 +vt 0.1875 0.4375 +vt 0.1875 0.1875 +vt 0.3125 0.4375 +vt 0.1875 0.1875 +vt 0.3125 0.1875 +vt 0.3125 0.4375 +vt 0 0.4375 +vt 0 0.1875 +vt 0.125 0.4375 +vt 0 0.1875 +vt 0.125 0.1875 +vt 0.125 0.4375 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 105/469/469 107/470/470 106/471/471 +f 107/472/472 108/473/473 106/474/474 +usemtl m_2 +f 109/475/475 111/476/476 110/477/477 +f 111/478/478 112/479/479 110/480/480 +usemtl m_2 +f 109/481/481 110/482/482 106/483/483 +f 110/484/484 105/485/485 106/486/486 +usemtl m_2 +f 112/487/487 111/488/488 107/489/489 +f 111/490/490 108/491/491 107/492/492 +usemtl m_2 +f 110/493/493 112/494/494 105/495/495 +f 112/496/496 107/497/497 105/498/498 +usemtl m_2 +f 106/499/499 108/500/500 109/501/501 +f 108/502/502 111/503/503 109/504/504 +o cube +v 0.46875 1.1167279411764715 0.14338235294117574 +v 0.46875 1.1167279411764715 -0.04411764705882426 +v 0.46875 0.3667279411764711 0.14338235294117574 +v 0.46875 0.3667279411764711 -0.04411764705882426 +v 0.28125 1.1167279411764715 -0.04411764705882426 +v 0.28125 1.1167279411764715 0.14338235294117574 +v 0.28125 0.3667279411764711 -0.04411764705882426 +v 0.28125 0.3667279411764711 0.14338235294117574 +vt 0.125 0.4375 +vt 0.125 0.1875 +vt 0.0625 0.4375 +vt 0.125 0.1875 +vt 0.0625 0.1875 +vt 0.0625 0.4375 +vt 0.0625 1 +vt 0.0625 0.75 +vt 0 1 +vt 0.0625 0.75 +vt 0 0.75 +vt 0 1 +vt 0.0625 0.625 +vt 0.0625 0.5625 +vt 0 0.625 +vt 0.0625 0.5625 +vt 0 0.5625 +vt 0 0.625 +vt 0.3125 0.375 +vt 0.3125 0.3125 +vt 0.1875 0.375 +vt 0.3125 0.3125 +vt 0.1875 0.3125 +vt 0.1875 0.375 +vt 0.3125 0.4375 +vt 0.3125 0.1875 +vt 0.1875 0.4375 +vt 0.3125 0.1875 +vt 0.1875 0.1875 +vt 0.1875 0.4375 +vt 0.125 0.4375 +vt 0.125 0.1875 +vt 0 0.4375 +vt 0.125 0.1875 +vt 0 0.1875 +vt 0 0.4375 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 113/505/505 115/506/506 114/507/507 +f 115/508/508 116/509/509 114/510/510 +usemtl m_2 +f 117/511/511 119/512/512 118/513/513 +f 119/514/514 120/515/515 118/516/516 +usemtl m_2 +f 117/517/517 118/518/518 114/519/519 +f 118/520/520 113/521/521 114/522/522 +usemtl m_2 +f 120/523/523 119/524/524 115/525/525 +f 119/526/526 116/527/527 115/528/528 +usemtl m_2 +f 118/529/529 120/530/530 113/531/531 +f 120/532/532 115/533/533 113/534/534 +usemtl m_2 +f 114/535/535 116/536/536 117/537/537 +f 116/538/538 119/539/539 117/540/540 +o cube +v 0.28125 1.491727941176471 -0.04411764705882426 +v 0.28125 1.491727941176471 -0.23161764705882426 +v 0.28125 1.3042279411764715 -0.04411764705882426 +v 0.28125 1.3042279411764715 -0.23161764705882426 +v -0.28125 1.491727941176471 -0.23161764705882426 +v -0.28125 1.491727941176471 -0.04411764705882426 +v -0.28125 1.3042279411764715 -0.23161764705882426 +v -0.28125 1.3042279411764715 -0.04411764705882426 +vt 0 1 +vt 0 0.9375 +vt 0.0625 1 +vt 0 0.9375 +vt 0.0625 0.9375 +vt 0.0625 1 +vt 0.125 0.6875 +vt 0.125 0.625 +vt 0.1875 0.6875 +vt 0.125 0.625 +vt 0.1875 0.625 +vt 0.1875 0.6875 +vt 0 1 +vt 0 0.9375 +vt 0.1875 1 +vt 0 0.9375 +vt 0.1875 0.9375 +vt 0.1875 1 +vt 0 1 +vt 0 0.9375 +vt 0.1875 1 +vt 0 0.9375 +vt 0.1875 0.9375 +vt 0.1875 1 +vt 0 1 +vt 0 0.9375 +vt 0.1875 1 +vt 0 0.9375 +vt 0.1875 0.9375 +vt 0.1875 1 +vt 0 1 +vt 0 0.9375 +vt 0.1875 1 +vt 0 0.9375 +vt 0.1875 0.9375 +vt 0.1875 1 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 121/541/541 123/542/542 122/543/543 +f 123/544/544 124/545/545 122/546/546 +usemtl m_2 +f 125/547/547 127/548/548 126/549/549 +f 127/550/550 128/551/551 126/552/552 +usemtl m_2 +f 125/553/553 126/554/554 122/555/555 +f 126/556/556 121/557/557 122/558/558 +usemtl m_2 +f 128/559/559 127/560/560 123/561/561 +f 127/562/562 124/563/563 123/564/564 +usemtl m_2 +f 126/565/565 128/566/566 121/567/567 +f 128/568/568 123/569/569 121/570/570 +usemtl m_2 +f 122/571/571 124/572/572 125/573/573 +f 124/574/574 127/575/575 125/576/576 +o cube +v 0.28125 1.491727941176471 0.14338235294117574 +v 0.28125 1.491727941176471 -0.04411764705882426 +v 0.28125 1.3042279411764715 0.14338235294117574 +v 0.28125 1.3042279411764715 -0.04411764705882426 +v -0.28125 1.491727941176471 -0.04411764705882426 +v -0.28125 1.491727941176471 0.14338235294117574 +v -0.28125 1.3042279411764715 -0.04411764705882426 +v -0.28125 1.3042279411764715 0.14338235294117574 +vt 0.3125 1 +vt 0.3125 0.8125 +vt 0.5 1 +vt 0.3125 0.8125 +vt 0.5 0.8125 +vt 0.5 1 +vt 0.3125 1 +vt 0.3125 0.8125 +vt 0.5 1 +vt 0.3125 0.8125 +vt 0.5 0.8125 +vt 0.5 1 +vt 0 1 +vt 0 0.9375 +vt 0.1875 1 +vt 0 0.9375 +vt 0.1875 0.9375 +vt 0.1875 1 +vt 0 1 +vt 0 0.9375 +vt 0.1875 1 +vt 0 0.9375 +vt 0.1875 0.9375 +vt 0.1875 1 +vt 0 1 +vt 0 0.9375 +vt 0.1875 1 +vt 0 0.9375 +vt 0.1875 0.9375 +vt 0.1875 1 +vt 0 1 +vt 0 0.9375 +vt 0.1875 1 +vt 0 0.9375 +vt 0.1875 0.9375 +vt 0.1875 1 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn 1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn -1 0 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 -1 0 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +vn 0 0 -1 +usemtl m_2 +f 129/577/577 131/578/578 130/579/579 +f 131/580/580 132/581/581 130/582/582 +usemtl m_2 +f 133/583/583 135/584/584 134/585/585 +f 135/586/586 136/587/587 134/588/588 +usemtl m_2 +f 133/589/589 134/590/590 130/591/591 +f 134/592/592 129/593/593 130/594/594 +usemtl m_2 +f 136/595/595 135/596/596 131/597/597 +f 135/598/598 132/599/599 131/600/600 +usemtl m_2 +f 134/601/601 136/602/602 129/603/603 +f 136/604/604 131/605/605 129/606/606 +usemtl m_2 +f 130/607/607 132/608/608 133/609/609 +f 132/610/610 135/611/611 133/612/612 diff --git a/mod/src/main/resources/assets/dg/textures/penguin.png b/mod/src/main/resources/assets/dg/textures/penguin.png Binary files differnew file mode 100644 index 00000000..4b39154c --- /dev/null +++ b/mod/src/main/resources/assets/dg/textures/penguin.png diff --git a/mod/src/main/resources/defaultConfig.conf b/mod/src/main/resources/defaultConfig.conf new file mode 100755 index 00000000..e69de29b --- /dev/null +++ b/mod/src/main/resources/defaultConfig.conf diff --git a/mod/src/main/resources/gamesdk/darwin/libdiscord_game_sdk.dylib b/mod/src/main/resources/gamesdk/darwin/libdiscord_game_sdk.dylib Binary files differnew file mode 100644 index 00000000..24045f79 --- /dev/null +++ b/mod/src/main/resources/gamesdk/darwin/libdiscord_game_sdk.dylib diff --git a/mod/src/main/resources/gamesdk/linux/libdiscord_game_sdk.so b/mod/src/main/resources/gamesdk/linux/libdiscord_game_sdk.so Binary files differnew file mode 100644 index 00000000..e4657606 --- /dev/null +++ b/mod/src/main/resources/gamesdk/linux/libdiscord_game_sdk.so diff --git a/mod/src/main/resources/gamesdk/win-x64/discord_game_sdk.dll b/mod/src/main/resources/gamesdk/win-x64/discord_game_sdk.dll Binary files differnew file mode 100644 index 00000000..10a8928f --- /dev/null +++ b/mod/src/main/resources/gamesdk/win-x64/discord_game_sdk.dll diff --git a/mod/src/main/resources/gamesdk/win-x86/discord_game_sdk.dll b/mod/src/main/resources/gamesdk/win-x86/discord_game_sdk.dll Binary files differnew file mode 100644 index 00000000..8f1ee0a6 --- /dev/null +++ b/mod/src/main/resources/gamesdk/win-x86/discord_game_sdk.dll diff --git a/mod/src/main/resources/roomdata/00d66020-b34e-429d-9fd3-696bc15cfce2.roomdata b/mod/src/main/resources/roomdata/00d66020-b34e-429d-9fd3-696bc15cfce2.roomdata Binary files differnew file mode 100644 index 00000000..c2898747 --- /dev/null +++ b/mod/src/main/resources/roomdata/00d66020-b34e-429d-9fd3-696bc15cfce2.roomdata diff --git a/mod/src/main/resources/roomdata/01949106-2ddc-4601-9b4c-e934f5d373a6.roomdata b/mod/src/main/resources/roomdata/01949106-2ddc-4601-9b4c-e934f5d373a6.roomdata Binary files differnew file mode 100644 index 00000000..ba8abf1b --- /dev/null +++ b/mod/src/main/resources/roomdata/01949106-2ddc-4601-9b4c-e934f5d373a6.roomdata diff --git a/mod/src/main/resources/roomdata/02b94b9a-8990-446a-993a-9b59de987b16.roomdata b/mod/src/main/resources/roomdata/02b94b9a-8990-446a-993a-9b59de987b16.roomdata Binary files differnew file mode 100644 index 00000000..dd8d633b --- /dev/null +++ b/mod/src/main/resources/roomdata/02b94b9a-8990-446a-993a-9b59de987b16.roomdata diff --git a/mod/src/main/resources/roomdata/05ba6123-3468-4ec3-8e32-0553a8e5d3b2.roomdata b/mod/src/main/resources/roomdata/05ba6123-3468-4ec3-8e32-0553a8e5d3b2.roomdata Binary files differnew file mode 100644 index 00000000..700c4c5c --- /dev/null +++ b/mod/src/main/resources/roomdata/05ba6123-3468-4ec3-8e32-0553a8e5d3b2.roomdata diff --git a/mod/src/main/resources/roomdata/067df8a7-9d28-4fdd-a538-c6d38f126cd2.roomdata b/mod/src/main/resources/roomdata/067df8a7-9d28-4fdd-a538-c6d38f126cd2.roomdata Binary files differnew file mode 100644 index 00000000..51b542fe --- /dev/null +++ b/mod/src/main/resources/roomdata/067df8a7-9d28-4fdd-a538-c6d38f126cd2.roomdata diff --git a/mod/src/main/resources/roomdata/07ce87bb-a49a-412b-a8f7-c9dde9f884de.roomdata b/mod/src/main/resources/roomdata/07ce87bb-a49a-412b-a8f7-c9dde9f884de.roomdata Binary files differnew file mode 100644 index 00000000..cc88f7ea --- /dev/null +++ b/mod/src/main/resources/roomdata/07ce87bb-a49a-412b-a8f7-c9dde9f884de.roomdata diff --git a/mod/src/main/resources/roomdata/0877607a-b8a2-433a-b893-f4de7c83378a.roomdata b/mod/src/main/resources/roomdata/0877607a-b8a2-433a-b893-f4de7c83378a.roomdata Binary files differnew file mode 100644 index 00000000..82646b7a --- /dev/null +++ b/mod/src/main/resources/roomdata/0877607a-b8a2-433a-b893-f4de7c83378a.roomdata diff --git a/mod/src/main/resources/roomdata/09c3072e-3099-4019-a577-7ddc17a9e29d.roomdata b/mod/src/main/resources/roomdata/09c3072e-3099-4019-a577-7ddc17a9e29d.roomdata Binary files differnew file mode 100644 index 00000000..fd3db034 --- /dev/null +++ b/mod/src/main/resources/roomdata/09c3072e-3099-4019-a577-7ddc17a9e29d.roomdata diff --git a/mod/src/main/resources/roomdata/11982f7f-703e-4d98-9d27-4e07ba3fef71.roomdata b/mod/src/main/resources/roomdata/11982f7f-703e-4d98-9d27-4e07ba3fef71.roomdata Binary files differnew file mode 100644 index 00000000..fb41bfe3 --- /dev/null +++ b/mod/src/main/resources/roomdata/11982f7f-703e-4d98-9d27-4e07ba3fef71.roomdata diff --git a/mod/src/main/resources/roomdata/12080b02-4ccc-49ce-9eaf-e7d8946f3984.roomdata b/mod/src/main/resources/roomdata/12080b02-4ccc-49ce-9eaf-e7d8946f3984.roomdata Binary files differnew file mode 100644 index 00000000..e78efe14 --- /dev/null +++ b/mod/src/main/resources/roomdata/12080b02-4ccc-49ce-9eaf-e7d8946f3984.roomdata diff --git a/mod/src/main/resources/roomdata/15083814-fb7b-4791-b5d7-0810dd396b01.roomdata b/mod/src/main/resources/roomdata/15083814-fb7b-4791-b5d7-0810dd396b01.roomdata Binary files differnew file mode 100644 index 00000000..a9b615de --- /dev/null +++ b/mod/src/main/resources/roomdata/15083814-fb7b-4791-b5d7-0810dd396b01.roomdata diff --git a/mod/src/main/resources/roomdata/1ae1d65c-2c72-4ed6-afab-84d0de759e1e.roomdata b/mod/src/main/resources/roomdata/1ae1d65c-2c72-4ed6-afab-84d0de759e1e.roomdata Binary files differnew file mode 100644 index 00000000..f6989947 --- /dev/null +++ b/mod/src/main/resources/roomdata/1ae1d65c-2c72-4ed6-afab-84d0de759e1e.roomdata diff --git a/mod/src/main/resources/roomdata/1df3a849-2a5b-451d-8bd7-971eb608363c.roomdata b/mod/src/main/resources/roomdata/1df3a849-2a5b-451d-8bd7-971eb608363c.roomdata Binary files differnew file mode 100644 index 00000000..88b5fb2e --- /dev/null +++ b/mod/src/main/resources/roomdata/1df3a849-2a5b-451d-8bd7-971eb608363c.roomdata diff --git a/mod/src/main/resources/roomdata/1e8d4327-7465-4bff-a8c7-505528273985.roomdata b/mod/src/main/resources/roomdata/1e8d4327-7465-4bff-a8c7-505528273985.roomdata Binary files differnew file mode 100644 index 00000000..5b35cca3 --- /dev/null +++ b/mod/src/main/resources/roomdata/1e8d4327-7465-4bff-a8c7-505528273985.roomdata diff --git a/mod/src/main/resources/roomdata/23d6e1f6-efa3-476b-b452-ad5cf6a37be9.roomdata b/mod/src/main/resources/roomdata/23d6e1f6-efa3-476b-b452-ad5cf6a37be9.roomdata Binary files differnew file mode 100644 index 00000000..7d1e0a5b --- /dev/null +++ b/mod/src/main/resources/roomdata/23d6e1f6-efa3-476b-b452-ad5cf6a37be9.roomdata diff --git a/mod/src/main/resources/roomdata/250624ee-bb7a-4330-b698-a78f5e44ba99.roomdata b/mod/src/main/resources/roomdata/250624ee-bb7a-4330-b698-a78f5e44ba99.roomdata Binary files differnew file mode 100644 index 00000000..e08121e6 --- /dev/null +++ b/mod/src/main/resources/roomdata/250624ee-bb7a-4330-b698-a78f5e44ba99.roomdata diff --git a/mod/src/main/resources/roomdata/25956a46-7094-4a9e-b5d9-c9f8291ffef4.roomdata b/mod/src/main/resources/roomdata/25956a46-7094-4a9e-b5d9-c9f8291ffef4.roomdata Binary files differnew file mode 100644 index 00000000..bc5657c5 --- /dev/null +++ b/mod/src/main/resources/roomdata/25956a46-7094-4a9e-b5d9-c9f8291ffef4.roomdata diff --git a/mod/src/main/resources/roomdata/296fd7ea-4ac5-46e5-beb9-5d27019e3796.roomdata b/mod/src/main/resources/roomdata/296fd7ea-4ac5-46e5-beb9-5d27019e3796.roomdata Binary files differnew file mode 100644 index 00000000..3ad857f4 --- /dev/null +++ b/mod/src/main/resources/roomdata/296fd7ea-4ac5-46e5-beb9-5d27019e3796.roomdata diff --git a/mod/src/main/resources/roomdata/2b5cb4ef-00a3-4aae-baec-d2094a158d60.roomdata b/mod/src/main/resources/roomdata/2b5cb4ef-00a3-4aae-baec-d2094a158d60.roomdata Binary files differnew file mode 100644 index 00000000..d28cf558 --- /dev/null +++ b/mod/src/main/resources/roomdata/2b5cb4ef-00a3-4aae-baec-d2094a158d60.roomdata diff --git a/mod/src/main/resources/roomdata/2ccc73b5-883f-4436-9b8f-1a32123b2cb9.roomdata b/mod/src/main/resources/roomdata/2ccc73b5-883f-4436-9b8f-1a32123b2cb9.roomdata Binary files differnew file mode 100644 index 00000000..e1a6f670 --- /dev/null +++ b/mod/src/main/resources/roomdata/2ccc73b5-883f-4436-9b8f-1a32123b2cb9.roomdata diff --git a/mod/src/main/resources/roomdata/2d9705f3-2e69-4035-905d-6b11d6ee270b.roomdata b/mod/src/main/resources/roomdata/2d9705f3-2e69-4035-905d-6b11d6ee270b.roomdata Binary files differnew file mode 100644 index 00000000..0383d611 --- /dev/null +++ b/mod/src/main/resources/roomdata/2d9705f3-2e69-4035-905d-6b11d6ee270b.roomdata diff --git a/mod/src/main/resources/roomdata/2f7927cc-4ce0-4f02-a81a-88d5709248e8.roomdata b/mod/src/main/resources/roomdata/2f7927cc-4ce0-4f02-a81a-88d5709248e8.roomdata Binary files differnew file mode 100644 index 00000000..101d4d8f --- /dev/null +++ b/mod/src/main/resources/roomdata/2f7927cc-4ce0-4f02-a81a-88d5709248e8.roomdata diff --git a/mod/src/main/resources/roomdata/31749ba0-8b9d-4129-b3c9-ee78d9fdb9d7.roomdata b/mod/src/main/resources/roomdata/31749ba0-8b9d-4129-b3c9-ee78d9fdb9d7.roomdata Binary files differnew file mode 100644 index 00000000..9b349d9f --- /dev/null +++ b/mod/src/main/resources/roomdata/31749ba0-8b9d-4129-b3c9-ee78d9fdb9d7.roomdata diff --git a/mod/src/main/resources/roomdata/31766264-1004-492f-9d65-cb5deaff82f0.roomdata b/mod/src/main/resources/roomdata/31766264-1004-492f-9d65-cb5deaff82f0.roomdata Binary files differnew file mode 100644 index 00000000..9fcaccc9 --- /dev/null +++ b/mod/src/main/resources/roomdata/31766264-1004-492f-9d65-cb5deaff82f0.roomdata diff --git a/mod/src/main/resources/roomdata/3406a386-c56d-47de-a0ad-aa0ab74d2abb.roomdata b/mod/src/main/resources/roomdata/3406a386-c56d-47de-a0ad-aa0ab74d2abb.roomdata Binary files differnew file mode 100644 index 00000000..e4c819ed --- /dev/null +++ b/mod/src/main/resources/roomdata/3406a386-c56d-47de-a0ad-aa0ab74d2abb.roomdata diff --git a/mod/src/main/resources/roomdata/340c5665-e59b-42c1-bf84-8fc03d38981f.roomdata b/mod/src/main/resources/roomdata/340c5665-e59b-42c1-bf84-8fc03d38981f.roomdata Binary files differnew file mode 100644 index 00000000..946972cc --- /dev/null +++ b/mod/src/main/resources/roomdata/340c5665-e59b-42c1-bf84-8fc03d38981f.roomdata diff --git a/mod/src/main/resources/roomdata/34639497-d991-4137-83c4-db0a25542b71.roomdata b/mod/src/main/resources/roomdata/34639497-d991-4137-83c4-db0a25542b71.roomdata Binary files differnew file mode 100644 index 00000000..99f82f4a --- /dev/null +++ b/mod/src/main/resources/roomdata/34639497-d991-4137-83c4-db0a25542b71.roomdata diff --git a/mod/src/main/resources/roomdata/35fb741d-b0b1-471a-a5b6-8224f99a1133.roomdata b/mod/src/main/resources/roomdata/35fb741d-b0b1-471a-a5b6-8224f99a1133.roomdata Binary files differnew file mode 100644 index 00000000..02235155 --- /dev/null +++ b/mod/src/main/resources/roomdata/35fb741d-b0b1-471a-a5b6-8224f99a1133.roomdata diff --git a/mod/src/main/resources/roomdata/388e95fc-4775-4747-8473-5329fbb8e5cc.roomdata b/mod/src/main/resources/roomdata/388e95fc-4775-4747-8473-5329fbb8e5cc.roomdata Binary files differnew file mode 100644 index 00000000..b03478d5 --- /dev/null +++ b/mod/src/main/resources/roomdata/388e95fc-4775-4747-8473-5329fbb8e5cc.roomdata diff --git a/mod/src/main/resources/roomdata/38affd31-fc6f-44cd-a41e-ae7d0589ba0d.roomdata b/mod/src/main/resources/roomdata/38affd31-fc6f-44cd-a41e-ae7d0589ba0d.roomdata Binary files differnew file mode 100644 index 00000000..b2442ea5 --- /dev/null +++ b/mod/src/main/resources/roomdata/38affd31-fc6f-44cd-a41e-ae7d0589ba0d.roomdata diff --git a/mod/src/main/resources/roomdata/3acb9949-d252-4f16-9983-a1fcdc38a6cf.roomdata b/mod/src/main/resources/roomdata/3acb9949-d252-4f16-9983-a1fcdc38a6cf.roomdata Binary files differnew file mode 100644 index 00000000..b1b9bbee --- /dev/null +++ b/mod/src/main/resources/roomdata/3acb9949-d252-4f16-9983-a1fcdc38a6cf.roomdata diff --git a/mod/src/main/resources/roomdata/4067578d-c259-4f89-8b88-a891b2decbbf.roomdata b/mod/src/main/resources/roomdata/4067578d-c259-4f89-8b88-a891b2decbbf.roomdata Binary files differnew file mode 100644 index 00000000..054b7b76 --- /dev/null +++ b/mod/src/main/resources/roomdata/4067578d-c259-4f89-8b88-a891b2decbbf.roomdata diff --git a/mod/src/main/resources/roomdata/40fb4b64-18d7-4301-b899-0da7b1d466c1.roomdata b/mod/src/main/resources/roomdata/40fb4b64-18d7-4301-b899-0da7b1d466c1.roomdata Binary files differnew file mode 100644 index 00000000..ee18bbc8 --- /dev/null +++ b/mod/src/main/resources/roomdata/40fb4b64-18d7-4301-b899-0da7b1d466c1.roomdata diff --git a/mod/src/main/resources/roomdata/41086d97-5e36-41a5-88ff-d3fb296791ce.roomdata b/mod/src/main/resources/roomdata/41086d97-5e36-41a5-88ff-d3fb296791ce.roomdata Binary files differnew file mode 100644 index 00000000..510995d4 --- /dev/null +++ b/mod/src/main/resources/roomdata/41086d97-5e36-41a5-88ff-d3fb296791ce.roomdata diff --git a/mod/src/main/resources/roomdata/42029218-9142-4286-b184-e17b3734886f.roomdata b/mod/src/main/resources/roomdata/42029218-9142-4286-b184-e17b3734886f.roomdata Binary files differnew file mode 100644 index 00000000..59506da6 --- /dev/null +++ b/mod/src/main/resources/roomdata/42029218-9142-4286-b184-e17b3734886f.roomdata diff --git a/mod/src/main/resources/roomdata/43c74bd0-77f6-4a2b-8edb-c227a72abf0f.roomdata b/mod/src/main/resources/roomdata/43c74bd0-77f6-4a2b-8edb-c227a72abf0f.roomdata Binary files differnew file mode 100644 index 00000000..8a37dc95 --- /dev/null +++ b/mod/src/main/resources/roomdata/43c74bd0-77f6-4a2b-8edb-c227a72abf0f.roomdata diff --git a/mod/src/main/resources/roomdata/44d9b135-d2ca-4350-969e-6e9c34af2fe6.roomdata b/mod/src/main/resources/roomdata/44d9b135-d2ca-4350-969e-6e9c34af2fe6.roomdata Binary files differnew file mode 100644 index 00000000..d02da4a7 --- /dev/null +++ b/mod/src/main/resources/roomdata/44d9b135-d2ca-4350-969e-6e9c34af2fe6.roomdata diff --git a/mod/src/main/resources/roomdata/4538898f-8e79-4d53-aae6-08e4df6abb61.roomdata b/mod/src/main/resources/roomdata/4538898f-8e79-4d53-aae6-08e4df6abb61.roomdata Binary files differnew file mode 100644 index 00000000..c1620a2e --- /dev/null +++ b/mod/src/main/resources/roomdata/4538898f-8e79-4d53-aae6-08e4df6abb61.roomdata diff --git a/mod/src/main/resources/roomdata/4b5f4983-0453-4402-821c-804f092d1ecd.roomdata b/mod/src/main/resources/roomdata/4b5f4983-0453-4402-821c-804f092d1ecd.roomdata Binary files differnew file mode 100644 index 00000000..fc743f64 --- /dev/null +++ b/mod/src/main/resources/roomdata/4b5f4983-0453-4402-821c-804f092d1ecd.roomdata diff --git a/mod/src/main/resources/roomdata/4e8087d2-0c64-4558-b4ff-4be94275a320.roomdata b/mod/src/main/resources/roomdata/4e8087d2-0c64-4558-b4ff-4be94275a320.roomdata Binary files differnew file mode 100644 index 00000000..1e581560 --- /dev/null +++ b/mod/src/main/resources/roomdata/4e8087d2-0c64-4558-b4ff-4be94275a320.roomdata diff --git a/mod/src/main/resources/roomdata/4ed557b1-553c-4ecc-b3c1-88dd9da6d33c.roomdata b/mod/src/main/resources/roomdata/4ed557b1-553c-4ecc-b3c1-88dd9da6d33c.roomdata Binary files differnew file mode 100644 index 00000000..e04863f4 --- /dev/null +++ b/mod/src/main/resources/roomdata/4ed557b1-553c-4ecc-b3c1-88dd9da6d33c.roomdata diff --git a/mod/src/main/resources/roomdata/4f8be93c-f3e7-47ca-9e0d-87261f5fc386.roomdata b/mod/src/main/resources/roomdata/4f8be93c-f3e7-47ca-9e0d-87261f5fc386.roomdata Binary files differnew file mode 100644 index 00000000..250c7b16 --- /dev/null +++ b/mod/src/main/resources/roomdata/4f8be93c-f3e7-47ca-9e0d-87261f5fc386.roomdata diff --git a/mod/src/main/resources/roomdata/4ffce449-eab8-470b-bc8c-d30507248fc2.roomdata b/mod/src/main/resources/roomdata/4ffce449-eab8-470b-bc8c-d30507248fc2.roomdata Binary files differnew file mode 100644 index 00000000..68fab05f --- /dev/null +++ b/mod/src/main/resources/roomdata/4ffce449-eab8-470b-bc8c-d30507248fc2.roomdata diff --git a/mod/src/main/resources/roomdata/5000be9d-3081-4a5e-8563-dd826705663a.roomdata b/mod/src/main/resources/roomdata/5000be9d-3081-4a5e-8563-dd826705663a.roomdata Binary files differnew file mode 100644 index 00000000..5fb8ed4b --- /dev/null +++ b/mod/src/main/resources/roomdata/5000be9d-3081-4a5e-8563-dd826705663a.roomdata diff --git a/mod/src/main/resources/roomdata/54008e69-d31e-4ed2-9ad0-870a3ad5ee1a.roomdata b/mod/src/main/resources/roomdata/54008e69-d31e-4ed2-9ad0-870a3ad5ee1a.roomdata Binary files differnew file mode 100644 index 00000000..1446bedb --- /dev/null +++ b/mod/src/main/resources/roomdata/54008e69-d31e-4ed2-9ad0-870a3ad5ee1a.roomdata diff --git a/mod/src/main/resources/roomdata/54aaf168-7039-48dc-99a3-8d1f02d79097.roomdata b/mod/src/main/resources/roomdata/54aaf168-7039-48dc-99a3-8d1f02d79097.roomdata Binary files differnew file mode 100644 index 00000000..aa1998ab --- /dev/null +++ b/mod/src/main/resources/roomdata/54aaf168-7039-48dc-99a3-8d1f02d79097.roomdata diff --git a/mod/src/main/resources/roomdata/5aef2a82-42a3-495a-9e72-63a9b611e1cb.roomdata b/mod/src/main/resources/roomdata/5aef2a82-42a3-495a-9e72-63a9b611e1cb.roomdata Binary files differnew file mode 100644 index 00000000..6861efef --- /dev/null +++ b/mod/src/main/resources/roomdata/5aef2a82-42a3-495a-9e72-63a9b611e1cb.roomdata diff --git a/mod/src/main/resources/roomdata/5b6968ce-4a5b-4a48-8cb3-423ff9a7788d.roomdata b/mod/src/main/resources/roomdata/5b6968ce-4a5b-4a48-8cb3-423ff9a7788d.roomdata Binary files differnew file mode 100644 index 00000000..dbf90b36 --- /dev/null +++ b/mod/src/main/resources/roomdata/5b6968ce-4a5b-4a48-8cb3-423ff9a7788d.roomdata diff --git a/mod/src/main/resources/roomdata/63634341-8ef3-4197-aafa-17f5875dd307.roomdata b/mod/src/main/resources/roomdata/63634341-8ef3-4197-aafa-17f5875dd307.roomdata Binary files differnew file mode 100644 index 00000000..eb267e0b --- /dev/null +++ b/mod/src/main/resources/roomdata/63634341-8ef3-4197-aafa-17f5875dd307.roomdata diff --git a/mod/src/main/resources/roomdata/6367a338-dd48-4c30-9e03-7ff6b5c7a936.roomdata b/mod/src/main/resources/roomdata/6367a338-dd48-4c30-9e03-7ff6b5c7a936.roomdata Binary files differnew file mode 100644 index 00000000..7b130d82 --- /dev/null +++ b/mod/src/main/resources/roomdata/6367a338-dd48-4c30-9e03-7ff6b5c7a936.roomdata diff --git a/mod/src/main/resources/roomdata/65d8264d-f47c-4306-b89f-46e28b117511.roomdata b/mod/src/main/resources/roomdata/65d8264d-f47c-4306-b89f-46e28b117511.roomdata Binary files differnew file mode 100644 index 00000000..b23716ab --- /dev/null +++ b/mod/src/main/resources/roomdata/65d8264d-f47c-4306-b89f-46e28b117511.roomdata diff --git a/mod/src/main/resources/roomdata/6b0dfb3e-c86c-41d1-8526-a172027dbb8d.roomdata b/mod/src/main/resources/roomdata/6b0dfb3e-c86c-41d1-8526-a172027dbb8d.roomdata Binary files differnew file mode 100644 index 00000000..7a24fffe --- /dev/null +++ b/mod/src/main/resources/roomdata/6b0dfb3e-c86c-41d1-8526-a172027dbb8d.roomdata diff --git a/mod/src/main/resources/roomdata/6b7256ae-8673-4c2f-825f-6cd727801ea9.roomdata b/mod/src/main/resources/roomdata/6b7256ae-8673-4c2f-825f-6cd727801ea9.roomdata Binary files differnew file mode 100644 index 00000000..2f8ca05d --- /dev/null +++ b/mod/src/main/resources/roomdata/6b7256ae-8673-4c2f-825f-6cd727801ea9.roomdata diff --git a/mod/src/main/resources/roomdata/6dcddc04-c094-4b9b-8c05-b101e8f3dd27.roomdata b/mod/src/main/resources/roomdata/6dcddc04-c094-4b9b-8c05-b101e8f3dd27.roomdata Binary files differnew file mode 100644 index 00000000..e775f23e --- /dev/null +++ b/mod/src/main/resources/roomdata/6dcddc04-c094-4b9b-8c05-b101e8f3dd27.roomdata diff --git a/mod/src/main/resources/roomdata/6fac9602-c596-458f-9750-9b331e2cb845.roomdata b/mod/src/main/resources/roomdata/6fac9602-c596-458f-9750-9b331e2cb845.roomdata Binary files differnew file mode 100644 index 00000000..d1173e62 --- /dev/null +++ b/mod/src/main/resources/roomdata/6fac9602-c596-458f-9750-9b331e2cb845.roomdata diff --git a/mod/src/main/resources/roomdata/70a1451a-5430-40bd-b20b-13245aac910a.roomdata b/mod/src/main/resources/roomdata/70a1451a-5430-40bd-b20b-13245aac910a.roomdata Binary files differnew file mode 100644 index 00000000..85216806 --- /dev/null +++ b/mod/src/main/resources/roomdata/70a1451a-5430-40bd-b20b-13245aac910a.roomdata diff --git a/mod/src/main/resources/roomdata/7a594650-2a42-46e5-81a6-9b7d198e9c1c.roomdata b/mod/src/main/resources/roomdata/7a594650-2a42-46e5-81a6-9b7d198e9c1c.roomdata Binary files differnew file mode 100644 index 00000000..cd31d247 --- /dev/null +++ b/mod/src/main/resources/roomdata/7a594650-2a42-46e5-81a6-9b7d198e9c1c.roomdata diff --git a/mod/src/main/resources/roomdata/7d975e04-15c8-40cb-8c12-d664edc1b0d7.roomdata b/mod/src/main/resources/roomdata/7d975e04-15c8-40cb-8c12-d664edc1b0d7.roomdata Binary files differnew file mode 100644 index 00000000..c5396b01 --- /dev/null +++ b/mod/src/main/resources/roomdata/7d975e04-15c8-40cb-8c12-d664edc1b0d7.roomdata diff --git a/mod/src/main/resources/roomdata/7dd6596f-c647-4144-9eec-fb4690e12251.roomdata b/mod/src/main/resources/roomdata/7dd6596f-c647-4144-9eec-fb4690e12251.roomdata Binary files differnew file mode 100644 index 00000000..ad1da134 --- /dev/null +++ b/mod/src/main/resources/roomdata/7dd6596f-c647-4144-9eec-fb4690e12251.roomdata diff --git a/mod/src/main/resources/roomdata/8116e928-56f1-4e0b-933a-f86b841938c8.roomdata b/mod/src/main/resources/roomdata/8116e928-56f1-4e0b-933a-f86b841938c8.roomdata Binary files differnew file mode 100644 index 00000000..82029939 --- /dev/null +++ b/mod/src/main/resources/roomdata/8116e928-56f1-4e0b-933a-f86b841938c8.roomdata diff --git a/mod/src/main/resources/roomdata/81cf3e0b-70c5-4803-9169-7e7864b096ce.roomdata b/mod/src/main/resources/roomdata/81cf3e0b-70c5-4803-9169-7e7864b096ce.roomdata Binary files differnew file mode 100644 index 00000000..f9030edb --- /dev/null +++ b/mod/src/main/resources/roomdata/81cf3e0b-70c5-4803-9169-7e7864b096ce.roomdata diff --git a/mod/src/main/resources/roomdata/83e1ab6b-ad44-469e-a6bf-71c6bebcab4b.roomdata b/mod/src/main/resources/roomdata/83e1ab6b-ad44-469e-a6bf-71c6bebcab4b.roomdata Binary files differnew file mode 100644 index 00000000..3fbeac44 --- /dev/null +++ b/mod/src/main/resources/roomdata/83e1ab6b-ad44-469e-a6bf-71c6bebcab4b.roomdata diff --git a/mod/src/main/resources/roomdata/845aec22-bc9e-4d50-b8de-db67188232e9.roomdata b/mod/src/main/resources/roomdata/845aec22-bc9e-4d50-b8de-db67188232e9.roomdata Binary files differnew file mode 100644 index 00000000..1f4f1502 --- /dev/null +++ b/mod/src/main/resources/roomdata/845aec22-bc9e-4d50-b8de-db67188232e9.roomdata diff --git a/mod/src/main/resources/roomdata/86a3b53b-6ede-43bd-8988-135001149d4b.roomdata b/mod/src/main/resources/roomdata/86a3b53b-6ede-43bd-8988-135001149d4b.roomdata Binary files differnew file mode 100644 index 00000000..dc802f6d --- /dev/null +++ b/mod/src/main/resources/roomdata/86a3b53b-6ede-43bd-8988-135001149d4b.roomdata diff --git a/mod/src/main/resources/roomdata/8b4ec0bf-b783-4e66-b5fa-89493ac6efa1.roomdata b/mod/src/main/resources/roomdata/8b4ec0bf-b783-4e66-b5fa-89493ac6efa1.roomdata Binary files differnew file mode 100644 index 00000000..ca5e4112 --- /dev/null +++ b/mod/src/main/resources/roomdata/8b4ec0bf-b783-4e66-b5fa-89493ac6efa1.roomdata diff --git a/mod/src/main/resources/roomdata/8c184746-6857-480a-958e-f22e09bb1295.roomdata b/mod/src/main/resources/roomdata/8c184746-6857-480a-958e-f22e09bb1295.roomdata Binary files differnew file mode 100644 index 00000000..9a52caa7 --- /dev/null +++ b/mod/src/main/resources/roomdata/8c184746-6857-480a-958e-f22e09bb1295.roomdata diff --git a/mod/src/main/resources/roomdata/8e6409d8-ea3f-4348-ae30-f8f1e15d05b9.roomdata b/mod/src/main/resources/roomdata/8e6409d8-ea3f-4348-ae30-f8f1e15d05b9.roomdata Binary files differnew file mode 100644 index 00000000..f97210fe --- /dev/null +++ b/mod/src/main/resources/roomdata/8e6409d8-ea3f-4348-ae30-f8f1e15d05b9.roomdata diff --git a/mod/src/main/resources/roomdata/8f317c52-6550-42dd-829b-2a477389fe89.roomdata b/mod/src/main/resources/roomdata/8f317c52-6550-42dd-829b-2a477389fe89.roomdata Binary files differnew file mode 100644 index 00000000..8e3cbeb0 --- /dev/null +++ b/mod/src/main/resources/roomdata/8f317c52-6550-42dd-829b-2a477389fe89.roomdata diff --git a/mod/src/main/resources/roomdata/9087fdc7-43e2-4736-b53b-33477ac65351.roomdata b/mod/src/main/resources/roomdata/9087fdc7-43e2-4736-b53b-33477ac65351.roomdata Binary files differnew file mode 100644 index 00000000..43cd23af --- /dev/null +++ b/mod/src/main/resources/roomdata/9087fdc7-43e2-4736-b53b-33477ac65351.roomdata diff --git a/mod/src/main/resources/roomdata/91068a01-bd3e-402c-99aa-e148f9f04c41.roomdata b/mod/src/main/resources/roomdata/91068a01-bd3e-402c-99aa-e148f9f04c41.roomdata Binary files differnew file mode 100644 index 00000000..6ef74324 --- /dev/null +++ b/mod/src/main/resources/roomdata/91068a01-bd3e-402c-99aa-e148f9f04c41.roomdata diff --git a/mod/src/main/resources/roomdata/9139cb1c-b6f3-4bac-92de-909b1eb73449.roomdata b/mod/src/main/resources/roomdata/9139cb1c-b6f3-4bac-92de-909b1eb73449.roomdata Binary files differnew file mode 100644 index 00000000..4f1c607e --- /dev/null +++ b/mod/src/main/resources/roomdata/9139cb1c-b6f3-4bac-92de-909b1eb73449.roomdata diff --git a/mod/src/main/resources/roomdata/95c57abe-34d4-443c-baac-11d43cbc821f.roomdata b/mod/src/main/resources/roomdata/95c57abe-34d4-443c-baac-11d43cbc821f.roomdata Binary files differnew file mode 100644 index 00000000..fae6f539 --- /dev/null +++ b/mod/src/main/resources/roomdata/95c57abe-34d4-443c-baac-11d43cbc821f.roomdata diff --git a/mod/src/main/resources/roomdata/9650cb39-5f22-45f4-86cd-5d197a4266e5.roomdata b/mod/src/main/resources/roomdata/9650cb39-5f22-45f4-86cd-5d197a4266e5.roomdata Binary files differnew file mode 100644 index 00000000..0467aaea --- /dev/null +++ b/mod/src/main/resources/roomdata/9650cb39-5f22-45f4-86cd-5d197a4266e5.roomdata diff --git a/mod/src/main/resources/roomdata/9890fbac-d382-4525-ab88-fe1ebc118702.roomdata b/mod/src/main/resources/roomdata/9890fbac-d382-4525-ab88-fe1ebc118702.roomdata Binary files differnew file mode 100644 index 00000000..73442dc2 --- /dev/null +++ b/mod/src/main/resources/roomdata/9890fbac-d382-4525-ab88-fe1ebc118702.roomdata diff --git a/mod/src/main/resources/roomdata/990f6e4c-f7cf-4d27-ae91-11219b85861f.roomdata b/mod/src/main/resources/roomdata/990f6e4c-f7cf-4d27-ae91-11219b85861f.roomdata Binary files differnew file mode 100644 index 00000000..80c679fe --- /dev/null +++ b/mod/src/main/resources/roomdata/990f6e4c-f7cf-4d27-ae91-11219b85861f.roomdata diff --git a/mod/src/main/resources/roomdata/9a0e71bf-babd-421e-a785-442c13d5a8b2.roomdata b/mod/src/main/resources/roomdata/9a0e71bf-babd-421e-a785-442c13d5a8b2.roomdata Binary files differnew file mode 100644 index 00000000..ebd1d67e --- /dev/null +++ b/mod/src/main/resources/roomdata/9a0e71bf-babd-421e-a785-442c13d5a8b2.roomdata diff --git a/mod/src/main/resources/roomdata/9b949f89-1542-4bcf-9bf3-063ec69bc5f4.roomdata b/mod/src/main/resources/roomdata/9b949f89-1542-4bcf-9bf3-063ec69bc5f4.roomdata Binary files differnew file mode 100644 index 00000000..d14dc314 --- /dev/null +++ b/mod/src/main/resources/roomdata/9b949f89-1542-4bcf-9bf3-063ec69bc5f4.roomdata diff --git a/mod/src/main/resources/roomdata/9cd523a2-0c7f-4072-a374-9b99d59554ea.roomdata b/mod/src/main/resources/roomdata/9cd523a2-0c7f-4072-a374-9b99d59554ea.roomdata Binary files differnew file mode 100644 index 00000000..60e89356 --- /dev/null +++ b/mod/src/main/resources/roomdata/9cd523a2-0c7f-4072-a374-9b99d59554ea.roomdata diff --git a/mod/src/main/resources/roomdata/9fa09d68-c483-4320-872e-9e07b049ee37.roomdata b/mod/src/main/resources/roomdata/9fa09d68-c483-4320-872e-9e07b049ee37.roomdata Binary files differnew file mode 100644 index 00000000..1ff815b7 --- /dev/null +++ b/mod/src/main/resources/roomdata/9fa09d68-c483-4320-872e-9e07b049ee37.roomdata diff --git a/mod/src/main/resources/roomdata/a053f4fa-d6b2-4aef-ae3e-97c7eee0252e.roomdata b/mod/src/main/resources/roomdata/a053f4fa-d6b2-4aef-ae3e-97c7eee0252e.roomdata Binary files differnew file mode 100644 index 00000000..964c2d7a --- /dev/null +++ b/mod/src/main/resources/roomdata/a053f4fa-d6b2-4aef-ae3e-97c7eee0252e.roomdata diff --git a/mod/src/main/resources/roomdata/a069f006-0728-4952-8d9f-1d318cee60d8.roomdata b/mod/src/main/resources/roomdata/a069f006-0728-4952-8d9f-1d318cee60d8.roomdata Binary files differnew file mode 100644 index 00000000..ceb1fbbc --- /dev/null +++ b/mod/src/main/resources/roomdata/a069f006-0728-4952-8d9f-1d318cee60d8.roomdata diff --git a/mod/src/main/resources/roomdata/a0c57185-4e1a-4fdd-979d-6ed0957e78fb.roomdata b/mod/src/main/resources/roomdata/a0c57185-4e1a-4fdd-979d-6ed0957e78fb.roomdata Binary files differnew file mode 100644 index 00000000..20c61ab4 --- /dev/null +++ b/mod/src/main/resources/roomdata/a0c57185-4e1a-4fdd-979d-6ed0957e78fb.roomdata diff --git a/mod/src/main/resources/roomdata/a1c8fd24-c105-49b6-ba56-51dfbb7023cb.roomdata b/mod/src/main/resources/roomdata/a1c8fd24-c105-49b6-ba56-51dfbb7023cb.roomdata Binary files differnew file mode 100644 index 00000000..f450d06c --- /dev/null +++ b/mod/src/main/resources/roomdata/a1c8fd24-c105-49b6-ba56-51dfbb7023cb.roomdata diff --git a/mod/src/main/resources/roomdata/a2c5d503-55e7-4e5c-8fc0-5d37f2ac19bf.roomdata b/mod/src/main/resources/roomdata/a2c5d503-55e7-4e5c-8fc0-5d37f2ac19bf.roomdata Binary files differnew file mode 100644 index 00000000..54dc0a6a --- /dev/null +++ b/mod/src/main/resources/roomdata/a2c5d503-55e7-4e5c-8fc0-5d37f2ac19bf.roomdata diff --git a/mod/src/main/resources/roomdata/a5b419e7-49ee-4d6d-bdce-470f508b315d.roomdata b/mod/src/main/resources/roomdata/a5b419e7-49ee-4d6d-bdce-470f508b315d.roomdata Binary files differnew file mode 100644 index 00000000..00ff2a22 --- /dev/null +++ b/mod/src/main/resources/roomdata/a5b419e7-49ee-4d6d-bdce-470f508b315d.roomdata diff --git a/mod/src/main/resources/roomdata/a7321dea-d35f-44f9-a5b0-0bcaf414dc12.roomdata b/mod/src/main/resources/roomdata/a7321dea-d35f-44f9-a5b0-0bcaf414dc12.roomdata Binary files differnew file mode 100644 index 00000000..0ca60208 --- /dev/null +++ b/mod/src/main/resources/roomdata/a7321dea-d35f-44f9-a5b0-0bcaf414dc12.roomdata diff --git a/mod/src/main/resources/roomdata/a7f00d0f-bbf5-4d80-8eed-f3e28477879c.roomdata b/mod/src/main/resources/roomdata/a7f00d0f-bbf5-4d80-8eed-f3e28477879c.roomdata Binary files differnew file mode 100644 index 00000000..b8b70394 --- /dev/null +++ b/mod/src/main/resources/roomdata/a7f00d0f-bbf5-4d80-8eed-f3e28477879c.roomdata diff --git a/mod/src/main/resources/roomdata/ae5b48ac-43ec-4837-a34e-ac70cba71481.roomdata b/mod/src/main/resources/roomdata/ae5b48ac-43ec-4837-a34e-ac70cba71481.roomdata Binary files differnew file mode 100644 index 00000000..efd0c9f7 --- /dev/null +++ b/mod/src/main/resources/roomdata/ae5b48ac-43ec-4837-a34e-ac70cba71481.roomdata diff --git a/mod/src/main/resources/roomdata/b2dce4ed-2bda-4303-a4d7-3ebb914db318.roomdata b/mod/src/main/resources/roomdata/b2dce4ed-2bda-4303-a4d7-3ebb914db318.roomdata Binary files differnew file mode 100644 index 00000000..abc02a95 --- /dev/null +++ b/mod/src/main/resources/roomdata/b2dce4ed-2bda-4303-a4d7-3ebb914db318.roomdata diff --git a/mod/src/main/resources/roomdata/b2df250c-4af2-4201-963c-0ee1cb6bd3de.roomdata b/mod/src/main/resources/roomdata/b2df250c-4af2-4201-963c-0ee1cb6bd3de.roomdata Binary files differnew file mode 100644 index 00000000..d302623d --- /dev/null +++ b/mod/src/main/resources/roomdata/b2df250c-4af2-4201-963c-0ee1cb6bd3de.roomdata diff --git a/mod/src/main/resources/roomdata/b58cfdf5-a11d-4f28-b3c4-6576e5157374.roomdata b/mod/src/main/resources/roomdata/b58cfdf5-a11d-4f28-b3c4-6576e5157374.roomdata Binary files differnew file mode 100644 index 00000000..73413ff3 --- /dev/null +++ b/mod/src/main/resources/roomdata/b58cfdf5-a11d-4f28-b3c4-6576e5157374.roomdata diff --git a/mod/src/main/resources/roomdata/b9e8fcee-dce8-40fd-8f3a-d8cb5c3edd70.roomdata b/mod/src/main/resources/roomdata/b9e8fcee-dce8-40fd-8f3a-d8cb5c3edd70.roomdata Binary files differnew file mode 100644 index 00000000..3b9a56c7 --- /dev/null +++ b/mod/src/main/resources/roomdata/b9e8fcee-dce8-40fd-8f3a-d8cb5c3edd70.roomdata diff --git a/mod/src/main/resources/roomdata/c1b1eaf0-d6de-4d1f-944b-e1b3205ef7d0.roomdata b/mod/src/main/resources/roomdata/c1b1eaf0-d6de-4d1f-944b-e1b3205ef7d0.roomdata Binary files differnew file mode 100644 index 00000000..cd8e4532 --- /dev/null +++ b/mod/src/main/resources/roomdata/c1b1eaf0-d6de-4d1f-944b-e1b3205ef7d0.roomdata diff --git a/mod/src/main/resources/roomdata/c2ea0a41-d495-437f-86cc-235a71c49f22.roomdata b/mod/src/main/resources/roomdata/c2ea0a41-d495-437f-86cc-235a71c49f22.roomdata Binary files differnew file mode 100644 index 00000000..f796bc9f --- /dev/null +++ b/mod/src/main/resources/roomdata/c2ea0a41-d495-437f-86cc-235a71c49f22.roomdata diff --git a/mod/src/main/resources/roomdata/c6c65c08-893a-42f7-ad9e-cecc0f0bdeaf.roomdata b/mod/src/main/resources/roomdata/c6c65c08-893a-42f7-ad9e-cecc0f0bdeaf.roomdata Binary files differnew file mode 100644 index 00000000..c02feb39 --- /dev/null +++ b/mod/src/main/resources/roomdata/c6c65c08-893a-42f7-ad9e-cecc0f0bdeaf.roomdata diff --git a/mod/src/main/resources/roomdata/c6ebcdb2-4ea8-4387-b997-031bd56f7e3b.roomdata b/mod/src/main/resources/roomdata/c6ebcdb2-4ea8-4387-b997-031bd56f7e3b.roomdata Binary files differnew file mode 100644 index 00000000..8d9d1d5c --- /dev/null +++ b/mod/src/main/resources/roomdata/c6ebcdb2-4ea8-4387-b997-031bd56f7e3b.roomdata diff --git a/mod/src/main/resources/roomdata/c9078cd2-91d4-457d-ae30-3579293821da.roomdata b/mod/src/main/resources/roomdata/c9078cd2-91d4-457d-ae30-3579293821da.roomdata Binary files differnew file mode 100644 index 00000000..6884ea4f --- /dev/null +++ b/mod/src/main/resources/roomdata/c9078cd2-91d4-457d-ae30-3579293821da.roomdata diff --git a/mod/src/main/resources/roomdata/cab054ed-b9ea-4f54-9d23-9864a50789f0.roomdata b/mod/src/main/resources/roomdata/cab054ed-b9ea-4f54-9d23-9864a50789f0.roomdata Binary files differnew file mode 100644 index 00000000..7e477833 --- /dev/null +++ b/mod/src/main/resources/roomdata/cab054ed-b9ea-4f54-9d23-9864a50789f0.roomdata diff --git a/mod/src/main/resources/roomdata/cf44c95c-950e-49e0-aa4c-82c2b18d0acc.roomdata b/mod/src/main/resources/roomdata/cf44c95c-950e-49e0-aa4c-82c2b18d0acc.roomdata Binary files differnew file mode 100644 index 00000000..d28015f1 --- /dev/null +++ b/mod/src/main/resources/roomdata/cf44c95c-950e-49e0-aa4c-82c2b18d0acc.roomdata diff --git a/mod/src/main/resources/roomdata/cf6d49d3-4f1e-4ec9-836e-049573793ddd.roomdata b/mod/src/main/resources/roomdata/cf6d49d3-4f1e-4ec9-836e-049573793ddd.roomdata Binary files differnew file mode 100644 index 00000000..0297e9cc --- /dev/null +++ b/mod/src/main/resources/roomdata/cf6d49d3-4f1e-4ec9-836e-049573793ddd.roomdata diff --git a/mod/src/main/resources/roomdata/d3e61abf-4198-4520-a950-a03761a0eb6f.roomdata b/mod/src/main/resources/roomdata/d3e61abf-4198-4520-a950-a03761a0eb6f.roomdata Binary files differnew file mode 100644 index 00000000..06ef33ab --- /dev/null +++ b/mod/src/main/resources/roomdata/d3e61abf-4198-4520-a950-a03761a0eb6f.roomdata diff --git a/mod/src/main/resources/roomdata/d4a015ae-f123-4696-8fb6-719b5a21b623.roomdata b/mod/src/main/resources/roomdata/d4a015ae-f123-4696-8fb6-719b5a21b623.roomdata Binary files differnew file mode 100644 index 00000000..6aa61e43 --- /dev/null +++ b/mod/src/main/resources/roomdata/d4a015ae-f123-4696-8fb6-719b5a21b623.roomdata diff --git a/mod/src/main/resources/roomdata/d712ae5b-903a-4d80-96ee-8ee54b050ea5.roomdata b/mod/src/main/resources/roomdata/d712ae5b-903a-4d80-96ee-8ee54b050ea5.roomdata Binary files differnew file mode 100644 index 00000000..59ade145 --- /dev/null +++ b/mod/src/main/resources/roomdata/d712ae5b-903a-4d80-96ee-8ee54b050ea5.roomdata diff --git a/mod/src/main/resources/roomdata/datas.txt b/mod/src/main/resources/roomdata/datas.txt new file mode 100644 index 00000000..d5ac2d6b --- /dev/null +++ b/mod/src/main/resources/roomdata/datas.txt @@ -0,0 +1,118 @@ +roomdata/e773dc09-f989-4d8f-8aba-43dbb71e7b62.roomdata +roomdata/e22c44d7-4094-4230-89ba-efa438aa3615.roomdata +roomdata/12080b02-4ccc-49ce-9eaf-e7d8946f3984.roomdata +roomdata/44d9b135-d2ca-4350-969e-6e9c34af2fe6.roomdata +roomdata/b2dce4ed-2bda-4303-a4d7-3ebb914db318.roomdata +roomdata/7d975e04-15c8-40cb-8c12-d664edc1b0d7.roomdata +roomdata/2f7927cc-4ce0-4f02-a81a-88d5709248e8.roomdata +roomdata/990f6e4c-f7cf-4d27-ae91-11219b85861f.roomdata +roomdata/4f8be93c-f3e7-47ca-9e0d-87261f5fc386.roomdata +roomdata/1ae1d65c-2c72-4ed6-afab-84d0de759e1e.roomdata +roomdata/dc5d63b3-3dc4-41f1-a79c-973271ba71c2.roomdata +roomdata/01949106-2ddc-4601-9b4c-e934f5d373a6.roomdata +roomdata/4ed557b1-553c-4ecc-b3c1-88dd9da6d33c.roomdata +roomdata/b2df250c-4af2-4201-963c-0ee1cb6bd3de.roomdata +roomdata/c9078cd2-91d4-457d-ae30-3579293821da.roomdata +roomdata/1df3a849-2a5b-451d-8bd7-971eb608363c.roomdata +roomdata/e6d51aea-c715-4396-986d-2e09d31993e1.roomdata +roomdata/e66fe526-22c1-45bc-b4a8-d10549d7ee3f.roomdata +roomdata/9890fbac-d382-4525-ab88-fe1ebc118702.roomdata +roomdata/4ffce449-eab8-470b-bc8c-d30507248fc2.roomdata +roomdata/95c57abe-34d4-443c-baac-11d43cbc821f.roomdata +roomdata/e7e0bb38-8fc3-4d7c-a0c6-1fce55ac9082.roomdata +roomdata/23d6e1f6-efa3-476b-b452-ad5cf6a37be9.roomdata +roomdata/9b949f89-1542-4bcf-9bf3-063ec69bc5f4.roomdata +roomdata/0877607a-b8a2-433a-b893-f4de7c83378a.roomdata +roomdata/54aaf168-7039-48dc-99a3-8d1f02d79097.roomdata +roomdata/65d8264d-f47c-4306-b89f-46e28b117511.roomdata +roomdata/067df8a7-9d28-4fdd-a538-c6d38f126cd2.roomdata +roomdata/b58cfdf5-a11d-4f28-b3c4-6576e5157374.roomdata +roomdata/2b5cb4ef-00a3-4aae-baec-d2094a158d60.roomdata +roomdata/5b6968ce-4a5b-4a48-8cb3-423ff9a7788d.roomdata +roomdata/9a0e71bf-babd-421e-a785-442c13d5a8b2.roomdata +roomdata/ffd5411b-6ff4-4f60-b387-72f00510ec50.roomdata +roomdata/4538898f-8e79-4d53-aae6-08e4df6abb61.roomdata +roomdata/ae5b48ac-43ec-4837-a34e-ac70cba71481.roomdata +roomdata/9087fdc7-43e2-4736-b53b-33477ac65351.roomdata +roomdata/d4a015ae-f123-4696-8fb6-719b5a21b623.roomdata +roomdata/25956a46-7094-4a9e-b5d9-c9f8291ffef4.roomdata +roomdata/6367a338-dd48-4c30-9e03-7ff6b5c7a936.roomdata +roomdata/5000be9d-3081-4a5e-8563-dd826705663a.roomdata +roomdata/70a1451a-5430-40bd-b20b-13245aac910a.roomdata +roomdata/54008e69-d31e-4ed2-9ad0-870a3ad5ee1a.roomdata +roomdata/3acb9949-d252-4f16-9983-a1fcdc38a6cf.roomdata +roomdata/2ccc73b5-883f-4436-9b8f-1a32123b2cb9.roomdata +roomdata/41086d97-5e36-41a5-88ff-d3fb296791ce.roomdata +roomdata/cab054ed-b9ea-4f54-9d23-9864a50789f0.roomdata +roomdata/a5b419e7-49ee-4d6d-bdce-470f508b315d.roomdata +roomdata/40fb4b64-18d7-4301-b899-0da7b1d466c1.roomdata +roomdata/d3e61abf-4198-4520-a950-a03761a0eb6f.roomdata +roomdata/a7321dea-d35f-44f9-a5b0-0bcaf414dc12.roomdata +roomdata/2d9705f3-2e69-4035-905d-6b11d6ee270b.roomdata +roomdata/09c3072e-3099-4019-a577-7ddc17a9e29d.roomdata +roomdata/b9e8fcee-dce8-40fd-8f3a-d8cb5c3edd70.roomdata +roomdata/6b0dfb3e-c86c-41d1-8526-a172027dbb8d.roomdata +roomdata/83e1ab6b-ad44-469e-a6bf-71c6bebcab4b.roomdata +roomdata/9fa09d68-c483-4320-872e-9e07b049ee37.roomdata +roomdata/35fb741d-b0b1-471a-a5b6-8224f99a1133.roomdata +roomdata/42029218-9142-4286-b184-e17b3734886f.roomdata +roomdata/e83ed91c-4a35-4020-985a-d0306f17117a.roomdata +roomdata/3406a386-c56d-47de-a0ad-aa0ab74d2abb.roomdata +roomdata/cf6d49d3-4f1e-4ec9-836e-049573793ddd.roomdata +roomdata/296fd7ea-4ac5-46e5-beb9-5d27019e3796.roomdata +roomdata/91068a01-bd3e-402c-99aa-e148f9f04c41.roomdata +roomdata/e9f4f98a-0913-4542-a02d-4ed3cec6f09b.roomdata +roomdata/4e8087d2-0c64-4558-b4ff-4be94275a320.roomdata +roomdata/02b94b9a-8990-446a-993a-9b59de987b16.roomdata +roomdata/6dcddc04-c094-4b9b-8c05-b101e8f3dd27.roomdata +roomdata/15083814-fb7b-4791-b5d7-0810dd396b01.roomdata +roomdata/5aef2a82-42a3-495a-9e72-63a9b611e1cb.roomdata +roomdata/43c74bd0-77f6-4a2b-8edb-c227a72abf0f.roomdata +roomdata/ed57833a-01ca-4487-b516-6c3690c6221c.roomdata +roomdata/81cf3e0b-70c5-4803-9169-7e7864b096ce.roomdata +roomdata/8f317c52-6550-42dd-829b-2a477389fe89.roomdata +roomdata/7a594650-2a42-46e5-81a6-9b7d198e9c1c.roomdata +roomdata/250624ee-bb7a-4330-b698-a78f5e44ba99.roomdata +roomdata/00d66020-b34e-429d-9fd3-696bc15cfce2.roomdata +roomdata/a053f4fa-d6b2-4aef-ae3e-97c7eee0252e.roomdata +roomdata/fd34b23c-ce7c-4df6-9f5b-0aa23ba9a758.roomdata +roomdata/a7f00d0f-bbf5-4d80-8eed-f3e28477879c.roomdata +roomdata/9cd523a2-0c7f-4072-a374-9b99d59554ea.roomdata +roomdata/86a3b53b-6ede-43bd-8988-135001149d4b.roomdata +roomdata/ef097340-7c03-407d-b634-7bf7af551d01.roomdata +roomdata/6b7256ae-8673-4c2f-825f-6cd727801ea9.roomdata +roomdata/1e8d4327-7465-4bff-a8c7-505528273985.roomdata +roomdata/05ba6123-3468-4ec3-8e32-0553a8e5d3b2.roomdata +roomdata/a069f006-0728-4952-8d9f-1d318cee60d8.roomdata +roomdata/845aec22-bc9e-4d50-b8de-db67188232e9.roomdata +roomdata/e0608346-08a0-490b-a6d5-96786ebd5d96.roomdata +roomdata/8b4ec0bf-b783-4e66-b5fa-89493ac6efa1.roomdata +roomdata/31766264-1004-492f-9d65-cb5deaff82f0.roomdata +roomdata/8116e928-56f1-4e0b-933a-f86b841938c8.roomdata +roomdata/c1b1eaf0-d6de-4d1f-944b-e1b3205ef7d0.roomdata +roomdata/8c184746-6857-480a-958e-f22e09bb1295.roomdata +roomdata/9139cb1c-b6f3-4bac-92de-909b1eb73449.roomdata +roomdata/07ce87bb-a49a-412b-a8f7-c9dde9f884de.roomdata +roomdata/38affd31-fc6f-44cd-a41e-ae7d0589ba0d.roomdata +roomdata/d712ae5b-903a-4d80-96ee-8ee54b050ea5.roomdata +roomdata/a2c5d503-55e7-4e5c-8fc0-5d37f2ac19bf.roomdata +roomdata/4067578d-c259-4f89-8b88-a891b2decbbf.roomdata +roomdata/f8bee714-de5b-4007-a572-575fcd467c82.roomdata +roomdata/388e95fc-4775-4747-8473-5329fbb8e5cc.roomdata +roomdata/340c5665-e59b-42c1-bf84-8fc03d38981f.roomdata +roomdata/31749ba0-8b9d-4129-b3c9-ee78d9fdb9d7.roomdata +roomdata/8e6409d8-ea3f-4348-ae30-f8f1e15d05b9.roomdata +roomdata/7dd6596f-c647-4144-9eec-fb4690e12251.roomdata +roomdata/c6c65c08-893a-42f7-ad9e-cecc0f0bdeaf.roomdata +roomdata/a1c8fd24-c105-49b6-ba56-51dfbb7023cb.roomdata +roomdata/a0c57185-4e1a-4fdd-979d-6ed0957e78fb.roomdata +roomdata/cf44c95c-950e-49e0-aa4c-82c2b18d0acc.roomdata +roomdata/6fac9602-c596-458f-9750-9b331e2cb845.roomdata +roomdata/11982f7f-703e-4d98-9d27-4e07ba3fef71.roomdata +roomdata/dfe5d13c-3284-4ad3-aadf-9719f2c12a6e.roomdata +roomdata/63634341-8ef3-4197-aafa-17f5875dd307.roomdata +roomdata/c6ebcdb2-4ea8-4387-b997-031bd56f7e3b.roomdata +roomdata/c2ea0a41-d495-437f-86cc-235a71c49f22.roomdata +roomdata/9650cb39-5f22-45f4-86cd-5d197a4266e5.roomdata +roomdata/4b5f4983-0453-4402-821c-804f092d1ecd.roomdata +roomdata/34639497-d991-4137-83c4-db0a25542b71.roomdata diff --git a/mod/src/main/resources/roomdata/dc5d63b3-3dc4-41f1-a79c-973271ba71c2.roomdata b/mod/src/main/resources/roomdata/dc5d63b3-3dc4-41f1-a79c-973271ba71c2.roomdata Binary files differnew file mode 100644 index 00000000..fc956333 --- /dev/null +++ b/mod/src/main/resources/roomdata/dc5d63b3-3dc4-41f1-a79c-973271ba71c2.roomdata diff --git a/mod/src/main/resources/roomdata/dfe5d13c-3284-4ad3-aadf-9719f2c12a6e.roomdata b/mod/src/main/resources/roomdata/dfe5d13c-3284-4ad3-aadf-9719f2c12a6e.roomdata Binary files differnew file mode 100644 index 00000000..7c19cf8a --- /dev/null +++ b/mod/src/main/resources/roomdata/dfe5d13c-3284-4ad3-aadf-9719f2c12a6e.roomdata diff --git a/mod/src/main/resources/roomdata/e0608346-08a0-490b-a6d5-96786ebd5d96.roomdata b/mod/src/main/resources/roomdata/e0608346-08a0-490b-a6d5-96786ebd5d96.roomdata Binary files differnew file mode 100644 index 00000000..1a3b8512 --- /dev/null +++ b/mod/src/main/resources/roomdata/e0608346-08a0-490b-a6d5-96786ebd5d96.roomdata diff --git a/mod/src/main/resources/roomdata/e22c44d7-4094-4230-89ba-efa438aa3615.roomdata b/mod/src/main/resources/roomdata/e22c44d7-4094-4230-89ba-efa438aa3615.roomdata Binary files differnew file mode 100644 index 00000000..772a8ad1 --- /dev/null +++ b/mod/src/main/resources/roomdata/e22c44d7-4094-4230-89ba-efa438aa3615.roomdata diff --git a/mod/src/main/resources/roomdata/e66fe526-22c1-45bc-b4a8-d10549d7ee3f.roomdata b/mod/src/main/resources/roomdata/e66fe526-22c1-45bc-b4a8-d10549d7ee3f.roomdata Binary files differnew file mode 100644 index 00000000..cabbefdc --- /dev/null +++ b/mod/src/main/resources/roomdata/e66fe526-22c1-45bc-b4a8-d10549d7ee3f.roomdata diff --git a/mod/src/main/resources/roomdata/e6d51aea-c715-4396-986d-2e09d31993e1.roomdata b/mod/src/main/resources/roomdata/e6d51aea-c715-4396-986d-2e09d31993e1.roomdata Binary files differnew file mode 100644 index 00000000..ae711151 --- /dev/null +++ b/mod/src/main/resources/roomdata/e6d51aea-c715-4396-986d-2e09d31993e1.roomdata diff --git a/mod/src/main/resources/roomdata/e773dc09-f989-4d8f-8aba-43dbb71e7b62.roomdata b/mod/src/main/resources/roomdata/e773dc09-f989-4d8f-8aba-43dbb71e7b62.roomdata Binary files differnew file mode 100644 index 00000000..26bd5a84 --- /dev/null +++ b/mod/src/main/resources/roomdata/e773dc09-f989-4d8f-8aba-43dbb71e7b62.roomdata diff --git a/mod/src/main/resources/roomdata/e7e0bb38-8fc3-4d7c-a0c6-1fce55ac9082.roomdata b/mod/src/main/resources/roomdata/e7e0bb38-8fc3-4d7c-a0c6-1fce55ac9082.roomdata Binary files differnew file mode 100644 index 00000000..9924525b --- /dev/null +++ b/mod/src/main/resources/roomdata/e7e0bb38-8fc3-4d7c-a0c6-1fce55ac9082.roomdata diff --git a/mod/src/main/resources/roomdata/e83ed91c-4a35-4020-985a-d0306f17117a.roomdata b/mod/src/main/resources/roomdata/e83ed91c-4a35-4020-985a-d0306f17117a.roomdata Binary files differnew file mode 100644 index 00000000..3526d708 --- /dev/null +++ b/mod/src/main/resources/roomdata/e83ed91c-4a35-4020-985a-d0306f17117a.roomdata diff --git a/mod/src/main/resources/roomdata/e9f4f98a-0913-4542-a02d-4ed3cec6f09b.roomdata b/mod/src/main/resources/roomdata/e9f4f98a-0913-4542-a02d-4ed3cec6f09b.roomdata Binary files differnew file mode 100644 index 00000000..e76f5c06 --- /dev/null +++ b/mod/src/main/resources/roomdata/e9f4f98a-0913-4542-a02d-4ed3cec6f09b.roomdata diff --git a/mod/src/main/resources/roomdata/ed57833a-01ca-4487-b516-6c3690c6221c.roomdata b/mod/src/main/resources/roomdata/ed57833a-01ca-4487-b516-6c3690c6221c.roomdata Binary files differnew file mode 100644 index 00000000..d787e6ab --- /dev/null +++ b/mod/src/main/resources/roomdata/ed57833a-01ca-4487-b516-6c3690c6221c.roomdata diff --git a/mod/src/main/resources/roomdata/ef097340-7c03-407d-b634-7bf7af551d01.roomdata b/mod/src/main/resources/roomdata/ef097340-7c03-407d-b634-7bf7af551d01.roomdata Binary files differnew file mode 100644 index 00000000..6c83ed95 --- /dev/null +++ b/mod/src/main/resources/roomdata/ef097340-7c03-407d-b634-7bf7af551d01.roomdata diff --git a/mod/src/main/resources/roomdata/f8bee714-de5b-4007-a572-575fcd467c82.roomdata b/mod/src/main/resources/roomdata/f8bee714-de5b-4007-a572-575fcd467c82.roomdata Binary files differnew file mode 100644 index 00000000..6953bc24 --- /dev/null +++ b/mod/src/main/resources/roomdata/f8bee714-de5b-4007-a572-575fcd467c82.roomdata diff --git a/mod/src/main/resources/roomdata/fd34b23c-ce7c-4df6-9f5b-0aa23ba9a758.roomdata b/mod/src/main/resources/roomdata/fd34b23c-ce7c-4df6-9f5b-0aa23ba9a758.roomdata Binary files differnew file mode 100644 index 00000000..47ba61c5 --- /dev/null +++ b/mod/src/main/resources/roomdata/fd34b23c-ce7c-4df6-9f5b-0aa23ba9a758.roomdata diff --git a/mod/src/main/resources/roomdata/ffd5411b-6ff4-4f60-b387-72f00510ec50.roomdata b/mod/src/main/resources/roomdata/ffd5411b-6ff4-4f60-b387-72f00510ec50.roomdata Binary files differnew file mode 100644 index 00000000..8cfe9d73 --- /dev/null +++ b/mod/src/main/resources/roomdata/ffd5411b-6ff4-4f60-b387-72f00510ec50.roomdata diff --git a/mod/src/main/resources/timescore/10.csv b/mod/src/main/resources/timescore/10.csv new file mode 100644 index 00000000..6d576cd8 --- /dev/null +++ b/mod/src/main/resources/timescore/10.csv @@ -0,0 +1,144 @@ +0,100 +611000,100 +612000,99 +623000,99 +624000,98 +635000,98 +636000,97 +647000,97 +648000,96 +659000,96 +660000,95 +671000,95 +672000,94 +683000,94 +684000,93 +695000,93 +696000,92 +707000,92 +708000,91 +719000,91 +720000,90 +743000,90 +744000,89 +767000,89 +768000,88 +791000,88 +792000,87 +815000,87 +816000,86 +839000,86 +840000,85 +863000,85 +864000,84 +887000,84 +888000,83 +911000,83 +912000,82 +935000,82 +936000,81 +959000,81 +960000,80 +989000,80 +990000,79 +1019000,79 +1020000,78 +1049000,78 +1050000,77 +1079000,77 +1080000,76 +1109000,76 +1110000,75 +1139000,75 +1140000,74 +1169000,74 +1170000,73 +1199000,73 +1200000,72 +1229000,72 +1230000,71 +1259000,71 +1261000,70 +1293000,70 +1296000,69 +1331000,69 +1332000,68 +1367000,68 +1368000,67 +1401000,67 +1404000,66 +1439000,66 +1440000,65 +1474000,65 +1477000,64 +1511000,64 +1512000,63 +1547000,63 +1549000,62 +1582000,62 +1585000,61 +1618000,61 +1620000,60 +1660000,60 +1663000,59 +1704000,59 +1706000,58 +1744000,58 +1753000,57 +1788000,57 +1791000,56 +1829000,56 +1833000,55 +1870000,55 +1874000,54 +1903000,54 +1915000,53 +1955000,53 +1963000,52 +1982000,52 +2003000,51 +2037000,51 +2044000,50 +2066000,50 +2105000,49 +2121000,49 +2138000,48 +2152000,48 +2172000,47 +2199000,47 +2219000,46 +2239000,46 +2260000,45 +2277000,45 +2312000,44 +2333000,44 +2367000,43 +2373000,43 +2408000,42 +2408000,42 +2485000,40 +2495000,40 +2519000,39 +2521000,39 +2565000,38 +2565000,38 +2599000,37 +2599000,37 +2707000,35 +2707000,35 +2763000,33 +2763000,33 +2800000,32 +2830000,32 +2932000,29 +2958000,29 +3022000,27 +3022000,27 +3128000,25 +3129000,25 +3225000,22 +3256000,22 +3373000,19 +3373000,19 +3435000,17 +3435000,17 diff --git a/mod/src/main/resources/timescore/12.csv b/mod/src/main/resources/timescore/12.csv new file mode 100644 index 00000000..242d3ba6 --- /dev/null +++ b/mod/src/main/resources/timescore/12.csv @@ -0,0 +1,96 @@ +134000,100 +734000,100 +735000,99 +748000,99 +749000,98 +763000,98 +764000,97 +777000,97 +778000,96 +791000,96 +792000,95 +806000,95 +807000,94 +820000,94 +821000,93 +835000,93 +836000,92 +849000,92 +850000,91 +863000,91 +864000,90 +892000,90 +893000,89 +921000,89 +922000,88 +950000,88 +951000,87 +979000,87 +981000,86 +1007000,86 +1008000,85 +1036000,85 +1037000,84 +1065000,84 +1066000,83 +1094000,83 +1095000,82 +1121000,82 +1124000,81 +1151000,81 +1152000,80 +1187000,80 +1188000,79 +1223000,79 +1224000,78 +1256000,78 +1263000,77 +1292000,77 +1296000,76 +1330000,76 +1333000,75 +1364000,75 +1373000,74 +1391000,74 +1412000,73 +1438000,73 +1440000,72 +1475000,72 +1494000,71 +1507000,71 +1524000,70 +1546000,70 +1561000,69 +1595000,69 +1610000,68 +1638000,68 +1654000,67 +1654000,67 +1685000,66 +1726000,66 +1755000,65 +1770000,65 +1794000,64 +1806000,64 +1830000,63 +1845000,63 +1900000,62 +1900000,62 +1919000,61 +1919000,61 +1954000,60 +1954000,60 +2033000,59 +2042000,59 +2051000,58 +2051000,58 +2164000,56 +2168000,56 +2240000,55 +2240000,55 +2382000,52 +2382000,52 +2466000,50 +2466000,50 +2554000,48 +2554000,48 diff --git a/mod/src/main/resources/timescore/8.csv b/mod/src/main/resources/timescore/8.csv new file mode 100644 index 00000000..2634befd --- /dev/null +++ b/mod/src/main/resources/timescore/8.csv @@ -0,0 +1,88 @@ +139000,100 +489000,100 +490000,99 +499000,99 +500000,98 +508000,98 +509000,97 +518000,97 +519000,96 +527000,96 +528000,95 +537000,95 +539000,94 +546000,94 +548000,93 +556000,93 +559000,92 +566000,92 +567000,91 +575000,91 +576000,90 +594000,90 +596000,89 +612000,89 +616000,88 +633000,88 +636000,87 +651000,87 +653000,86 +670000,86 +673000,85 +691000,85 +692000,84 +708000,84 +712000,83 +729000,83 +730000,82 +742000,82 +750000,81 +764000,81 +769000,80 +788000,80 +794000,79 +815000,79 +819000,78 +836000,78 +844000,77 +861000,77 +866000,76 +886000,76 +888000,75 +901000,75 +914000,74 +928000,74 +936000,73 +957000,73 +967000,72 +983000,72 +1000000,71 +1000000,71 +1008000,70 +1021000,70 +1082000,68 +1084000,68 +1109000,67 +1121000,67 +1161000,65 +1161000,65 +1185000,64 +1194000,64 +1219000,63 +1229000,63 +1251000,62 +1251000,62 +1282000,61 +1282000,61 +1308000,60 +1308000,60 +1336000,59 +1336000,59 +1382000,58 +1387000,58 +1425000,57 +1425000,57 +1441000,56 +1445000,56 +1488000,55 +1488000,55 |