Last active
December 30, 2025 15:28
-
-
Save solaritygh/0f24f473948bbfb8a56af58b08731180 to your computer and use it in GitHub Desktop.
Episode 2 resources
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package tutorial.account; | |
| import com.google.gson.*; | |
| import com.google.gson.annotations.Expose; | |
| import net.lenni0451.commons.httpclient.HttpClient; | |
| import net.minecraft.client.Minecraft; | |
| import net.minecraft.util.Session; | |
| import net.raphimc.minecraftauth.MinecraftAuth; | |
| import net.raphimc.minecraftauth.java.JavaAuthManager; | |
| import net.raphimc.minecraftauth.java.model.MinecraftProfile; | |
| import net.raphimc.minecraftauth.java.model.MinecraftToken; | |
| import net.raphimc.minecraftauth.msa.model.MsaDeviceCode; | |
| import net.raphimc.minecraftauth.msa.service.MsaAuthService; | |
| import net.raphimc.minecraftauth.msa.service.impl.DeviceCodeMsaAuthService; | |
| import java.io.*; | |
| import java.lang.reflect.Type; | |
| import java.nio.charset.StandardCharsets; | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import java.nio.file.Paths; | |
| import java.util.ArrayList; | |
| import java.util.HashMap; | |
| import java.util.UUID; | |
| import java.util.concurrent.TimeoutException; | |
| import java.util.function.Consumer; | |
| import org.apache.commons.logging.Log; | |
| import org.apache.commons.logging.LogFactory; | |
| import tutorial.util.GSONUtil; | |
| /** | |
| * @author Mort | |
| * Created by Mort on 12/29/2025. | |
| */ | |
| public class AccountManager { | |
| private static final Log log = LogFactory.getLog(AccountManager.class); | |
| private final Minecraft mc = Minecraft.getMinecraft(); | |
| private String name = mc.getSession().getUsername(); | |
| private String id = mc.getSession().getPlayerID(); | |
| private String token = mc.getSession().getToken(); | |
| private String type = String.valueOf(mc.getSession().getSessionType()); | |
| private JavaAuthManager authManager; | |
| private JavaAuthManager.Builder authManagerBuilder; | |
| private HashMap<String, Session> SESSION_CACHE = new HashMap<>(); | |
| public void login(String username, String id, String token, String type) { | |
| mc.setSession(new Session(username, id, token, type)); | |
| SESSION_CACHE.put(id, new Session(username, id, token, type)); | |
| this.name = username; | |
| this.id = id; | |
| this.token = token; | |
| this.type = type; | |
| } | |
| public void loginWithOfflineAccount(String username) { | |
| login(username, username, "", "legacy"); | |
| } | |
| public boolean isLoggedIn(String username, String id) { | |
| if (SESSION_CACHE.get(id) == null) | |
| return false; | |
| return SESSION_CACHE.containsKey(id); | |
| } | |
| public void loginWithMicrosoftCode(StatusCallback callback) { | |
| new Thread(() -> { | |
| callback.onText("Logging in..."); | |
| try { | |
| authManager = authManagerBuilder.login(DeviceCodeMsaAuthService::new, new Consumer<MsaDeviceCode>() { | |
| @Override | |
| public void accept(MsaDeviceCode deviceCode) { | |
| callback.onText("Go to " + deviceCode.getDirectVerificationUri()); | |
| } | |
| }); | |
| if (authManager == null) { | |
| callback.onText("ERROR: Authentication manager is not initialized."); | |
| return; | |
| } | |
| // Ensure Minecraft profile and token are not null | |
| MinecraftProfile profile = authManager.getMinecraftProfile().getUpToDate(); | |
| if (profile == null) { | |
| callback.onText("ERROR: Minecraft profile is null."); | |
| return; | |
| } | |
| MinecraftToken token = authManager.getMinecraftToken().getUpToDate(); | |
| if (token == null) { | |
| callback.onText("ERROR: Minecraft token is null."); | |
| return; | |
| } | |
| login(profile.getName(), profile.getId().toString(), | |
| token.getToken(), token.getType()); | |
| // Save to file after login | |
| File file = new File("tutorial/accounts.json"); | |
| File parentDir = file.getParentFile(); | |
| if (parentDir != null && !parentDir.exists()) { | |
| parentDir.mkdirs(); // create directories if they don't exist | |
| } | |
| try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file))) { | |
| JsonObject serializedAuthManager = JavaAuthManager.toJson(authManager); | |
| bufferedWriter.write(serializedAuthManager.toString()); | |
| } | |
| callback.onText("Successfully logged in!"); | |
| } catch (IOException | InterruptedException | TimeoutException e) { | |
| callback.onText("ERROR: " + e.getClass().getSimpleName()); | |
| e.printStackTrace(); | |
| } catch (NullPointerException e) { | |
| callback.onText("ERROR: Null pointer exception occurred."); | |
| e.printStackTrace(); | |
| } | |
| }, "Login thread").start(); | |
| } | |
| public interface StatusCallback { | |
| void onText(String text); | |
| } | |
| public void load() { | |
| HttpClient httpClient = MinecraftAuth.createHttpClient(); | |
| authManagerBuilder = JavaAuthManager.create(httpClient); | |
| try (Reader reader = Files.newBufferedReader(Paths.get("tutorial/accounts.json"), StandardCharsets.UTF_8)) { | |
| JsonElement jsonElement = JsonParser.parseReader(reader); | |
| JsonObject jsonObject = jsonElement.getAsJsonObject(); | |
| authManager = JavaAuthManager.fromJson(httpClient, jsonObject); | |
| login(authManager.getMinecraftProfile().getUpToDate().getName(), | |
| authManager.getMinecraftProfile().getUpToDate().getId().toString(), | |
| authManager.getMinecraftToken().getUpToDate().getToken(), | |
| authManager.getMinecraftToken().getUpToDate().getType()); | |
| } catch (IOException e) { | |
| authManager = null; | |
| } | |
| } | |
| public void save() { | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package tutorial.account.gui; | |
| import net.minecraft.client.gui.GuiButton; | |
| import net.minecraft.client.gui.GuiScreen; | |
| import net.minecraft.client.gui.ScaledResolution; | |
| import tutorial.Tutorial; | |
| import java.io.IOException; | |
| /** | |
| * @author Mort | |
| * Created by Mort on 12/29/2025. | |
| */ | |
| public class AccountScreen extends GuiScreen { | |
| private String status = "Waiting..."; | |
| private int x, y; | |
| private final GuiScreen parent; | |
| public AccountScreen(GuiScreen parent) { | |
| this.parent = parent; | |
| } | |
| @Override | |
| public void initGui() { | |
| super.initGui(); | |
| ScaledResolution sr = new ScaledResolution(mc); | |
| buttonList.add(new GuiButton(1, sr.getScaledWidth()/2 - 100, sr.getScaledHeight()/2, "Login")); | |
| buttonList.add(new GuiButton(2, sr.getScaledWidth()/2 - 100, sr.getScaledHeight()/2 + 35, "Cancel")); | |
| } | |
| @Override | |
| public void drawScreen(int mouseX, int mouseY, float partialTicks) { | |
| this.drawDefaultBackground(); | |
| super.drawScreen(mouseX, mouseY, partialTicks); | |
| ScaledResolution sr = new ScaledResolution(mc); | |
| this.drawCenteredString(fontRendererObj, status, sr.getScaledWidth()/2, sr.getScaledHeight() / 2, -1); | |
| } | |
| @Override | |
| protected void actionPerformed(GuiButton button) throws IOException { | |
| super.actionPerformed(button); | |
| switch (button.id) { | |
| case 1: | |
| Tutorial.INSTANCE.getAccountManager().loginWithMicrosoftCode(text -> AccountScreen.this.status = text); | |
| break; | |
| case 2: | |
| // cancel | |
| mc.displayGuiScreen(parent); | |
| break; | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import net.minecraft.client.Minecraft; | |
| import net.minecraft.client.gui.Gui; | |
| import org.lwjgl.input.Mouse; | |
| public class DraggableComponent { | |
| private int x, y; | |
| private int width, height; | |
| private int color; | |
| private int lastX, lastY; | |
| private boolean dragging; | |
| public DraggableComponent(int x, int y, int width, int height, int color) { | |
| this.x = x; | |
| this.y = y; | |
| this.width = width; | |
| this.height = height; | |
| this.color = color; | |
| } | |
| public int getxPosition() { | |
| return this.x; | |
| } | |
| public int getyPosition() { | |
| return this.y; | |
| } | |
| public void setxPosition(int x) { | |
| this.x = x; | |
| } | |
| public void setyPosition(int y) { | |
| this.y = y; | |
| } | |
| public int getWidth() { | |
| return this.width; | |
| } | |
| public int getHeight() { | |
| return this.height; | |
| } | |
| public int getColor() { | |
| return this.color; | |
| } | |
| public void setColor(int color) { | |
| this.color = color; | |
| } | |
| public void renderDummy(int mouseX, int mouseY) { | |
| if(this.dragging) { | |
| this.x = mouseX + this.lastX; | |
| this.y = mouseY + this.lastY; | |
| if(!Mouse.isButtonDown(0)) {this.dragging = false;} | |
| } | |
| boolean mouseOverX = (mouseX >= this.getxPosition() && mouseX <= this.getxPosition()+this.getWidth()); | |
| boolean mouseOverY = (mouseY >= this.getyPosition() && mouseY <= this.getyPosition()+this.getHeight()); | |
| if(mouseOverX && mouseOverY) { | |
| if(Mouse.isButtonDown(0)) { | |
| if(!this.dragging) { | |
| this.lastX = this.x - mouseX; | |
| this.lastY = this.y - mouseY; | |
| this.dragging = true; | |
| } | |
| } | |
| } | |
| } | |
| public void render() { | |
| Gui.drawRect(this.getxPosition(), this.getyPosition(), this.getxPosition()+this.getWidth(), this.getyPosition()+this.getHeight(), this.getColor()); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package tutorial.util; | |
| import com.google.gson.Gson; | |
| import com.google.gson.GsonBuilder; | |
| /** | |
| * @author Mort | |
| * Created by Mort on 12/29/2025. | |
| */ | |
| public class GSONUtil { | |
| private static Gson gson; | |
| public static void initGSON() { | |
| gson = new GsonBuilder() | |
| .excludeFieldsWithoutExposeAnnotation() | |
| .create(); | |
| } | |
| public static Gson getGson() { | |
| return gson; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <dependency> | |
| <groupId>net.raphimc</groupId> | |
| <artifactId>MinecraftAuth</artifactId> | |
| <version>5.0.0</version> | |
| </dependency> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment