aboutsummaryrefslogtreecommitdiff
path: root/loader/src/main/java/kr
diff options
context:
space:
mode:
authorsyeyoung <cyoung06@naver.com>2023-02-04 18:39:59 +0900
committersyeyoung <cyoung06@naver.com>2023-02-04 18:39:59 +0900
commit7bc262cbfa173fb0a31fb58d6f1d55fa0cac3b08 (patch)
treecc92677cb4d86ace73da4afd29dfa3a336341620 /loader/src/main/java/kr
parent29d6ebc4433318fb72d4587d7a67b522fd744619 (diff)
downloadSkyblock-Dungeons-Guide-7bc262cbfa173fb0a31fb58d6f1d55fa0cac3b08.tar.gz
Skyblock-Dungeons-Guide-7bc262cbfa173fb0a31fb58d6f1d55fa0cac3b08.tar.bz2
Skyblock-Dungeons-Guide-7bc262cbfa173fb0a31fb58d6f1d55fa0cac3b08.zip
- cursors
- move guiv2 to launcher - add force letsencrypt support (without modifying keystore directly) ^ very cool Signed-off-by: syeyoung <cyoung06@naver.com>
Diffstat (limited to 'loader/src/main/java/kr')
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/LetsEncrypt.java78
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/auth/DgAuthUtil.java11
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/branch/UpdateRetrieverUtil.java17
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/Context.java1
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/DomElement.java2
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/GuiScreenAdapter.java4
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/RootDom.java2
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/Button.java2
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/CircularRect.java4
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/CompatLayer.java169
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/RoundRect.java4
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/TextField.java2
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/ToggleButton.java2
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/image/ImageTexture.java5
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/richtext/styles/ITextStyle.java14
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/xml/DomElementRegistry.java1
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/shader/ShaderManager.java128
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/shader/ShaderProgram.java126
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/CursorReader.java95
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/EnumCursor.java79
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/Foundation.java33
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/GLCursors.java232
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/User32.java67
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/X11.java37
24 files changed, 916 insertions, 199 deletions
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/LetsEncrypt.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/LetsEncrypt.java
new file mode 100644
index 00000000..7d75d571
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/LetsEncrypt.java
@@ -0,0 +1,78 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2023 cyoung06 (syeyoung)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.launcher;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Objects;
+
+// Smh minecraft default launcher letsencrypt
+public class LetsEncrypt {
+ public static SSLSocketFactory LETS_ENCRYPT;
+
+ static {
+ try {
+ LETS_ENCRYPT = letsEncryptAddedFactory();
+ } catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException |
+ KeyManagementException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static SSLSocketFactory letsEncryptAddedFactory() throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, KeyManagementException {
+ String keyStoreLocation = System.getProperty( "javax.net.ssl.trustStore", Paths.get(System.getProperty("java.home"), "lib", "security", "cacerts").toString());
+ String keyStorePassword = System.getProperty( "javax.net.ssl.trustStorePassword", "" ); // You might ask, "THE DEFAULT PASSWORD IS changeit". But in fact, just loading keystore does not require a key!! https://stackoverflow.com/a/42363257
+ String keyStoreType = System.getProperty("javax.net.ssl.trustStoreType", KeyStore.getDefaultType());
+
+ char[] charArr = keyStorePassword.isEmpty() ? null : keyStorePassword.toCharArray();
+
+ KeyStore keyStore = KeyStore.getInstance(keyStoreType);
+ try (InputStream readStream = Files.newInputStream(Paths.get(keyStoreLocation))) {
+ keyStore.load(readStream, charArr);
+ }
+
+ if (keyStore.getCertificate("ISRGRootX1") == null) {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ try (InputStream caInput = LetsEncrypt.class.getResourceAsStream("/isrgrootx1.der")) {
+ Certificate crt = cf.generateCertificate(caInput);
+ keyStore.setCertificateEntry("ISRGRootX1", crt);
+ }
+ }
+
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ tmf.init(keyStore);
+
+ SSLContext context = SSLContext.getInstance( "TLS" );
+ context.init( null, tmf.getTrustManagers(), null);
+ return context.getSocketFactory();
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/auth/DgAuthUtil.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/auth/DgAuthUtil.java
index 2c59dd2c..d1abadca 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/auth/DgAuthUtil.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/auth/DgAuthUtil.java
@@ -21,6 +21,7 @@ package kr.syeyoung.dungeonsguide.launcher.auth;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.minecraft.MinecraftSessionService;
+import kr.syeyoung.dungeonsguide.launcher.LetsEncrypt;
import kr.syeyoung.dungeonsguide.launcher.Main;
import kr.syeyoung.dungeonsguide.launcher.auth.token.AuthToken;
import kr.syeyoung.dungeonsguide.launcher.auth.token.DGAuthToken;
@@ -37,6 +38,7 @@ import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
+import javax.net.ssl.HttpsURLConnection;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
@@ -97,7 +99,8 @@ public class DgAuthUtil {
public static String requestAuth() throws IOException {
GameProfile profile = Minecraft.getMinecraft().getSession().getProfile();
- HttpURLConnection connection = (HttpURLConnection) new URL(Main.DOMAIN + "/auth/v2/requestAuth").openConnection();
+ HttpsURLConnection connection = (HttpsURLConnection) new URL(Main.DOMAIN + "/auth/v2/requestAuth").openConnection();
+ connection.setSSLSocketFactory(LetsEncrypt.LETS_ENCRYPT);
connection.setRequestProperty("User-Agent", "DungeonsGuide/4.0");
connection.setRequestProperty("Content-Type", "application/json");
connection.setConnectTimeout(1000);
@@ -147,7 +150,8 @@ public class DgAuthUtil {
* @throws AuthServerException when auth server throws error
*/
public static AuthToken verifyAuth(String tempToken, byte[] encSecret) throws IOException {
- HttpURLConnection urlConnection = (HttpURLConnection) new URL(Main.DOMAIN + "/auth/v2/authenticate").openConnection();
+ HttpsURLConnection urlConnection = (HttpsURLConnection) new URL(Main.DOMAIN + "/auth/v2/authenticate").openConnection();
+ urlConnection.setSSLSocketFactory(LetsEncrypt.LETS_ENCRYPT);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("User-Agent", "DungeonsGuide/4.0");
urlConnection.setRequestProperty("Content-Type", "application/json");
@@ -173,7 +177,8 @@ public class DgAuthUtil {
}
public static AuthToken acceptNewPrivacyPolicy(String tempToken, long version) throws IOException {
- HttpURLConnection urlConnection = (HttpURLConnection) new URL(Main.DOMAIN + "/auth/v2/acceptPrivacyPolicy").openConnection();
+ HttpsURLConnection urlConnection = (HttpsURLConnection) new URL(Main.DOMAIN + "/auth/v2/acceptPrivacyPolicy").openConnection();
+ urlConnection.setSSLSocketFactory(LetsEncrypt.LETS_ENCRYPT);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("User-Agent", "DungeonsGuide/4.0");
urlConnection.setRequestProperty("Content-Type", "application/json");
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/branch/UpdateRetrieverUtil.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/branch/UpdateRetrieverUtil.java
index 0414129c..ef282f1e 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/branch/UpdateRetrieverUtil.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/branch/UpdateRetrieverUtil.java
@@ -18,6 +18,7 @@
package kr.syeyoung.dungeonsguide.launcher.branch;
+import kr.syeyoung.dungeonsguide.launcher.LetsEncrypt;
import kr.syeyoung.dungeonsguide.launcher.Main;
import kr.syeyoung.dungeonsguide.launcher.auth.AuthManager;
import kr.syeyoung.dungeonsguide.launcher.exceptions.AssetNotFoundException;
@@ -29,6 +30,7 @@ import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONObject;
+import javax.net.ssl.HttpsURLConnection;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
@@ -47,7 +49,8 @@ public class UpdateRetrieverUtil {
}
public static List<UpdateBranch> getUpdateBranches() throws IOException {
- HttpURLConnection connection = (HttpURLConnection) new URL(Main.DOMAIN + "/updates/").openConnection();
+ HttpsURLConnection connection = (HttpsURLConnection) new URL(Main.DOMAIN + "/updates/").openConnection();
+ connection.setSSLSocketFactory(LetsEncrypt.LETS_ENCRYPT);
connection.setRequestProperty("User-Agent", "DungeonsGuide/4.0");
connection.setRequestProperty("Authorization", "Bearer "+ AuthManager.getInstance().getWorkingTokenOrThrow());
connection.setRequestMethod("GET");
@@ -78,7 +81,8 @@ public class UpdateRetrieverUtil {
}
public static List<Update> getLatestUpdates(long branchId, int page) throws IOException {
- HttpURLConnection connection = (HttpURLConnection) new URL(Main.DOMAIN + "/updates/"+branchId+"/?page="+page).openConnection();
+ HttpsURLConnection connection = (HttpsURLConnection) new URL(Main.DOMAIN + "/updates/"+branchId+"/?page="+page).openConnection();
+ connection.setSSLSocketFactory(LetsEncrypt.LETS_ENCRYPT);
connection.setRequestProperty("User-Agent", "DungeonsGuide/4.0");
connection.setRequestMethod("GET");
connection.setConnectTimeout(1000);
@@ -120,7 +124,8 @@ public class UpdateRetrieverUtil {
}
public static Update getUpdate(long branchId, long updateId) throws IOException {
- HttpURLConnection connection = (HttpURLConnection) new URL(Main.DOMAIN + "/updates/"+branchId+"/"+updateId).openConnection();
+ HttpsURLConnection connection = (HttpsURLConnection) new URL(Main.DOMAIN + "/updates/"+branchId+"/"+updateId).openConnection();
+ connection.setSSLSocketFactory(LetsEncrypt.LETS_ENCRYPT);
connection.setRequestProperty("User-Agent", "DungeonsGuide/4.0");
connection.setRequestProperty("Authorization", "Bearer "+ AuthManager.getInstance().getWorkingTokenOrThrow());
connection.setRequestMethod("GET");
@@ -162,7 +167,8 @@ public class UpdateRetrieverUtil {
try {
- HttpURLConnection connection = (HttpURLConnection) new URL(Main.DOMAIN + "/updates/" + update.getBranchId() + "/" + update.getId() + "/" + asset.getAssetId()).openConnection();
+ HttpsURLConnection connection = (HttpsURLConnection) new URL(Main.DOMAIN + "/updates/" + update.getBranchId() + "/" + update.getId() + "/" + asset.getAssetId()).openConnection();
+ connection.setSSLSocketFactory(LetsEncrypt.LETS_ENCRYPT);
connection.setRequestProperty("User-Agent", "DungeonsGuide/4.0");
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "Bearer " + AuthManager.getInstance().getWorkingTokenOrThrow());
@@ -181,7 +187,8 @@ public class UpdateRetrieverUtil {
throw new ResponseParsingException(payload, e);
}
try {
- connection = (HttpURLConnection) new URL(url).openConnection();
+ connection = (HttpsURLConnection) new URL(url).openConnection();
+ connection.setSSLSocketFactory(LetsEncrypt.LETS_ENCRYPT);
connection.setRequestProperty("User-Agent", "DungeonsGuide/4.0");
connection.setConnectTimeout(1000);
connection.setReadTimeout(5000);
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/Context.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/Context.java
index b59c2c2b..a5ac459b 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/Context.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/Context.java
@@ -21,7 +21,6 @@ package kr.syeyoung.dungeonsguide.launcher.guiv2;
import java.util.HashMap;
import java.util.Map;
-// TODO: get rid of this and change it with tree walking.
public class Context {
public Map<String, Object> CONTEXT = new HashMap<>();
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/DomElement.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/DomElement.java
index 9487b21c..90f17921 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/DomElement.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/DomElement.java
@@ -27,7 +27,7 @@ import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.Rect;
import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.Size;
import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.DrawNothingRenderer;
import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.Renderer;
-import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import kr.syeyoung.dungeonsguide.launcher.util.cursor.EnumCursor;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/GuiScreenAdapter.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/GuiScreenAdapter.java
index 03c60397..d4d46834 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/GuiScreenAdapter.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/GuiScreenAdapter.java
@@ -22,8 +22,8 @@ import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.ConstraintBox;
import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.Rect;
import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.Size;
import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.RenderingContext;
-import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
-import kr.syeyoung.dungeonsguide.mod.utils.cursor.GLCursors;
+import kr.syeyoung.dungeonsguide.launcher.util.cursor.EnumCursor;
+import kr.syeyoung.dungeonsguide.launcher.util.cursor.GLCursors;
import lombok.Getter;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/RootDom.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/RootDom.java
index d7c732f3..a759f982 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/RootDom.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/RootDom.java
@@ -20,7 +20,7 @@ package kr.syeyoung.dungeonsguide.launcher.guiv2;
import kr.syeyoung.dungeonsguide.launcher.guiv2.layouter.SingleChildPassingLayouter;
import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.SingleChildRenderer;
-import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import kr.syeyoung.dungeonsguide.launcher.util.cursor.EnumCursor;
import lombok.Getter;
import lombok.Setter;
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/Button.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/Button.java
index 73b0e21d..77ceb167 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/Button.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/Button.java
@@ -29,7 +29,7 @@ import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.AnnotatedWidget;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Bind;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Export;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Passthrough;
-import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import kr.syeyoung.dungeonsguide.launcher.util.cursor.EnumCursor;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.ResourceLocation;
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/CircularRect.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/CircularRect.java
index 18738d42..24f74963 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/CircularRect.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/CircularRect.java
@@ -27,8 +27,8 @@ import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.RenderingContext;
import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.SingleChildRenderer;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.AnnotatedExportOnlyWidget;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Export;
-import kr.syeyoung.dungeonsguide.mod.shader.ShaderManager;
-import kr.syeyoung.dungeonsguide.mod.shader.ShaderProgram;
+import kr.syeyoung.dungeonsguide.launcher.shader.ShaderManager;
+import kr.syeyoung.dungeonsguide.launcher.shader.ShaderProgram;
import net.minecraft.client.Minecraft;
import org.lwjgl.opengl.GL20;
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/CompatLayer.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/CompatLayer.java
deleted file mode 100644
index 69ad5652..00000000
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/CompatLayer.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
- * Copyright (C) 2023 cyoung06 (syeyoung)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package kr.syeyoung.dungeonsguide.launcher.guiv2.elements;
-
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MTooltip;
-import kr.syeyoung.dungeonsguide.launcher.guiv2.DomElement;
-import kr.syeyoung.dungeonsguide.launcher.guiv2.Widget;
-import kr.syeyoung.dungeonsguide.launcher.guiv2.elements.popups.AbsLocationPopup;
-import kr.syeyoung.dungeonsguide.launcher.guiv2.elements.popups.PopupMgr;
-import kr.syeyoung.dungeonsguide.launcher.guiv2.layouter.Layouter;
-import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.ConstraintBox;
-import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.Size;
-import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.Renderer;
-import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.RenderingContext;
-import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
-import net.minecraft.client.Minecraft;
-import org.lwjgl.opengl.GL11;
-
-import java.awt.*;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public class CompatLayer extends Widget implements Layouter, Renderer {
- private MPanel panel;
- private Rectangle force;
-
- public CompatLayer(MPanel panel) {
- this(panel, null);
- }
-
- List<AbsLocationPopup> tooltips = new ArrayList<>();
- public CompatLayer(MPanel panel, Rectangle force) {
- this.panel = panel;
- this.force = force;
- panel.setParent(new MPanel() {
- @Override
- public void setCursor(EnumCursor enumCursor) {
- getDomElement().setCursor(enumCursor);
- }
-
- @Override
- public int getTooltipsOpen() {
- return 0;
- }
-
- @Override
- public void openTooltip(MTooltip mPanel) {
- Rectangle bounds = mPanel.getBounds();
- AbsLocationPopup absLocationPopup = new AbsLocationPopup(bounds.getX(), bounds.getY(), new CompatLayer(mPanel, bounds), true);
- PopupMgr.getPopupMgr(getDomElement()).openPopup(absLocationPopup, (a) -> {tooltips.remove(absLocationPopup);});
- tooltips.add(absLocationPopup);
- }
- });
- }
-
- @Override
- public void onUnmount() {
- super.onUnmount();
- tooltips.forEach(PopupMgr.getPopupMgr(getDomElement())::closePopup);
- }
-
- @Override
- public List<Widget> build(DomElement buildContext) {
- return Collections.emptyList();
- }
-
-
-
- @Override
- public boolean mouseClicked(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int mouseButton) {
- getDomElement().obtainFocus();
- double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
- return panel.mouseClicked0( (int)(absMouseX / scale), (int)(absMouseY / scale), (int)relMouseX,(int) relMouseY, mouseButton);
- }
-
- @Override
- public void mouseClickMove(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int clickedMouseButton, long timeSinceLastClick) {
- double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
- panel.mouseClickMove0( (int)(absMouseX / scale), (int)(absMouseY / scale), (int)relMouseX, (int)relMouseY, clickedMouseButton, timeSinceLastClick);
- }
-
- @Override
- public void mouseReleased(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int state) {
- double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
- panel.mouseReleased0( (int)(absMouseX / scale), (int)(absMouseY / scale), (int)relMouseX,(int) relMouseY, state);
- }
-
- @Override
- public boolean mouseMoved(int absMouseX, int absMouseY, double relMouseX0, double relMouseY0) {
- double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
- panel.mouseMoved0( (int)(absMouseX / scale), (int)(absMouseY / scale), (int)relMouseX0, (int)relMouseY0);
- return true;
- }
-
- @Override
- public boolean mouseScrolled(int absMouseX, int absMouseY, double relMouseX0, double relMouseY0, int scrollAmount) {
- double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
- panel.mouseScrolled0( (int)(absMouseX / scale), (int)(absMouseY / scale), (int)relMouseX0, (int)relMouseY0, scrollAmount);
- return true;
- }
-
- @Override
- public void keyPressed(char typedChar, int keyCode) {
- panel.keyPressed0(typedChar, keyCode);
- }
-
- @Override
- public void keyReleased(char typedChar, int keyCode) {
- panel.keyReleased0(typedChar, keyCode);
- }
-
- @Override
- public void keyHeld(char typedChar, int keyCode) {
- panel.keyHeld0(typedChar, keyCode);
- }
-
- @Override
- public Size layout(DomElement buildContext, ConstraintBox constraintBox) {
- Dimension dimension = force == null ? panel.getPreferredSize() : force.getSize();
- panel.resize((int) constraintBox.getMaxWidth(), (int) constraintBox.getMaxHeight());
- if (panel.getBounds().getWidth() != 0) dimension = panel.getSize();
-
- panel.setBounds(new Rectangle(0,0, (int) dimension.getWidth(), (int) dimension.getHeight()));
- return new Size(dimension.getWidth(), dimension.getHeight());
- }
-
- @Override
- public void doRender(int absMouseX, int absMouseY, double relMouseX, double relMouseY, float partialTicks, RenderingContext context, DomElement buildContext) {
- double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
-
- Rectangle originalRect = context.currentClip();
- Rectangle rectangle = originalRect == null ? null : originalRect.getBounds();
- boolean isNotNull = rectangle != null;
- if (rectangle == null) rectangle = new Rectangle(0,0,Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight);
-
- rectangle.y = Minecraft.getMinecraft().displayHeight - rectangle.y - rectangle.height;
- rectangle.width /= scale;
- rectangle.height /= scale;
- rectangle.x /= scale;
- rectangle.y /= scale;
-
-// System.out.println(rectangle);
- panel.render0(scale, new Point((int) (getDomElement().getAbsBounds().getX() / scale), (int) (getDomElement().getAbsBounds().getY() /scale)),
- rectangle, (int)(absMouseX / scale), (int)(absMouseY / scale), (int)relMouseX, (int)relMouseY, partialTicks);
-
- if (isNotNull) {
- GL11.glEnable(GL11.GL_SCISSOR_TEST);
- GL11.glScissor(originalRect.x, originalRect.y, originalRect.width, originalRect.height);
- }
- }
-}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/RoundRect.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/RoundRect.java
index 217972e5..051bbe4b 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/RoundRect.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/RoundRect.java
@@ -26,8 +26,8 @@ import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.RenderingContext;
import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.SingleChildRenderer;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.AnnotatedExportOnlyWidget;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Export;
-import kr.syeyoung.dungeonsguide.mod.shader.ShaderManager;
-import kr.syeyoung.dungeonsguide.mod.shader.ShaderProgram;
+import kr.syeyoung.dungeonsguide.launcher.shader.ShaderManager;
+import kr.syeyoung.dungeonsguide.launcher.shader.ShaderProgram;
import net.minecraft.client.Minecraft;
import org.lwjgl.opengl.GL20;
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/TextField.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/TextField.java
index 5cc977c8..dff6da58 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/TextField.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/TextField.java
@@ -29,7 +29,7 @@ import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.Renderer;
import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.RenderingContext;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.AnnotatedExportOnlyWidget;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Export;
-import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import kr.syeyoung.dungeonsguide.launcher.util.cursor.EnumCursor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/ToggleButton.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/ToggleButton.java
index 8b4e7256..78814199 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/ToggleButton.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/ToggleButton.java
@@ -29,7 +29,7 @@ import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.AnnotatedWidget;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Bind;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Export;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Passthrough;
-import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import kr.syeyoung.dungeonsguide.launcher.util.cursor.EnumCursor;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.ResourceLocation;
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/image/ImageTexture.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/image/ImageTexture.java
index e5ceec72..79ca20c9 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/image/ImageTexture.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/image/ImageTexture.java
@@ -19,7 +19,6 @@
package kr.syeyoung.dungeonsguide.launcher.guiv2.elements.image;
-import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
import lombok.Data;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
@@ -148,9 +147,9 @@ public class ImageTexture {
tessellator.draw();
}
- public static final ExecutorService executorService = Executors.newFixedThreadPool(3, DungeonsGuide.THREAD_FACTORY);
+ public static final ExecutorService executorService = Executors.newFixedThreadPool(3);
public static final Map<String, ImageTexture> imageMap = new HashMap<>();
- public static final Logger logger = LogManager.getLogger("DG-ImageLoader");
+ public static final Logger logger = LogManager.getLogger("DG-Loader-ImageLoader");
public static void loadImage(String url, Consumer<ImageTexture> callback) {
if (imageMap.containsKey(url)) {
callback.accept(imageMap.get(url));
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/richtext/styles/ITextStyle.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/richtext/styles/ITextStyle.java
index 48cee96f..4d62522f 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/richtext/styles/ITextStyle.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/richtext/styles/ITextStyle.java
@@ -36,17 +36,17 @@ public interface ITextStyle {
Boolean isShadow();
- kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getBackgroundShader();
+ kr.syeyoung.dungeonsguide.launcher.guiv2.elements.richtext.shaders.Shader getBackgroundShader();
- kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getTextShader();
+ kr.syeyoung.dungeonsguide.launcher.guiv2.elements.richtext.shaders.Shader getTextShader();
- kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getStrikeThroughShader();
+ kr.syeyoung.dungeonsguide.launcher.guiv2.elements.richtext.shaders.Shader getStrikeThroughShader();
- kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getUnderlineShader();
+ kr.syeyoung.dungeonsguide.launcher.guiv2.elements.richtext.shaders.Shader getUnderlineShader();
- kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getOutlineShader();
+ kr.syeyoung.dungeonsguide.launcher.guiv2.elements.richtext.shaders.Shader getOutlineShader();
- kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getShadowShader();
+ kr.syeyoung.dungeonsguide.launcher.guiv2.elements.richtext.shaders.Shader getShadowShader();
- kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.fonts.FontRenderer getFontRenderer();
+ kr.syeyoung.dungeonsguide.launcher.guiv2.elements.richtext.fonts.FontRenderer getFontRenderer();
}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/xml/DomElementRegistry.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/xml/DomElementRegistry.java
index 8ca03ab5..4a4eff58 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/xml/DomElementRegistry.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/xml/DomElementRegistry.java
@@ -26,6 +26,7 @@ import kr.syeyoung.dungeonsguide.launcher.guiv2.view.TestView;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.data.Parser;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.data.ParserException;
import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.data.W3CBackedParser;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.elements.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IResource;
import net.minecraft.util.ResourceLocation;
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/shader/ShaderManager.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/shader/ShaderManager.java
new file mode 100644
index 00000000..f0a7a79a
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/shader/ShaderManager.java
@@ -0,0 +1,128 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2023 cyoung06 (syeyoung)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.launcher.shader;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.ResourceLocation;
+import org.apache.commons.io.IOUtils;
+import org.lwjgl.opengl.GL20;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class ShaderManager {
+ private static final Map<String, ShaderProgram> shaders = new HashMap<>();
+
+ public static void onResourceReload() {
+ for (ShaderProgram value : shaders.values()) {
+ value.close();
+ }
+ Set<String> keySet = new HashSet<>(shaders.keySet());
+ shaders.clear();
+ for (String s : keySet) {
+ loadShader(s);
+ }
+ }
+
+ public static void unload() {
+ for (ShaderProgram value : shaders.values()) {
+ value.close();
+ }
+ }
+
+ public static ShaderProgram getShader(String str) {
+ if (shaders.containsKey(str)) return shaders.get(str);
+ return loadShader(str);
+ }
+
+ private static ShaderProgram loadShader(String name) {
+ int vertex = -1;
+ String sourceVert = getShaderSource(name+".vert");
+ String sourceFrag = getShaderSource(name + ".frag");
+ if (sourceVert == null && sourceFrag == null) {
+ shaders.put(name, null); // shortcut
+ return null;
+ }
+ if (sourceVert != null) {
+ vertex = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
+ System.out.println(sourceVert);
+ GL20.glShaderSource(vertex, sourceVert);
+ GL20.glCompileShader(vertex);
+
+ if (GL20.glGetShaderi(vertex, 35713) == 0) {
+ System.err.println(GL20.glGetShaderInfoLog(vertex, 100));
+ GL20.glDeleteShader(vertex);
+ return null;
+ }
+ }
+
+ int fragment = -1;
+ if (sourceFrag != null) {
+ fragment = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
+ System.out.println(sourceFrag);
+ GL20.glShaderSource(fragment, sourceFrag);
+ GL20.glCompileShader(fragment);
+
+ if (GL20.glGetShaderi(fragment, 35713) == 0) {
+ System.err.println(GL20.glGetShaderInfoLog(fragment, 100));
+ if (vertex != -1)
+ GL20.glDeleteShader(vertex);
+ GL20.glDeleteShader(fragment);
+ return null;
+ }
+ }
+
+
+ int program = GL20.glCreateProgram();
+ if (vertex != -1) GL20.glAttachShader(program, vertex);
+ if (fragment != -1) GL20.glAttachShader(program, fragment);
+
+ GL20.glLinkProgram(program);
+
+ if (vertex != -1) GL20.glDeleteShader(vertex);
+ if (fragment != -1) GL20.glDeleteShader(fragment);
+
+ if (GL20.glGetProgrami(program, 35714) == 0) {
+ System.err.println(GL20.glGetProgramInfoLog(program, 100));
+ return null;
+ }
+ GL20.glValidateProgram(program);
+ if (GL20.glGetProgrami(program, 35715) == 0) {
+ System.err.println(GL20.glGetProgramInfoLog(program, 100));
+ return null;
+ }
+ ShaderProgram shaderProgram = new ShaderProgram(name, program);
+ shaders.put(name, shaderProgram);
+ return shaderProgram;
+ }
+
+ private static String getShaderSource(String name) {
+ ResourceLocation location = new ResourceLocation(
+ "dungeons_guide_loader:"+name
+ );
+ try (InputStream is = Minecraft.getMinecraft().getResourceManager().getResource(location).getInputStream()) {
+ return IOUtils.toString(is);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/shader/ShaderProgram.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/shader/ShaderProgram.java
new file mode 100644
index 00000000..10b6ade1
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/shader/ShaderProgram.java
@@ -0,0 +1,126 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2023 cyoung06 (syeyoung)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.launcher.shader;
+
+import lombok.AllArgsConstructor;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.util.vector.Matrix2f;
+
+import javax.vecmath.Matrix3f;
+import javax.vecmath.Matrix4f;
+import java.nio.FloatBuffer;
+
+@AllArgsConstructor
+public class ShaderProgram {
+ private String shaderName;
+ private int shaderId;
+
+ private void ensureInitialized() {
+ if (shaderId == -1) throw new IllegalStateException("ShaderProgram not initialized");
+ }
+
+ public void useShader() {
+ ensureInitialized();
+ GL20.glUseProgram(shaderId);
+ }
+
+ public int getUniformLocation(String name) {
+ ensureInitialized();
+ return GL20.glGetUniformLocation(shaderId, name);
+ }
+
+ public void uploadUniform(String name, int val) {
+ GL20.glUniform1i(getUniformLocation(name), val);
+ }
+
+ public void uploadUniform(String name, int v1, int v2) {
+ GL20.glUniform2i(getUniformLocation(name), v1, v2);
+ }
+
+ public void uploadUniform(String name, int v1, int v2, int v3) {
+ GL20.glUniform3i(getUniformLocation(name), v1, v2, v3);
+ }
+
+ public void uploadUniform(String name, int v1, int v2, int v3, int v4) {
+ GL20.glUniform4i(getUniformLocation(name), v1, v2, v3, v4);
+ }
+
+ public void uploadUniform(String name, float val) {
+ GL20.glUniform1f(getUniformLocation(name), val);
+ }
+
+ public void uploadUniform(String name, float v1, float v2) {
+ GL20.glUniform2f(getUniformLocation(name), v1, v2);
+ }
+
+ public void uploadUniform(String name, float v1, float v2, float v3) {
+ GL20.glUniform3f(getUniformLocation(name), v1, v2, v3);
+ }
+
+ public void uploadUniform(String name, float v1, float v2, float v3, float v4) {
+ GL20.glUniform4f(getUniformLocation(name), v1, v2, v3, v4);
+ }
+
+ public void uploadUniform(String name, Matrix2f matrix2f) {
+ FloatBuffer floatBuffer = FloatBuffer.allocate(4);
+ matrix2f.store(floatBuffer);
+ GL20.glUniformMatrix2(getUniformLocation(name), false, floatBuffer);
+ }
+
+ public void uploadUniform(String name, Matrix3f matrix3f) {
+ FloatBuffer floatBuffer = FloatBuffer.allocate(9);
+ floatBuffer.put(matrix3f.m00);
+ floatBuffer.put(matrix3f.m01);
+ floatBuffer.put(matrix3f.m02);
+ floatBuffer.put(matrix3f.m10);
+ floatBuffer.put(matrix3f.m11);
+ floatBuffer.put(matrix3f.m12);
+ floatBuffer.put(matrix3f.m20);
+ floatBuffer.put(matrix3f.m21);
+ floatBuffer.put(matrix3f.m22);
+ GL20.glUniformMatrix3(getUniformLocation(name), false, floatBuffer);
+ }
+
+ public void uploadUniform(String name, Matrix4f matrix4f) {
+ FloatBuffer floatBuffer = FloatBuffer.allocate(16);
+ floatBuffer.put(matrix4f.m00);
+ floatBuffer.put(matrix4f.m01);
+ floatBuffer.put(matrix4f.m02);
+ floatBuffer.put(matrix4f.m03);
+ floatBuffer.put(matrix4f.m10);
+ floatBuffer.put(matrix4f.m11);
+ floatBuffer.put(matrix4f.m12);
+ floatBuffer.put(matrix4f.m13);
+ floatBuffer.put(matrix4f.m20);
+ floatBuffer.put(matrix4f.m21);
+ floatBuffer.put(matrix4f.m22);
+ floatBuffer.put(matrix4f.m23);
+ floatBuffer.put(matrix4f.m30);
+ floatBuffer.put(matrix4f.m31);
+ floatBuffer.put(matrix4f.m32);
+ floatBuffer.put(matrix4f.m33);
+ GL20.glUniformMatrix4(getUniformLocation(name), false, floatBuffer);
+ }
+
+ public void close() {
+ if (shaderId == -1) return;
+ GL20.glDeleteProgram(shaderId);
+ shaderId = -1;
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/CursorReader.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/CursorReader.java
new file mode 100644
index 00000000..34c40964
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/CursorReader.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.launcher.util.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.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CursorReader {
+ public static List<CursorData> readFromInputStream(InputStream inputStream) throws IOException {
+ 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/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/EnumCursor.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/EnumCursor.java
new file mode 100644
index 00000000..8bea67b9
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/EnumCursor.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.launcher.util.cursor;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+
+@AllArgsConstructor
+@Getter
+public enum EnumCursor {
+ /** there are these hidden cursors for macos
+ * [NSCursor _windowResizeEastCursor]
+ * [NSCursor _windowResizeWestCursor]
+ * [NSCursor _windowResizeEastWestCursor]
+ * [NSCursor _windowResizeNorthCursor]
+ * [NSCursor _windowResizeSouthCursor]
+ * [NSCursor _windowResizeNorthSouthCursor]
+ * [NSCursor _windowResizeNorthEastCursor]
+ * [NSCursor _windowResizeNorthWestCursor]
+ * [NSCursor _windowResizeSouthEastCursor]
+ * [NSCursor _windowResizeSouthWestCursor]
+ * [NSCursor _windowResizeNorthEastSouthWestCursor]
+ * [NSCursor _windowResizeNorthWestSouthEastCursor]
+ * https://stackoverflow.com/questions/10733228/native-osx-lion-resize-cursor-for-custom-nswindow-or-nsview
+ */
+ 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"),
+
+ MOVE_BAR_LEFT(32644, 70,"resizeLeftCursor", "resizeLeftCursor.cur"),
+ MOVE_BAR_RIGHT(32644, 96,"resizeRightCursor", "resizeRightCursor.cur"),
+ MOVE_BAR_LEFT_RIGHT(32644, 108, "resizeLeftRightCursor", "resizeLeftRightCursor.cur"),
+ MOVE_BAR_UP(32645,138,"resizeUpCursor", "resizeUpCursor.cur"),
+ MOVE_BAR_DOWN(32645,16,"resizeDownCursor", "resizeDownCursor.cur"),
+ MOVE_BAR_UP_DOWN(32645,116,"resizeUpDownCursor", "resizeUpDownCursor.cur"),
+
+ RESIZE_LEFT(32644, 70,"_windowResizeWestCursor", "resizeLeftCursor.cur"),
+ RESIZE_RIGHT(32644, 96,"_windowResizeEastCursor", "resizeRightCursor.cur"),
+ RESIZE_LEFT_RIGHT(32644, 108, "_windowResizeEastWestCursor", "resizeLeftRightCursor.cur"),
+ RESIZE_UP(32645,138,"_windowResizeNorthCursor", "resizeUpCursor.cur"),
+ RESIZE_DOWN(32645,16,"_windowResizeSouthCursor", "resizeDownCursor.cur"),
+ RESIZE_UP_DOWN(32645,116,"_windowResizeNorthSouthCursor", "resizeUpDownCursor.cur"),
+
+
+ RESIZE_TL(32642, 134, "_windowResizeNorthWestCursor", "resizeNW.cur"),
+ RESIZE_DR(32642, 14, "_windowResizeSouthEastCursor", "resizeSE.cur"),
+ RESIZE_TLDR(32642, 14, "_windowResizeNorthWestSouthEastCursor", "resizeNWSE.cur"),
+ RESIZE_TR(32643, 136, "_windowResizeNorthEastCursor", "resizeNE.cur"),
+ RESIZE_DL(32643, 12, "_windowResizeSouthWestCursor", "resizeSW.cur"),
+ RESIZE_TRDL(32643, 12, "_windowResizeNorthEastSouthWestCursor", "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/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/Foundation.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/Foundation.java
new file mode 100644
index 00000000..2a44e4ad
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/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.launcher.util.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/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/GLCursors.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/GLCursors.java
new file mode 100644
index 00000000..b0e10351
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/GLCursors.java
@@ -0,0 +1,232 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.launcher.util.cursor;
+
+
+import com.google.common.base.Throwables;
+import com.sun.jna.Native;
+import com.sun.jna.Pointer;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.ResourceLocation;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+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;
+
+
+@SuppressWarnings("unsafe")
+public class GLCursors {
+
+ static Logger logger = LogManager.getLogger("DG-GlCursors");
+
+ @SuppressWarnings("unsafe")
+ static boolean verbose = false;
+
+ 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) {
+ if(verbose) logger.error("Error occurred 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("dungeons_guide_loader: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);
+ if(verbose) logger.info(cursorData);
+ bufferedImage = cursorData.getBufferedImage();
+ hotspotX = cursorData.getXHotSpot();
+ hotspotY = cursorData.getYHotSpot();
+ } catch (Throwable t) {
+ if(verbose) logger.error("loading cursor failed with message, {}", String.valueOf(Throwables.getRootCause(t)));
+ }
+
+
+ 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(0xFFFFFFFF);
+ } 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) {
+ if(verbose) logger.error("Error occurred 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);
+ if(verbose) logger.info(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(" ");
+ }
+ if(verbose) logger.info(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(Native.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 < Native.POINTER_SIZE; i++) {
+ byte value = (byte) ((ptrVal >> i * 8) & 0xFF);
+ handle.put(value);
+ }
+ } else {
+ for (int i = Native.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/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/User32.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/User32.java
new file mode 100644
index 00000000..4dffc35f
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/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.launcher.util.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/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/X11.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/cursor/X11.java
new file mode 100644
index 00000000..a9a96fef
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/util/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.launcher.util.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() {
+ }
+ }
+
+}