summary refs log blame commit diff stats
path: root/src/main/java/ganarchy/friendcode/client/FriendConnectingScreen.java
blob: 748801c67235b546444349dbabcd8e5d40aa3cb0 (plain) (tree)













































































































                                                                                                                                                                                                                                                           
package ganarchy.friendcode.client;

import it.unimi.dsi.fastutil.booleans.BooleanConsumer;
import net.minecraft.client.gui.screen.LoadingDisplay;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.screen.ScreenTexts;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
import org.apache.commons.codec.binary.Base32;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Locale;

public class FriendConnectingScreen extends Screen {
    private static final Text PATIENCE_TEXT = Text.translatable("friendcode.patience");
    private final ServerInfo serverEntry;
    private final BooleanConsumer callback;
    private final SamProxyThread proxyThread;
    private long startTimeMs;
    private Text renderText = null;

    public FriendConnectingScreen(ServerInfo serverEntry, BooleanConsumer callback, String text) {
        super(Text.translatable("friendcode.connecting"));
        this.serverEntry = serverEntry;
        this.callback = callback;
        this.startTimeMs = Util.getMeasuringTimeMs();
        this.proxyThread = new SamProxyThread(text);
    }

    @Override
    protected void init() {
        try {
            this.proxyThread.start();
        } catch (IllegalThreadStateException ignored) {
        }
        // cancel friend code.
        this.addDrawableChild(new ButtonWidget(
                this.width / 2 - 155,
                this.height - 28,
                310,
                20,
                ScreenTexts.CANCEL,
                button -> this.close()
        ));
    }


    @Override
    public void close() {
        super.close();
        if (this.proxyThread.status() != SamProxyThread.Status.RUNNING) {
            this.proxyThread.stopProxy();
        }
    }

    @Override
    public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
        this.renderBackground(matrices);
        FriendConnectingScreen.drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 50, 0xFFFFFF);
        if (this.renderText != null) {
            FriendConnectingScreen.drawCenteredText(matrices, this.textRenderer, this.renderText, this.width / 2, 82, 0xFFFFFF);
        } else {
            FriendConnectingScreen.drawCenteredText(matrices, this.textRenderer, PATIENCE_TEXT, this.width / 2, 82, 0xFFFFFF);
            final String string = LoadingDisplay.get(Util.getMeasuringTimeMs());
            this.client.textRenderer.draw(matrices, string, (float) (this.client.currentScreen.width / 2 - this.client.textRenderer.getWidth(string) / 2), (float) (this.client.currentScreen.height / 2 + this.client.textRenderer.fontHeight), 0x808080);
        }
        super.render(matrices, mouseX, mouseY, delta);
    }

    @Override
    public void tick() {
        super.tick();
        if (proxyThread.status() != SamProxyThread.Status.IDLE) {
            switch (proxyThread.status()) {
                case CONNECTION_FAILED -> {
                    this.renderText = Text.translatable("friendcode.connect.no_i2p");
                    break;
                }
                case SETUP_FAILED -> {
                    this.renderText = Text.translatable("friendcode.connect.failed");
                    break;
                }
                case RESOLUTION_FAILED -> {
                    this.renderText = Text.translatable("friendcode.connect.no_such_code");
                    break;
                }
                case RUNNING -> {
                    this.serverEntry.address = "[::1]:" + this.proxyThread.port();
                    this.callback.accept(true);
                    break;
                }
            }
        }
        if (!this.proxyThread.isConnecting()) {
            startTimeMs = Util.getMeasuringTimeMs();
        }
        if (Util.getMeasuringTimeMs() - startTimeMs > 20 * 1000) {
            // keep it from getting stuck.
            // FIXME this is wrong.
            //this.proxyThread.interrupt();
        }
    }
}