From 2b3eca128f0575626e7770ebc706d8af59bffccf Mon Sep 17 00:00:00 2001 From: tttsaurus Date: Tue, 7 Jan 2025 15:51:54 -0500 Subject: [PATCH] Progression in spotify support --- .../com/tttsaurus/ingameinfo/IgiConfig.java | 27 ++++++ .../spotify/SpotifyAccessUtils.java | 4 +- .../spotify/SpotifyOAuthUtils.java | 21 ++++- .../api/appcommunication/spotify/Token.java | 8 +- .../common/api/gui/IgiGuiContainer.java | 7 ++ .../ingameinfo/common/api/mvvm/view/View.java | 4 +- .../common/api/mvvm/viewmodel/ViewModel.java | 4 + .../common/api/render/RenderUtils.java | 8 ++ .../spotify/SpotifyCommandHandler.java | 27 ++---- .../spotify/SpotifyViewModel.java | 93 ++++++++++++++++++- .../common/impl/gui/IgiGuiLifeCycle.java | 2 +- .../common/impl/gui/control/UrlImage.java | 2 +- .../common/impl/igievent/EventCenter.java | 3 + .../impl/igievent/SpotifyOverlayEvent.java | 13 +++ .../registry/MvvmRegisterEventHandler.java | 3 + .../render/renderer/UrlImageRenderer.java | 39 +++++++- .../plugin/crt/impl/CrtViewModel.java | 6 ++ .../ingameinfo/proxy/CommonProxy.java | 7 ++ 18 files changed, 241 insertions(+), 37 deletions(-) create mode 100644 src/main/java/com/tttsaurus/ingameinfo/IgiConfig.java create mode 100644 src/main/java/com/tttsaurus/ingameinfo/common/impl/igievent/SpotifyOverlayEvent.java diff --git a/src/main/java/com/tttsaurus/ingameinfo/IgiConfig.java b/src/main/java/com/tttsaurus/ingameinfo/IgiConfig.java new file mode 100644 index 0000000..c0b2fbb --- /dev/null +++ b/src/main/java/com/tttsaurus/ingameinfo/IgiConfig.java @@ -0,0 +1,27 @@ +package com.tttsaurus.ingameinfo; + +import net.minecraftforge.common.config.Configuration; + +public class IgiConfig +{ + public static String SPOTIFY_CLIENT_ID; + public static String SPOTIFY_CLIENT_SECRET; + + public static Configuration CONFIG; + + public static void loadConfig() + { + try + { + CONFIG.load(); + + SPOTIFY_CLIENT_ID = CONFIG.getString("Spotify Client Id", "spotify", "", "Input client id of your spotify app \nDeclaration: this mod doesn't record or share your client id \nand it's not recommended for you to share your client id \nGuide: you have to create a spotify app to get client id & secrete \nhttps://developer.spotify.com/documentation/web-api/concepts/apps \nRedirect URI should be set to http://localhost:8888 for this mod to listen"); + SPOTIFY_CLIENT_SECRET = CONFIG.getString("Spotify Client Secret", "spotify", "", "Input client secret of your spotify app \nDeclaration: this mod doesn't record or share your client secret \nand it's not recommended for you to share your client secret"); + } + catch (Exception ignored) { } + finally + { + if (CONFIG.hasChanged()) CONFIG.save(); + } + } +} diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/SpotifyAccessUtils.java b/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/SpotifyAccessUtils.java index 6294cfa..6cf43d4 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/SpotifyAccessUtils.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/SpotifyAccessUtils.java @@ -47,9 +47,9 @@ public static TrackPlaying getCurrentlyPlaying(String accessToken) throws Except String album = RawJsonUtils.extractValue(item, "album"); String images = RawJsonUtils.extractValue(album, "images"); List imageList = RawJsonUtils.splitArray(images); - track.albumImage64by64 = RawJsonUtils.extractValue(imageList.get(0), "url"); + track.albumImage64by64 = RawJsonUtils.extractValue(imageList.get(2), "url"); track.albumImage300by300 = RawJsonUtils.extractValue(imageList.get(1), "url"); - track.albumImage640by640 = RawJsonUtils.extractValue(imageList.get(2), "url"); + track.albumImage640by640 = RawJsonUtils.extractValue(imageList.get(0), "url"); String artists = RawJsonUtils.extractValue(item, "artists"); List artistList = RawJsonUtils.splitArray(artists); diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/SpotifyOAuthUtils.java b/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/SpotifyOAuthUtils.java index 7dc9883..9dd9c44 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/SpotifyOAuthUtils.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/SpotifyOAuthUtils.java @@ -7,7 +7,7 @@ import java.io.*; import java.net.*; import java.nio.charset.StandardCharsets; -import java.time.LocalDate; +import java.time.LocalDateTime; import javax.net.ssl.HttpsURLConnection; @SuppressWarnings("all") @@ -45,6 +45,19 @@ public void handle(HttpExchange exchange) throws IOException { SpotifyUserInfo.token = getToken(authorizationCode); + // write it to local cache + File directory = new File("config/ingameinfo/cache"); + if (!directory.exists()) directory.mkdirs(); + try + { + RandomAccessFile file = new RandomAccessFile("config/ingameinfo/cache/spotify_refresh_token.txt", "rw"); + file.setLength(0); + file.seek(0); + file.write(SpotifyUserInfo.token.refreshToken.getBytes(StandardCharsets.UTF_8)); + file.close(); + } + catch (Exception ignored) { } + String response = "

[In-Game Info Reborn]


Authorization Successful

You can close this window

"; byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8); exchange.getResponseHeaders().set("Content-Type", "text/html; charset=UTF-8"); @@ -80,8 +93,8 @@ public void handle(HttpExchange exchange) throws IOException } } - public static final String CLIENT_ID = ""; - public static final String CLIENT_SECRET = ""; + public static String CLIENT_ID = ""; + public static String CLIENT_SECRET = ""; // make sure this matches the redirect uri registered in your Spotify app private static final String REDIRECT_URI = "http://localhost:8888"; @@ -197,6 +210,6 @@ public static void refreshAccessToken(Token token) throws IOException token.accessToken = accessToken; token.expiresIn = Integer.parseInt(expiresIn); - token.start = LocalDate.now(); + token.start = LocalDateTime.now(); } } diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/Token.java b/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/Token.java index 3b06dfd..b7e3b8f 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/Token.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/api/appcommunication/spotify/Token.java @@ -1,6 +1,6 @@ package com.tttsaurus.ingameinfo.common.api.appcommunication.spotify; -import java.time.LocalDate; +import java.time.LocalDateTime; public class Token { @@ -8,14 +8,14 @@ public class Token public String refreshToken; public int expiresIn; - public LocalDate start; + public LocalDateTime start; public Token(String accessToken, String refreshToken, int expiresIn) { this.accessToken = accessToken; this.refreshToken = refreshToken; this.expiresIn = expiresIn; - this.start = LocalDate.now(); + this.start = LocalDateTime.now(); } public Token() @@ -23,6 +23,6 @@ public Token() accessToken = ""; refreshToken = ""; expiresIn = 0; - start = LocalDate.now(); + start = LocalDateTime.now(); } } diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/api/gui/IgiGuiContainer.java b/src/main/java/com/tttsaurus/ingameinfo/common/api/gui/IgiGuiContainer.java index 0877e46..709f7fe 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/api/gui/IgiGuiContainer.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/api/gui/IgiGuiContainer.java @@ -27,6 +27,7 @@ public class IgiGuiContainer protected int backgroundColor = -1072689136; private boolean initFlag = false; + private boolean active = true; // public int getExitKeyForFocusedGui() { return exitKeyForFocusedGui; } @@ -49,6 +50,7 @@ public void onInit() mainGroup.calcRenderPos(mainGroup.rect); mainGroup.finishReCalc(); + viewModel.activeSetter = (flag) -> { active = flag; }; viewModel.start(); } public void onScaledResolutionResize() @@ -59,10 +61,15 @@ public void onScaledResolutionResize() } public void onFixedUpdate(double deltaTime) { + if (!active) return; + + viewModel.onFixedUpdate(deltaTime); mainGroup.onFixedUpdate(deltaTime); } public void onRenderUpdate(boolean focused) { + if (!active) return; + if (isFocused && hasFocusBackground) { ScaledResolution resolution = new ScaledResolution(Minecraft.getMinecraft()); diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/api/mvvm/view/View.java b/src/main/java/com/tttsaurus/ingameinfo/common/api/mvvm/view/View.java index 5159403..44151cc 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/api/mvvm/view/View.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/api/mvvm/view/View.java @@ -74,11 +74,11 @@ private GuiLayout init() } } + file.close(); + GuiLayoutDeserializer deserializer = new GuiLayoutDeserializer(); GuiLayout guiLayout = deserializer.deserialize(builder.toString(), "ixml"); - file.close(); - return guiLayout; } catch (Exception ignored) { return InternalMethods.instance.GuiLayout$constructor.invoke(); } diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/api/mvvm/viewmodel/ViewModel.java b/src/main/java/com/tttsaurus/ingameinfo/common/api/mvvm/viewmodel/ViewModel.java index 7e74746..a9b9c82 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/api/mvvm/viewmodel/ViewModel.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/api/mvvm/viewmodel/ViewModel.java @@ -1,6 +1,7 @@ package com.tttsaurus.ingameinfo.common.api.mvvm.viewmodel; import com.tttsaurus.ingameinfo.common.api.gui.GuiLayout; +import com.tttsaurus.ingameinfo.common.api.internal.IAction_1Param; import com.tttsaurus.ingameinfo.common.api.mvvm.binding.IReactiveObjectGetter; import com.tttsaurus.ingameinfo.common.api.mvvm.binding.Reactive; import com.tttsaurus.ingameinfo.common.api.mvvm.binding.VvmBinding; @@ -13,6 +14,8 @@ @SuppressWarnings("all") public abstract class ViewModel { + public IAction_1Param activeSetter; + private VvmBinding binding = new VvmBinding<>(); // init entry point @@ -28,4 +31,5 @@ private GuiLayout init(String mvvmRegistryName) } public abstract void start(); + public abstract void onFixedUpdate(double deltaTime); } diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/api/render/RenderUtils.java b/src/main/java/com/tttsaurus/ingameinfo/common/api/render/RenderUtils.java index 961c445..03f3fc8 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/api/render/RenderUtils.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/api/render/RenderUtils.java @@ -11,6 +11,8 @@ import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; public final class RenderUtils { @@ -248,8 +250,12 @@ public static void renderRectOutline(float x, float y, float width, float height GlStateManager.popMatrix(); } + private static final IntBuffer intBuffer = ByteBuffer.allocateDirect(16 << 2).order(ByteOrder.nativeOrder()).asIntBuffer(); public static void renderTexture2D(float x, float y, float width, float height, int textureWidth, int textureHeight) { + GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D, intBuffer); + int textureID = intBuffer.get(0); + GlStateManager.enableTexture2D(); GlStateManager.disableLighting(); GlStateManager.enableBlend(); @@ -263,6 +269,8 @@ public static void renderTexture2D(float x, float y, float width, float height, GlStateManager.scale(width/(float)((int)(width)), height/(float)((int)(height)), 0); Gui.drawScaledCustomSizeModalRect(0, 0, 0, 0, textureWidth, textureHeight, (int)width, (int)height, textureWidth, textureHeight); GlStateManager.popMatrix(); + + GlStateManager.bindTexture(textureID); } public static Texture2D getInGameScreenShot(int x, int y, int width, int height) diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/impl/appcommunication/spotify/SpotifyCommandHandler.java b/src/main/java/com/tttsaurus/ingameinfo/common/impl/appcommunication/spotify/SpotifyCommandHandler.java index 0c4a7e1..226dae6 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/impl/appcommunication/spotify/SpotifyCommandHandler.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/impl/appcommunication/spotify/SpotifyCommandHandler.java @@ -1,10 +1,8 @@ package com.tttsaurus.ingameinfo.common.impl.appcommunication.spotify; -import com.tttsaurus.ingameinfo.common.api.appcommunication.spotify.SpotifyAccessUtils; import com.tttsaurus.ingameinfo.common.api.appcommunication.spotify.SpotifyOAuthUtils; -import com.tttsaurus.ingameinfo.common.api.appcommunication.spotify.TrackPlaying; import com.tttsaurus.ingameinfo.common.api.appcommunication.spotify.SpotifyUserInfo; -import com.tttsaurus.ingameinfo.common.impl.render.renderer.UrlImageRenderer; +import com.tttsaurus.ingameinfo.common.impl.igievent.EventCenter; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.util.text.Style; @@ -42,10 +40,10 @@ public static void onChatReceived(ClientChatReceivedEvent event) else if (message.startsWith("#spotify-oauth-code")) { event.setCanceled(true); - player.sendMessage(new TextComponentString(TextFormatting.DARK_PURPLE + message)); String[] args = message.split(" "); if (args.length == 2) { + player.sendMessage(new TextComponentString(TextFormatting.DARK_PURPLE + message)); String authorizationCode = args[1]; try { @@ -62,38 +60,29 @@ else if (message.startsWith("#spotify-oauth-code")) } } } - else if (message.startsWith("#spotify-ui-display")) + else if (message.startsWith("#spotify-gui")) { event.setCanceled(true); - player.sendMessage(new TextComponentString(TextFormatting.DARK_PURPLE + message)); String[] args = message.split(" "); if (args.length == 2) { String param = args[1]; if (param.equals("true") || param.equals("false")) { + player.sendMessage(new TextComponentString(TextFormatting.DARK_PURPLE + message)); boolean flag = param.equals("true"); if (flag) { if (SpotifyUserInfo.token.accessToken.isEmpty()) { player.sendMessage(new TextComponentString(TextFormatting.AQUA + "[SpotifyBot]" + TextFormatting.RESET + " The access token is empty.")); + player.sendMessage(new TextComponentString(TextFormatting.AQUA + "[SpotifyBot]" + TextFormatting.RESET + " Please run the command #spotify-oauth first.")); return; } - try - { - TrackPlaying trackPlaying = SpotifyAccessUtils.getCurrentlyPlaying(SpotifyUserInfo.token.accessToken); - player.sendMessage(new TextComponentString(TextFormatting.AQUA + "[SpotifyBot]" + TextFormatting.RESET + " " + trackPlaying.trackName)); - trackPlaying.artists.forEach(str -> player.sendMessage(new TextComponentString(TextFormatting.AQUA + "[SpotifyBot]" + TextFormatting.RESET + " " + str))); - UrlImageRenderer.SHARED.updateURL(trackPlaying.albumImage640by640); - } - catch (Exception e) - { - player.sendMessage(new TextComponentString(TextFormatting.AQUA + "[SpotifyBot]" + TextFormatting.RESET + " Exception: " + e.getMessage())); - return; - } - // display + EventCenter.spotifyOverlayEvent.trigger(true); } + else + EventCenter.spotifyOverlayEvent.trigger(false); } } } diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/impl/appcommunication/spotify/SpotifyViewModel.java b/src/main/java/com/tttsaurus/ingameinfo/common/impl/appcommunication/spotify/SpotifyViewModel.java index 7f108ad..c3f0d27 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/impl/appcommunication/spotify/SpotifyViewModel.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/impl/appcommunication/spotify/SpotifyViewModel.java @@ -1,17 +1,108 @@ package com.tttsaurus.ingameinfo.common.impl.appcommunication.spotify; +import com.tttsaurus.ingameinfo.common.api.appcommunication.spotify.SpotifyAccessUtils; +import com.tttsaurus.ingameinfo.common.api.appcommunication.spotify.SpotifyOAuthUtils; +import com.tttsaurus.ingameinfo.common.api.appcommunication.spotify.SpotifyUserInfo; +import com.tttsaurus.ingameinfo.common.api.appcommunication.spotify.TrackPlaying; import com.tttsaurus.ingameinfo.common.api.mvvm.binding.Reactive; import com.tttsaurus.ingameinfo.common.api.mvvm.binding.ReactiveObject; import com.tttsaurus.ingameinfo.common.api.mvvm.viewmodel.ViewModel; +import com.tttsaurus.ingameinfo.common.impl.igievent.EventCenter; +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.concurrent.CompletableFuture; public class SpotifyViewModel extends ViewModel { @Reactive(targetUid = "albumImage", property = "url", initiativeSync = true) public ReactiveObject albumImageUrl = new ReactiveObject<>(){}; + @Reactive(targetUid = "trackTitle", property = "text", initiativeSync = true) + public ReactiveObject trackTitleText = new ReactiveObject<>(){}; + @Override public void start() { - albumImageUrl.set("https://media.forgecdn.net/avatars/thumbnails/1071/348/256/256/638606872011907048.png"); + activeSetter.invoke(false); + EventCenter.spotifyOverlayEvent.addListener((flag) -> + { + if (flag) + { + activeSetter.invoke(true); + trackTitleText.set("Please wait..."); + CompletableFuture.supplyAsync(() -> + { + try + { + TrackPlaying trackPlaying = SpotifyAccessUtils.getCurrentlyPlaying(SpotifyUserInfo.token.accessToken); + albumImageUrl.set(trackPlaying.albumImage300by300); + trackTitleText.set(trackPlaying.trackName); + } + catch (Exception ignored) { } + return null; + }); + } + else + activeSetter.invoke(false); + }); + + // read refresh token and refresh + File directory = new File("config/ingameinfo/cache"); + if (!directory.exists()) directory.mkdirs(); + try + { + RandomAccessFile file = new RandomAccessFile("config/ingameinfo/cache/spotify_refresh_token.txt", "rw"); + StringBuilder builder = new StringBuilder(); + String line = file.readLine(); + while (line != null) + { + builder.append(line); + line = file.readLine(); + } + + String refreshToken = builder.toString(); + if (!refreshToken.isEmpty()) + { + try + { + SpotifyUserInfo.token.refreshToken = refreshToken; + SpotifyOAuthUtils.refreshAccessToken(SpotifyUserInfo.token); + } + catch (IOException e) + { + file.setLength(0); + } + } + + file.close(); + } + catch (Exception ignored) { } + } + + private float refreshTokenTimer = 0; + @Override + public void onFixedUpdate(double deltaTime) + { + refreshTokenTimer += (float)deltaTime; + if (refreshTokenTimer > 1f) + { + refreshTokenTimer -= 1f; + long timeSpan = Duration.between(SpotifyUserInfo.token.start, LocalDateTime.now()).getSeconds(); + if (timeSpan >= (SpotifyUserInfo.token.expiresIn - 5)) + { + CompletableFuture.supplyAsync(() -> + { + try + { + SpotifyOAuthUtils.refreshAccessToken(SpotifyUserInfo.token); + } + catch (Exception ignored) { } + return null; + }); + } + } } } diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/impl/gui/IgiGuiLifeCycle.java b/src/main/java/com/tttsaurus/ingameinfo/common/impl/gui/IgiGuiLifeCycle.java index 16929c4..43c079b 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/impl/gui/IgiGuiLifeCycle.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/impl/gui/IgiGuiLifeCycle.java @@ -235,7 +235,7 @@ public static void onRenderGameOverlay(RenderGameOverlayEvent event) else if (!isPlaceholderGuiOn && !openedGuiMap.isEmpty() && Minecraft.getMinecraft().currentScreen == null) { AtomicBoolean focus = new AtomicBoolean(false); - openedGuiMap.forEach((uuis, guiContainer) -> focus.set(focus.get() || guiContainer.getFocused())); + openedGuiMap.forEach((uuid, guiContainer) -> focus.set(focus.get() || guiContainer.getFocused())); if (focus.get()) { diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/impl/gui/control/UrlImage.java b/src/main/java/com/tttsaurus/ingameinfo/common/impl/gui/control/UrlImage.java index 38edcc5..a1bb5d2 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/impl/gui/control/UrlImage.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/impl/gui/control/UrlImage.java @@ -20,7 +20,7 @@ public void urlValidation(String value, CallbackInfo callbackInfo) @StylePropertyCallback public void setUrlCallback() { - urlImageRenderer.updateURL(url); + urlImageRenderer.updateUrlAsync(url); } @StyleProperty(setterCallbackPost = "setUrlCallback", setterCallbackPre = "urlValidation") public String url; diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/impl/igievent/EventCenter.java b/src/main/java/com/tttsaurus/ingameinfo/common/impl/igievent/EventCenter.java index 65662bf..f4d907b 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/impl/igievent/EventCenter.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/impl/igievent/EventCenter.java @@ -5,4 +5,7 @@ public final class EventCenter public final static IgiGuiFpsEvent igiGuiFpsEvent = new IgiGuiFpsEvent(); public final static GameFpsEvent gameFpsEvent = new GameFpsEvent(); public final static GameMemoryEvent gameMemoryEvent = new GameMemoryEvent(); + + // spotify + public final static SpotifyOverlayEvent spotifyOverlayEvent = new SpotifyOverlayEvent(); } diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/impl/igievent/SpotifyOverlayEvent.java b/src/main/java/com/tttsaurus/ingameinfo/common/impl/igievent/SpotifyOverlayEvent.java new file mode 100644 index 0000000..534ccc1 --- /dev/null +++ b/src/main/java/com/tttsaurus/ingameinfo/common/impl/igievent/SpotifyOverlayEvent.java @@ -0,0 +1,13 @@ +package com.tttsaurus.ingameinfo.common.impl.igievent; + +import com.tttsaurus.ingameinfo.common.api.igievent.EventBase; +import com.tttsaurus.ingameinfo.common.api.internal.IAction_1Param; + +public class SpotifyOverlayEvent extends EventBase> +{ + @Override + public void addListener(IAction_1Param listener) + { + addListenerInternal(listener); + } +} diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/impl/mvvm/registry/MvvmRegisterEventHandler.java b/src/main/java/com/tttsaurus/ingameinfo/common/impl/mvvm/registry/MvvmRegisterEventHandler.java index 088af27..ef08e66 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/impl/mvvm/registry/MvvmRegisterEventHandler.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/impl/mvvm/registry/MvvmRegisterEventHandler.java @@ -1,6 +1,7 @@ package com.tttsaurus.ingameinfo.common.impl.mvvm.registry; import com.tttsaurus.ingameinfo.common.api.event.MvvmRegisterEvent; +import com.tttsaurus.ingameinfo.common.api.gui.IgiGuiManager; import com.tttsaurus.ingameinfo.common.impl.appcommunication.spotify.SpotifyViewModel; import com.tttsaurus.ingameinfo.plugin.crt.impl.CrtMvvm; import com.tttsaurus.ingameinfo.plugin.crt.impl.CrtViewModel; @@ -20,5 +21,7 @@ public static void onMvvmRegister(MvvmRegisterEvent event) } MvvmRegistry.autoRegister("spotify", SpotifyViewModel.class); + + IgiGuiManager.openGui("spotify"); } } diff --git a/src/main/java/com/tttsaurus/ingameinfo/common/impl/render/renderer/UrlImageRenderer.java b/src/main/java/com/tttsaurus/ingameinfo/common/impl/render/renderer/UrlImageRenderer.java index ea76b06..885a44e 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/common/impl/render/renderer/UrlImageRenderer.java +++ b/src/main/java/com/tttsaurus/ingameinfo/common/impl/render/renderer/UrlImageRenderer.java @@ -7,11 +7,10 @@ import java.io.InputStream; import java.net.URL; import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; public class UrlImageRenderer extends ImageRenderer { - public static final UrlImageRenderer SHARED = new UrlImageRenderer("https://media.forgecdn.net/avatars/thumbnails/1071/348/256/256/638606872011907048.png"); - public UrlImageRenderer() { } public UrlImageRenderer(String url) @@ -20,7 +19,41 @@ public UrlImageRenderer(String url) if (image != null) texture = createTexture(image); } - public void updateURL(String url) + private BufferedImage asyncImage = null; + + public void updateUrlAsync(String url) + { + CompletableFuture.supplyAsync(() -> + { + try + { + URL imageUrl = new URL(url); + InputStream in = imageUrl.openStream(); + return ImageIO.read(in); + } + catch (Exception e) + { + return null; + } + }).thenAccept(image -> + { + if (image != null) asyncImage = image; + }); + } + + @Override + public void render() + { + if (asyncImage != null) + { + if (texture != null) texture.dispose(); + texture = createTexture(asyncImage); + asyncImage = null; + } + super.render(); + } + + public void updateUrl(String url) { BufferedImage image = downloadImage(url); if (image != null) diff --git a/src/main/java/com/tttsaurus/ingameinfo/plugin/crt/impl/CrtViewModel.java b/src/main/java/com/tttsaurus/ingameinfo/plugin/crt/impl/CrtViewModel.java index 2994840..9359008 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/plugin/crt/impl/CrtViewModel.java +++ b/src/main/java/com/tttsaurus/ingameinfo/plugin/crt/impl/CrtViewModel.java @@ -66,4 +66,10 @@ public void start() IViewModelStart action = startActions.get(runtimeMvvm); if (action != null) action.start(); } + + @Override + public void onFixedUpdate(double deltaTime) + { + + } } diff --git a/src/main/java/com/tttsaurus/ingameinfo/proxy/CommonProxy.java b/src/main/java/com/tttsaurus/ingameinfo/proxy/CommonProxy.java index f72e176..1ccf723 100644 --- a/src/main/java/com/tttsaurus/ingameinfo/proxy/CommonProxy.java +++ b/src/main/java/com/tttsaurus/ingameinfo/proxy/CommonProxy.java @@ -2,6 +2,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.tttsaurus.ingameinfo.IgiConfig; +import com.tttsaurus.ingameinfo.common.api.appcommunication.spotify.SpotifyOAuthUtils; import com.tttsaurus.ingameinfo.common.api.event.MvvmRegisterEvent; import com.tttsaurus.ingameinfo.common.api.gui.Element; import com.tttsaurus.ingameinfo.common.api.gui.style.IStylePropertyCallbackPost; @@ -16,6 +18,7 @@ import com.tttsaurus.ingameinfo.common.impl.mvvm.registry.MvvmRegisterEventHandler; import com.tttsaurus.ingameinfo.plugin.crt.impl.CrtEventManager; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.config.Configuration; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import org.apache.logging.log4j.Logger; @@ -25,7 +28,11 @@ public class CommonProxy { public void preInit(FMLPreInitializationEvent event, Logger logger) { + IgiConfig.CONFIG = new Configuration(event.getSuggestedConfigurationFile()); + IgiConfig.loadConfig(); + SpotifyOAuthUtils.CLIENT_ID = IgiConfig.SPOTIFY_CLIENT_ID; + SpotifyOAuthUtils.CLIENT_SECRET = IgiConfig.SPOTIFY_CLIENT_SECRET; } public void init(FMLInitializationEvent event, Logger logger)