Skip to content

Commit

Permalink
Work on protocol rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
Gaming32 committed Apr 20, 2023
1 parent fed3ed6 commit c4baa0f
Show file tree
Hide file tree
Showing 13 changed files with 813 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.github.gaming32.worldhost;

import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.toasts.SystemToast;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class DeferredToastManager {
@Nullable
public static IconRenderer queuedCustomIcon;

@FunctionalInterface
public interface IconRenderer {
void draw(PoseStack matrices, int x, int y);
}

private record ToastInfo(SystemToast.SystemToastIds type, IconRenderer icon, Component title, @Nullable Component description) {
}

private static List<ToastInfo> deferredToasts = new ArrayList<>();

public static void show(SystemToast.SystemToastIds type, Component title, @Nullable Component description) {
show(type, null, title, description);
}

public static void show(SystemToast.SystemToastIds type, IconRenderer icon, Component title, @Nullable Component description) {
final ToastInfo toast = new ToastInfo(type, icon, title, description);
if (deferredToasts != null) {
deferredToasts.add(toast);
} else {
show(toast);
}
}

private static void show(ToastInfo toast) {
Minecraft.getInstance().execute(() -> {
queuedCustomIcon = toast.icon;
SystemToast.addOrUpdate(
Minecraft.getInstance().getToasts(), toast.type, toast.title,
Objects.requireNonNullElse(toast.description, CommonComponents.EMPTY)
);
});
}

public static void ready() {
if (deferredToasts != null) {
deferredToasts.forEach(DeferredToastManager::show);
deferredToasts = null;
}
}
}
104 changes: 104 additions & 0 deletions src/main/java/io/github/gaming32/worldhost/WorldHost.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@

import com.mojang.authlib.GameProfile;
import com.mojang.blaze3d.systems.RenderSystem;
import io.github.gaming32.worldhost.protocol.ProtocolClient;
import io.github.gaming32.worldhost.upnp.Gateway;
import io.github.gaming32.worldhost.upnp.GatewayFinder;
import io.github.gaming32.worldhost.versions.Components;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.components.toasts.SystemToast;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.resources.SkinManager;
import net.minecraft.client.server.IntegratedServer;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket;
import net.minecraft.network.protocol.status.ServerStatus;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.players.GameProfileCache;
Expand All @@ -22,6 +31,7 @@
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.function.Supplier;

Expand Down Expand Up @@ -96,6 +106,11 @@ public class WorldHost

private static GameProfileCache profileCache;

public static boolean attemptingConnection;
public static ProtocolClient protoClient;
private static long lastReconnectTime;
private static Future<Void> connectingFuture;

