From bfb981cd49a6bbcd15482dceeb4ab121c0408157 Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Sun, 3 Jul 2022 23:12:06 -0300 Subject: [Project] Friend Code A Minecraft mod which adds friend codes, an easy way to play in the same world with remote friends. --- .../friendcode/client/FriendCodeScreen.java | 141 +++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 src/main/java/ganarchy/friendcode/client/FriendCodeScreen.java (limited to 'src/main/java/ganarchy/friendcode/client/FriendCodeScreen.java') 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); + } +} -- cgit 1.4.1