summary refs log tree commit diff stats
path: root/src/main/java/ganarchy/friendcode/client/FriendCodeScreen.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/ganarchy/friendcode/client/FriendCodeScreen.java')
-rw-r--r--src/main/java/ganarchy/friendcode/client/FriendCodeScreen.java141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/main/java/ganarchy/friendcode/client/FriendCodeScreen.java b/src/main/java/ganarchy/friendcode/client/FriendCodeScreen.java
new file mode 100644
index 0000000..38703a5
--- /dev/null
+++ b/src/main/java/ganarchy/friendcode/client/FriendCodeScreen.java
@@ -0,0 +1,141 @@
+package ganarchy.friendcode.client;
+
+import ganarchy.friendcode.FriendCode;
+import ganarchy.friendcode.mixin.FriendCodeIntegratedServerExt;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.OpenToLanScreen;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.gui.widget.CyclingButtonWidget;
+import net.minecraft.client.util.NetworkUtils;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.screen.ScreenTexts;
+import net.minecraft.server.network.ServerPlayerEntity;
+import net.minecraft.text.MutableText;
+import net.minecraft.text.Text;
+import net.minecraft.world.GameMode;
+
+import java.io.IOException;
+
+@Environment(EnvType.CLIENT)
+public class FriendCodeScreen extends Screen {
+    private static final Text ALLOW_COMMANDS_TEXT = Text.translatable("selectWorld.allowCommands");
+    private static final Text GAME_MODE_TEXT = Text.translatable("selectWorld.gameMode");
+    private static final Text OTHER_PLAYERS_TEXT = Text.translatable("lanServer.otherPlayers");
+    private final Screen parent;
+    private GameMode gameMode = GameMode.SURVIVAL;
+    private boolean allowCommands;
+
+    private static final Text START_SHARING = Text.translatable("friendcode.start");
+
+    public FriendCodeScreen(Screen parent) {
+        super(Text.translatable("friendcode.title"));
+        this.parent = parent;
+    }
+
+    @Override
+    protected void init() {
+        // title button allows going back to LAN screen
+        this.addDrawableChild(new ButtonWidget(
+            this.width / 2 - 155,
+            50,
+            310,
+            20,
+            this.title,
+            button -> this.client.setScreen(new OpenToLanScreen(this.parent))
+        ));
+
+        // game setting buttons
+        this.addDrawableChild(
+            CyclingButtonWidget
+            .builder(GameMode::getSimpleTranslatableName)
+            .values(GameMode.SURVIVAL, GameMode.SPECTATOR, GameMode.CREATIVE, GameMode.ADVENTURE)
+            .initially(this.gameMode)
+            .build(
+                this.width / 2 - 155,
+                100,
+                150,
+                20,
+                GAME_MODE_TEXT,
+                (button, gameMode) -> {
+                    this.gameMode = gameMode;
+                }
+            )
+        );
+        this.addDrawableChild(
+            CyclingButtonWidget
+            .onOffBuilder(this.allowCommands)
+            .build(
+                this.width / 2 + 5,
+                100,
+                150,
+                20,
+                ALLOW_COMMANDS_TEXT,
+                (button, allowCommands) -> {
+                    this.allowCommands = allowCommands;
+                }
+            )
+        );
+
+        // start sharing
+        this.addDrawableChild(new ButtonWidget(
+            this.width / 2 - 155,
+            this.height - 28,
+            150,
+            20,
+            START_SHARING,
+            button -> {
+                // FIXME
+                int i = NetworkUtils.findLocalPort();
+                var samPinger = openToFriends(this.client, this.gameMode, this.allowCommands, i);
+                MutableText text = samPinger != null ? Text.translatable("commands.publish.started", i) : Text.translatable("commands.publish.failed");
+                this.client.inGameHud.getChatHud().addMessage(text);
+                this.client.updateWindowTitle();
+                this.client.setScreen(new WaitingForFriendCodeScreen(samPinger));
+            }
+        ));
+
+        // go back to options
+        this.addDrawableChild(new ButtonWidget(
+            this.width / 2 + 5,
+            this.height - 28,
+            150,
+            20,
+            ScreenTexts.CANCEL,
+            button -> this.client.setScreen(this.parent)
+        ));
+    }
+
+    private static I2PSamPinger openToFriends(MinecraftClient client, GameMode gameMode, boolean allowCommands, int port) {
+        try {
+            client.loadBlockList();
+            client.getServer().getNetworkIo().bind(null, port);
+            FriendCode.LOGGER.info("Started serving on {}", port);
+            ((FriendCodeIntegratedServerExt) client.getServer()).lanPort(port);
+            // reuse LAN pinger machinery instead of rolling our own
+            var lanPinger = new I2PSamPinger(client.getServer().getServerMotd(), "" + port);
+            ((FriendCodeIntegratedServerExt) client.getServer()).lanPinger(lanPinger);
+            lanPinger.start();
+            ((FriendCodeIntegratedServerExt) client.getServer()).forcedGameMode(gameMode);
+            client.getServer().getPlayerManager().setCheatsAllowed(allowCommands);
+            int i = client.getServer().getPermissionLevel(client.player.getGameProfile());
+            client.player.setClientPermissionLevel(i);
+            for (ServerPlayerEntity serverPlayerEntity : client.getServer().getPlayerManager().getPlayerList()) {
+                client.getServer().getCommandManager().sendCommandTree(serverPlayerEntity);
+            }
+            return lanPinger;
+        }
+        catch (IOException iOException) {
+            return null;
+        }
+    }
+
+    @Override
+    public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
+        this.renderBackground(matrices);
+        FriendCodeScreen.drawCenteredText(matrices, this.textRenderer, OTHER_PLAYERS_TEXT, this.width / 2, 82, 0xFFFFFF);
+        super.render(matrices, mouseX, mouseY, delta);
+    }
+}