//#if FABRIC
@Override
public void onInitializeClient() {
Expand Down Expand Up @@ -131,6 +146,8 @@ private static void init() {
profileCache.setExecutor(Util.backgroundExecutor());
//#endif

reconnect(false, true);

new GatewayFinder(gateway -> {
upnpGateway = gateway;
LOGGER.info("Found UPnP gateway: {}", gateway.getGatewayIP());
Expand Down Expand Up @@ -169,6 +186,54 @@ public static void saveConfig() {
}
}

public static void tickHandler(Minecraft client) {
if (protoClient == null || protoClient.isClosed()) {
protoClient = null;
connectingFuture = null;
final long time = Util.getMillis();
if (time - lastReconnectTime > 10_000) {
lastReconnectTime = time;
if (!attemptingConnection) {
reconnect(CONFIG.isEnableReconnectionToasts(), false);
}
}
}
if (connectingFuture != null && connectingFuture.isDone()) {
connectingFuture = null;
LOGGER.info("Finished authenticating with WS server. Requesting friends list.");
ONLINE_FRIENDS.clear();
protoClient.listOnline(CONFIG.getFriends());
final IntegratedServer server = Minecraft.getInstance().getSingleplayerServer();
if (server != null && server.isPublished()) {
protoClient.publishedWorld(CONFIG.getFriends());
}
}
}

public static void reconnect(boolean successToast, boolean failureToast) {
if (protoClient != null) {
protoClient.close();
protoClient = null;
}
final UUID uuid = Minecraft.getInstance().getUser().getProfileId();
if (uuid == null) {
LOGGER.warn("Failed to get player UUID. Unable to use World Host.");
if (failureToast) {
DeferredToastManager.show(
SystemToast.SystemToastIds.TUTORIAL_HINT,
Components.translatable("world-host.ws_connect.not_available"),
null
);
}
return;
}
attemptingConnection = true;
LOGGER.info("Attempting to connect to WH server at {}", CONFIG.getServerIp());
protoClient = new ProtocolClient(CONFIG.getServerIp());
connectingFuture = protoClient.getConnectingFuture();
protoClient.authenticate(Minecraft.getInstance().getUser().getProfileId());
}

public static String getName(GameProfile profile) {
return getIfBlank(profile.getName(), () -> profile.getId().toString());
}
Expand Down Expand Up @@ -238,4 +303,43 @@ public static void color(float r, float g, float b, float a) {
//#endif
(r, g, b, a);
}

public static boolean isFriend(UUID user) {
return CONFIG.isEnableFriends() && CONFIG.getFriends().contains(user);
}

public static void showProfileToast(UUID user, String title, Component description) {
Util.backgroundExecutor().execute(() -> {
final GameProfile profile = Minecraft.getInstance()
.getMinecraftSessionService()
.fillProfileProperties(new GameProfile(user, null), false);
Minecraft.getInstance().execute(() -> {
final ResourceLocation skinTexture = Minecraft.getInstance().getSkinManager().getInsecureSkinLocation(profile);
DeferredToastManager.show(
SystemToast.SystemToastIds.PERIODIC_NOTIFICATION,
(matrices, x, y) -> {
RenderSystem.setShaderTexture(0, skinTexture);
RenderSystem.enableBlend();
GuiComponent.blit(matrices, x, y, 20, 20, 8, 8, 8, 8, 64, 64);
GuiComponent.blit(matrices, x, y, 20, 20, 40, 8, 8, 8, 64, 64);
},
Components.translatable(title, getName(profile)),
description
);
});
});
}

public static FriendlyByteBuf createByteBuf() {
return new FriendlyByteBuf(Unpooled.buffer());
}

public static ServerStatus parseServerStatus(FriendlyByteBuf buf) {
return new ClientboundStatusResponsePacket(buf)
//#if MC >= 11904
.status();
//#else
//$$ .getStatus();
//#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.UUID;

public class WorldHostConfig {
private String serverIp = "world-host.jemnetworks.com:9646";
private String serverIp = "world-host.jemnetworks.com";

private boolean showOnlineStatus = true;

Expand All @@ -35,6 +35,9 @@ public void read(JsonReader reader) throws IOException {
continue;
}
serverIp = serverUri.substring(index + 3);
if (serverIp.endsWith(":9646")) {
serverIp = serverIp.substring(0, serverIp.length() - 5);
}
}
case "showOnlineStatus" -> showOnlineStatus = reader.nextBoolean();
case "enableFriends" -> enableFriends = reader.nextBoolean();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import net.minecraft.client.gui.components.ObjectSelectionList;
import net.minecraft.client.gui.screens.ConfirmScreen;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
Expand Down Expand Up @@ -53,9 +52,9 @@ protected void init() {
assert minecraft != null;
minecraft.setScreen(new AddFriendScreen(this, ADD_FRIEND_TEXT, profile -> {
addFriend(profile);
// if (WorldHost.wsClient != null) {
// WorldHost.wsClient.friendRequest(profile.getId());
// }
if (WorldHost.protoClient != null) {
WorldHost.protoClient.friendRequest(profile.getId());
}
}));
}).pos(width / 2 - 152, height - 52)
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ public class WorldHostConfigScreen extends WorldHostScreen {
private final Screen parent;

private final String oldServerIp;
private final boolean oldEnableFriends;
private EditBox serverIpBox;

public WorldHostConfigScreen(Screen parent) {
super(TITLE);
oldServerIp = WorldHost.CONFIG.getServerIp();
oldEnableFriends = WorldHost.CONFIG.isEnableFriends();
this.parent = parent;
}

Expand Down Expand Up @@ -102,12 +104,18 @@ public void render(@NotNull PoseStack poseStack, int mouseX, int mouseY, float p
}

@Override
public void onClose() {
super.onClose();
public void removed() {
if (!serverIpBox.getValue().equals(oldServerIp)) {
WorldHost.CONFIG.setServerIp(serverIpBox.getValue());
WorldHost.saveConfig();
// TODO: Perform reconnect
WorldHost.reconnect(true, true);
} else if (
oldEnableFriends &&
!WorldHost.CONFIG.isEnableFriends() &&
WorldHost.protoClient != null &&
!WorldHost.protoClient.isClosed()
) {
WorldHost.protoClient.closedWorld(WorldHost.CONFIG.getFriends());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.github.gaming32.worldhost.mixin;

import io.github.gaming32.worldhost.DeferredToastManager;
import io.github.gaming32.worldhost.WorldHost;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Overlay;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(Minecraft.class)
public class MixinMinecraft {
@Inject(method = "setOverlay", at = @At("HEAD"))
private void deferredToastReady(Overlay loadingGui, CallbackInfo ci) {
if (loadingGui == null) {
DeferredToastManager.ready();
}
}

@Inject(method = "tick", at = @At("RETURN"))
private void tickEvent(CallbackInfo ci) {
//noinspection DataFlowIssue
WorldHost.tickHandler((Minecraft)(Object)this);
}
}
25 changes: 25 additions & 0 deletions src/main/java/io/github/gaming32/worldhost/protocol/JoinType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.github.gaming32.worldhost.protocol;

import java.io.DataOutputStream;
import java.io.IOException;

public sealed interface JoinType {
record UPnP(int port) implements JoinType {
@Override
public void encode(DataOutputStream dos) throws IOException {
dos.writeByte(0);
dos.writeShort(port);
}
}

enum Proxy implements JoinType {
INSTANCE;

@Override
public void encode(DataOutputStream dos) throws IOException {
dos.writeByte(1);
}
}

void encode(DataOutputStream dos) throws IOException;
}
Loading

0 comments on commit c4baa0f

Please sign in to comment.