Skip to content

Commit ea1a342

Browse files
committed
re-add skyclient end gui
1 parent e4e7d56 commit ea1a342

File tree

10 files changed

+410
-12
lines changed

10 files changed

+410
-12
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
mod_name = OneConfig
22
mod_id = oneconfig
33
mod_major_version = 0.2.2-alpha
4-
mod_minor_version = 225
4+
mod_minor_version = 226
55

66
polyfrost.defaults.loom=3
77

src/main/java/cc/polyfrost/oneconfig/utils/Notifications.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import cc.polyfrost.oneconfig.renderer.NanoVGHelper;
4343
import cc.polyfrost.oneconfig.renderer.asset.Icon;
4444
import cc.polyfrost.oneconfig.utils.gui.GuiUtils;
45-
import org.apache.commons.lang3.StringUtils;
4645
import org.jetbrains.annotations.Nullable;
4746

4847
import java.io.File;
@@ -254,8 +253,6 @@ else if (desiredPosition != entry.getValue().getEnd())
254253

255254
private Animation dummyAnimation;
256255
private static final Icon DEFAULT_ICON = new Icon(SVGs.ONECONFIG_HEAD_DARK);
257-
private static final File crashPatchSkyClientFile = new File("./OneConfig/CrashPatch/SKYCLIENT");
258-
private static final File oldCrashPatchSkyClientFile = new File("./W-OVERFLOW/CrashPatch/SKYCLIENT");
259256

260257
@Subscribe
261258
private void onTickEvent(TickEvent event) {
@@ -264,8 +261,7 @@ private void onTickEvent(TickEvent event) {
264261
Preferences.firstLaunch = false;
265262
Preferences.getInstance().save();
266263
dummyAnimation = new EaseInOutQuad(4000, 0, 1, false);
267-
boolean isSkyClient = isSkyClient();
268-
String message = isSkyClient ? "SkyClient now includes OneConfig, the next-gen config library for Minecraft. You can now simply press '" + Preferences.oneConfigKeyBind.getDisplay() + "' to configure all your mods!" : "Press '" + Preferences.oneConfigKeyBind.getDisplay() + "' to open OneConfig, the next-gen config library for Minecraft.";
264+
String message = "Press '" + Preferences.oneConfigKeyBind.getDisplay() + "' to open OneConfig, the next-gen config library for Minecraft.";
269265
send("Welcome to OneConfig!", message, DEFAULT_ICON, -1f, () -> {
270266
if (Platform.getGuiPlatform().getCurrentScreen() instanceof OneConfigGui || Preferences.oneconfigOpened) {
271267
Preferences.oneconfigOpened = true;
@@ -278,10 +274,4 @@ private void onTickEvent(TickEvent event) {
278274
}
279275
}
280276
}
281-
282-
private boolean isSkyClient() {
283-
if (crashPatchSkyClientFile.exists()) return true;
284-
if (oldCrashPatchSkyClientFile.exists()) return true;
285-
return Platform.getLoaderPlatform().getLoadedMods().stream().anyMatch(mod -> mod != null && StringUtils.contains(mod.id, "skyclient") || StringUtils.contains(mod.id, "skyblockclient") || StringUtils.equals(mod.id, "scc"));
286-
}
287277
}

versions/src/main/java/cc/polyfrost/oneconfig/internal/OneConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import cc.polyfrost.oneconfig.internal.config.core.ConfigCore;
3737
import cc.polyfrost.oneconfig.internal.config.core.KeyBindHandler;
3838
import cc.polyfrost.oneconfig.internal.gui.BlurHandler;
39+
import cc.polyfrost.oneconfig.internal.hacks.ByeSkyClientHack;
3940
import cc.polyfrost.oneconfig.internal.hud.HudCore;
4041
import cc.polyfrost.oneconfig.libs.universal.ChatColor;
4142
import cc.polyfrost.oneconfig.libs.universal.UChat;
@@ -172,6 +173,7 @@ public void init() {
172173
HypixelUtils.INSTANCE.initialize();
173174
EventManager.INSTANCE.register(KeyBindHandler.INSTANCE);
174175
ConfigCore.sortMods();
176+
ByeSkyClientHack.INSTANCE.initialize();
175177

176178
initialized = true;
177179
}
Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
/*
2+
* This file is part of OneConfig.
3+
* OneConfig - Next Generation Config Library for Minecraft: Java Edition
4+
* Copyright (C) 2021~2023 Polyfrost.
5+
* <https://polyfrost.cc> <https://github.com/Polyfrost/>
6+
*
7+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8+
*
9+
* OneConfig is licensed under the terms of version 3 of the GNU Lesser
10+
* General Public License as published by the Free Software Foundation, AND
11+
* under the Additional Terms Applicable to OneConfig, as published by Polyfrost,
12+
* either version 1.0 of the Additional Terms, or (at your option) any later
13+
* version.
14+
*
15+
* This program is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18+
* Lesser General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU Lesser General Public
21+
* License. If not, see <https://www.gnu.org/licenses/>. You should
22+
* have also received a copy of the Additional Terms Applicable
23+
* to OneConfig, as published by Polyfrost. If not, see
24+
* <https://polyfrost.cc/legal/oneconfig/additional-terms>
25+
*/
26+
27+
package cc.polyfrost.oneconfig.internal.hacks;
28+
29+
import cc.polyfrost.oneconfig.internal.assets.Colors;
30+
import cc.polyfrost.oneconfig.libs.universal.UResolution;
31+
import cc.polyfrost.oneconfig.platform.Platform;
32+
import cc.polyfrost.oneconfig.renderer.NanoVGHelper;
33+
import cc.polyfrost.oneconfig.renderer.font.Fonts;
34+
import cc.polyfrost.oneconfig.utils.NetworkUtils;
35+
import org.apache.commons.lang3.StringUtils;
36+
import org.lwjgl.input.Mouse;
37+
38+
import java.awt.*;
39+
import java.io.File;
40+
import java.time.LocalDate;
41+
import java.time.temporal.ChronoUnit;
42+
43+
public class ByeSkyClientHack {
44+
45+
private static final File crashPatchSkyClientFile = new File("./OneConfig/CrashPatch/SKYCLIENT");
46+
private static final File oldCrashPatchSkyClientFile = new File("./W-OVERFLOW/CrashPatch/SKYCLIENT");
47+
public static final ByeSkyClientHack INSTANCE = new ByeSkyClientHack();
48+
49+
private static final String[] CAROUSEL_IMAGES = {
50+
"/oneclient1.jpg",
51+
"/oneclient2.jpg",
52+
"/oneclient3.jpg"
53+
};
54+
55+
private static final float[] CAROUSEL_RATIOS = {
56+
644f / 1050f,
57+
803f / 1281f,
58+
803f / 1281f
59+
};
60+
61+
private static final String DOWNLOAD_URL = "https://polyfrost.org/projects/oneclient";
62+
private static final String DISCORD_URL = "https://discord.gg/polyfrost";
63+
private static final String FAQ_URL = "https://polyfrost.org/blog/oneclient-announcement";
64+
65+
private boolean dismissed = false;
66+
private boolean wasMouseDown = false;
67+
68+
private int currentImage = 0;
69+
private long lastImageSwitch = 0;
70+
private static final long AUTO_SWITCH_MS = 5000;
71+
72+
private float scrollY = 0;
73+
private float targetScrollY = 0;
74+
private long firstShownTime = 0;
75+
76+
public void initialize() {
77+
}
78+
79+
public void overwriteGui(int mouseX, int mouseY, float partialTicks) {
80+
NanoVGHelper nvg = NanoVGHelper.INSTANCE;
81+
82+
float scaleFactor = (float) UResolution.getScaleFactor();
83+
float mx = mouseX * scaleFactor;
84+
float my = mouseY * scaleFactor;
85+
86+
int dWheel = Mouse.getDWheel();
87+
if (dWheel != 0) {
88+
targetScrollY += dWheel > 0 ? 40 : -40;
89+
if (targetScrollY > 0) targetScrollY = 0;
90+
}
91+
scrollY += (targetScrollY - scrollY) * 0.3f;
92+
if (scrollY > 0) scrollY = 0;
93+
94+
boolean isMouseDown = Mouse.isButtonDown(0);
95+
boolean clicked = !isMouseDown && wasMouseDown;
96+
wasMouseDown = isMouseDown;
97+
98+
nvg.setupAndDraw(vg -> {
99+
float windowW = UResolution.getWindowWidth();
100+
float windowH = UResolution.getWindowHeight();
101+
102+
if (firstShownTime == 0) firstShownTime = System.currentTimeMillis();
103+
104+
nvg.drawRect(vg, 0, 0, windowW, windowH, Colors.GRAY_900);
105+
106+
float contentW = Math.min(700, windowW - 60);
107+
float contentX = (windowW - contentW) / 2f;
108+
109+
LocalDate endOfSupportDate = LocalDate.of(2026, 2, 24);
110+
LocalDate today = LocalDate.now();
111+
long daysDiff = ChronoUnit.DAYS.between(endOfSupportDate, today);
112+
String daysText;
113+
if (daysDiff > 0) {
114+
daysText = daysDiff + " days ago";
115+
} else if (daysDiff == 0) {
116+
daysText = "today";
117+
} else {
118+
daysText = "in " + Math.abs(daysDiff) + " days";
119+
}
120+
121+
float yBase = 40;
122+
float y = yBase + scrollY;
123+
124+
float titleSize = 32;
125+
nvg.drawCenteredText(vg, "SkyClient is moving to OneClient",
126+
windowW / 2f, y + titleSize / 2f, Colors.WHITE, titleSize, Fonts.BOLD);
127+
y += titleSize + 20;
128+
129+
nvg.drawRect(vg, contentX, y, contentW, 1, Colors.GRAY_600);
130+
y += 16;
131+
132+
float descSize = 14;
133+
String desc1 = "Starting from February 24th, 2026 (" + daysText
134+
+ "), Hypixel SkyBlock will be removing 1.8 support. "
135+
+ "As a result, we are ending support for SkyClient.";
136+
float[] desc1Bounds = nvg.getWrappedStringBounds(vg, desc1, contentW, descSize, 1.4f, Fonts.REGULAR);
137+
float desc1Height = desc1Bounds[3] - desc1Bounds[1];
138+
nvg.drawWrappedString(vg, desc1, contentX, y + descSize / 2f,
139+
contentW, Colors.WHITE_80, descSize, 1.4f, Fonts.REGULAR);
140+
y += desc1Height + 20;
141+
142+
float desc2Size = 16;
143+
String desc2 = "We have been developing OneClient, the 1.21 version of SkyClient "
144+
+ "with its own launcher and updated to the latest mods. We recommend trying it "
145+
+ "as it is the closest thing now to SkyClient and made by the same team.";
146+
float[] desc2Bounds = nvg.getWrappedStringBounds(vg, desc2, contentW, desc2Size, 1.4f, Fonts.MEDIUM);
147+
float desc2Height = desc2Bounds[3] - desc2Bounds[1];
148+
nvg.drawWrappedString(vg, desc2, contentX, y + desc2Size / 2f,
149+
contentW, Colors.WHITE, desc2Size, 1.4f, Fonts.MEDIUM);
150+
y += desc2Height + 28;
151+
152+
float imgW = contentW;
153+
float imgH = imgW * CAROUSEL_RATIOS[currentImage];
154+
155+
long now = System.currentTimeMillis();
156+
if (lastImageSwitch == 0) lastImageSwitch = now;
157+
if (now - lastImageSwitch > AUTO_SWITCH_MS) {
158+
currentImage = (currentImage + 1) % CAROUSEL_IMAGES.length;
159+
lastImageSwitch = now;
160+
}
161+
162+
nvg.drawDropShadow(vg, contentX, y, imgW, imgH, 12, 4, 12);
163+
nvg.drawRoundImage(vg, CAROUSEL_IMAGES[currentImage],
164+
contentX, y, imgW, imgH, 12, ByeSkyClientHack.class);
165+
166+
float arrowAreaW = 50;
167+
float arrowCenterY = y + imgH / 2f;
168+
boolean leftHover = mx >= contentX && mx <= contentX + arrowAreaW && my >= y && my <= y + imgH;
169+
int leftArrowColor = leftHover
170+
? new Color(255, 255, 255, 180).getRGB()
171+
: new Color(255, 255, 255, 80).getRGB();
172+
nvg.drawCenteredText(vg, "<", contentX + arrowAreaW / 2f,
173+
arrowCenterY, leftArrowColor, 28, Fonts.BOLD);
174+
if (clicked && leftHover) {
175+
currentImage = (currentImage - 1 + CAROUSEL_IMAGES.length) % CAROUSEL_IMAGES.length;
176+
lastImageSwitch = System.currentTimeMillis();
177+
}
178+
179+
float rightArrowX = contentX + imgW - arrowAreaW;
180+
boolean rightHover = mx >= rightArrowX && mx <= contentX + imgW && my >= y && my <= y + imgH;
181+
int rightArrowColor = rightHover
182+
? new Color(255, 255, 255, 180).getRGB()
183+
: new Color(255, 255, 255, 80).getRGB();
184+
nvg.drawCenteredText(vg, ">", rightArrowX + arrowAreaW / 2f,
185+
arrowCenterY, rightArrowColor, 28, Fonts.BOLD);
186+
if (clicked && rightHover) {
187+
currentImage = (currentImage + 1) % CAROUSEL_IMAGES.length;
188+
lastImageSwitch = System.currentTimeMillis();
189+
}
190+
191+
float dotAreaY = y + imgH + 12;
192+
float dotRadius = 4;
193+
float dotSpacing = 16;
194+
float dotsWidth = CAROUSEL_IMAGES.length * dotRadius * 2
195+
+ (CAROUSEL_IMAGES.length - 1) * (dotSpacing - dotRadius * 2);
196+
float dotStartX = (windowW - dotsWidth) / 2f;
197+
for (int i = 0; i < CAROUSEL_IMAGES.length; i++) {
198+
float dotCenterX = dotStartX + i * dotSpacing + dotRadius;
199+
float dotCenterY = dotAreaY + dotRadius;
200+
int dotColor = (i == currentImage) ? Colors.PRIMARY_500 : Colors.GRAY_500;
201+
nvg.drawCircle(vg, dotCenterX, dotCenterY, dotRadius, dotColor);
202+
203+
if (clicked && mx >= dotCenterX - dotRadius - 4 && mx <= dotCenterX + dotRadius + 4
204+
&& my >= dotCenterY - dotRadius - 4 && my <= dotCenterY + dotRadius + 4) {
205+
currentImage = i;
206+
lastImageSwitch = System.currentTimeMillis();
207+
}
208+
}
209+
210+
y = dotAreaY + dotRadius * 2 + 24;
211+
212+
float btnH = 40;
213+
float btnSpacing = 12;
214+
float btnRadius = 8;
215+
float btnFontSize = 14;
216+
217+
boolean downloadHovered = mx >= contentX && mx <= contentX + contentW
218+
&& my >= y && my <= y + btnH;
219+
nvg.drawRoundedRect(vg, contentX, y, contentW, btnH,
220+
downloadHovered ? Colors.PRIMARY_500 : Colors.PRIMARY_600, btnRadius);
221+
nvg.drawCenteredText(vg, "Download OneClient",
222+
contentX + contentW / 2f, y + btnH / 2f, Colors.WHITE, btnFontSize, Fonts.SEMIBOLD);
223+
if (clicked && downloadHovered) {
224+
NetworkUtils.browseLink(DOWNLOAD_URL);
225+
}
226+
y += btnH + btnSpacing;
227+
228+
float halfW = (contentW - btnSpacing) / 2f;
229+
float discordBtnX = contentX;
230+
float faqBtnX = contentX + halfW + btnSpacing;
231+
232+
boolean discordHovered = mx >= discordBtnX && mx <= discordBtnX + halfW
233+
&& my >= y && my <= y + btnH;
234+
nvg.drawRoundedRect(vg, discordBtnX, y, halfW, btnH,
235+
discordHovered ? Colors.GRAY_300 : Colors.GRAY_500, btnRadius);
236+
nvg.drawCenteredText(vg, "Discord",
237+
discordBtnX + halfW / 2f, y + btnH / 2f, Colors.WHITE, btnFontSize, Fonts.SEMIBOLD);
238+
if (clicked && discordHovered) {
239+
NetworkUtils.browseLink(DISCORD_URL);
240+
}
241+
242+
boolean faqHovered = mx >= faqBtnX && mx <= faqBtnX + halfW
243+
&& my >= y && my <= y + btnH;
244+
nvg.drawRoundedRect(vg, faqBtnX, y, halfW, btnH,
245+
faqHovered ? Colors.GRAY_300 : Colors.GRAY_500, btnRadius);
246+
nvg.drawCenteredText(vg, "FAQ",
247+
faqBtnX + halfW / 2f, y + btnH / 2f, Colors.WHITE, btnFontSize, Fonts.SEMIBOLD);
248+
if (clicked && faqHovered) {
249+
NetworkUtils.browseLink(FAQ_URL);
250+
}
251+
y += btnH + btnSpacing;
252+
253+
boolean continueHovered = mx >= contentX && mx <= contentX + contentW
254+
&& my >= y && my <= y + btnH;
255+
nvg.drawRoundedRect(vg, contentX, y, contentW, btnH,
256+
continueHovered ? Colors.GRAY_300 : Colors.GRAY_600, btnRadius);
257+
nvg.drawCenteredText(vg, "Continue using SkyClient",
258+
contentX + contentW / 2f, y + btnH / 2f, Colors.WHITE_60, btnFontSize, Fonts.MEDIUM);
259+
if (clicked && continueHovered) {
260+
dismissed = true;
261+
}
262+
263+
float totalContentHeight = (y - scrollY) + btnH + 40;
264+
float maxScroll = totalContentHeight - windowH;
265+
if (maxScroll > 0) {
266+
if (targetScrollY < -maxScroll) targetScrollY = -maxScroll;
267+
268+
float trackW = 4;
269+
float trackX = windowW - 12;
270+
nvg.drawRoundedRect(vg, trackX, 0, trackW, windowH, Colors.GRAY_700, 2);
271+
272+
float viewRatio = windowH / totalContentHeight;
273+
float thumbH = Math.max(30, windowH * viewRatio);
274+
float scrollFraction = -scrollY / maxScroll;
275+
float thumbY = scrollFraction * (windowH - thumbH);
276+
nvg.drawRoundedRect(vg, trackX, thumbY, trackW, thumbH, Colors.GRAY_400, 2);
277+
278+
if (-scrollY < maxScroll) {
279+
nvg.drawGradientRect(vg, 0, windowH - 80, windowW, 80,
280+
Colors.GRAY_900 & 0x00FFFFFF, Colors.GRAY_900,
281+
NanoVGHelper.GradientDirection.DOWN);
282+
}
283+
284+
long elapsed = System.currentTimeMillis() - firstShownTime;
285+
long fadeDuration = 500;
286+
long holdDuration = 3000;
287+
if (elapsed < holdDuration + fadeDuration) {
288+
float hintAlpha;
289+
if (elapsed < holdDuration) {
290+
hintAlpha = 1f;
291+
} else {
292+
hintAlpha = 1f - (float)(elapsed - holdDuration) / fadeDuration;
293+
}
294+
int hintColor = new Color(1f, 1f, 1f, hintAlpha * 0.7f).getRGB();
295+
float hintSize = 13;
296+
String hintText = "Scroll down \u2193";
297+
float hintX = windowW / 2f;
298+
float hintY = windowH - 18;
299+
nvg.drawCenteredText(vg, hintText, hintX, hintY, hintColor, hintSize, Fonts.MEDIUM);
300+
}
301+
} else {
302+
targetScrollY = 0;
303+
}
304+
});
305+
}
306+
307+
public boolean isSkyClient() {
308+
if (dismissed) return false;
309+
if (crashPatchSkyClientFile.exists()) return true;
310+
if (oldCrashPatchSkyClientFile.exists()) return true;
311+
return Platform.getLoaderPlatform().getLoadedMods().stream().anyMatch(
312+
mod -> mod != null && (StringUtils.contains(mod.id, "skyclient")
313+
|| StringUtils.contains(mod.id, "skyblockclient")
314+
|| StringUtils.equals(mod.id, "scc")));
315+
}
316+
}

0 commit comments

Comments
 (0)