|
| 1 | +package net.modificationstation.stationapi.impl.server.network; |
| 2 | + |
| 3 | +import net.fabricmc.loader.api.FabricLoader; |
| 4 | +import net.fabricmc.loader.api.ModContainer; |
| 5 | +import net.fabricmc.loader.api.metadata.ModMetadata; |
| 6 | +import net.mine_diver.unsafeevents.listener.EventListener; |
| 7 | +import net.minecraft.client.resource.language.I18n; |
| 8 | +import net.minecraft.entity.player.ServerPlayerEntity; |
| 9 | +import net.modificationstation.stationapi.api.StationAPI; |
| 10 | +import net.modificationstation.stationapi.api.event.registry.MessageListenerRegistryEvent; |
| 11 | +import net.modificationstation.stationapi.api.mod.entrypoint.Entrypoint; |
| 12 | +import net.modificationstation.stationapi.api.mod.entrypoint.EntrypointManager; |
| 13 | +import net.modificationstation.stationapi.api.mod.entrypoint.EventBusPolicy; |
| 14 | +import net.modificationstation.stationapi.api.server.event.network.PlayerAttemptLoginEvent; |
| 15 | +import net.modificationstation.stationapi.impl.network.ModdedPacketHandlerSetter; |
| 16 | + |
| 17 | +import java.lang.invoke.MethodHandles; |
| 18 | +import java.util.HashMap; |
| 19 | +import java.util.Map; |
| 20 | +import java.util.stream.Collectors; |
| 21 | + |
| 22 | +import static net.modificationstation.stationapi.api.StationAPI.LOGGER; |
| 23 | +import static net.modificationstation.stationapi.api.StationAPI.NAMESPACE; |
| 24 | +import static net.modificationstation.stationapi.impl.network.VanillaChecker.CLIENT_REQUIRED_MODS; |
| 25 | +import static net.modificationstation.stationapi.impl.network.VanillaChecker.MASK; |
| 26 | + |
| 27 | +@Entrypoint(eventBus = @EventBusPolicy(registerInstance = false)) |
| 28 | +@EventListener(phase = StationAPI.INTERNAL_PHASE) |
| 29 | +public class ServerVanillaChecker { |
| 30 | + static { |
| 31 | + EntrypointManager.registerLookup(MethodHandles.lookup()); |
| 32 | + } |
| 33 | + |
| 34 | + @EventListener |
| 35 | + private static void onPlayerLogin(PlayerAttemptLoginEvent event) { |
| 36 | + if ((event.loginHelloPacket.worldSeed & MASK) == MASK) { |
| 37 | + Map<String, String> mods = new HashMap<>(); |
| 38 | + FabricLoader.getInstance().getAllMods().forEach(modContainer -> mods.put(modContainer.getMetadata().getId(), modContainer.getMetadata().getVersion().getFriendlyString())); |
| 39 | + ((ModdedPacketHandlerSetter) event.serverLoginNetworkHandler).setModded(mods); |
| 40 | + } |
| 41 | + else if (!CLIENT_REQUIRED_MODS.isEmpty()) { |
| 42 | + LOGGER.error("Player \"" + event.loginHelloPacket.username + "\" attempted joining the server without " + NAMESPACE.getName() + ", disconnecting."); |
| 43 | + event.serverLoginNetworkHandler.disconnect(I18n.getTranslation("disconnect." + NAMESPACE + ".missingStation")); |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + @EventListener |
| 48 | + private static void registerMessages(MessageListenerRegistryEvent event) { |
| 49 | + event.register(NAMESPACE.id("modlist"), (player, message) -> { |
| 50 | + if (!CLIENT_REQUIRED_MODS.isEmpty()) { |
| 51 | + LOGGER.info("Received a list of mods from player \"" + player.name + "\", verifying..."); |
| 52 | + ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player; |
| 53 | + String version = message.strings[0]; |
| 54 | + String serverStationVersion = NAMESPACE.getVersion().getFriendlyString(); |
| 55 | + if (!version.equals(serverStationVersion)) { |
| 56 | + LOGGER.error("Player \"" + player.name + "\" has a mismatching " + NAMESPACE.getName() + " version \"" + version + "\", disconnecting."); |
| 57 | + serverPlayer.field_255.method_833(I18n.getTranslation("disconnect." + NAMESPACE + ".stationVersionMismatch", serverStationVersion, version)); |
| 58 | + return; |
| 59 | + } |
| 60 | + Map<String, String> clientMods = new HashMap<>(); |
| 61 | + for (int i = 1; i < message.strings.length; i += 2) |
| 62 | + clientMods.put(message.strings[i], message.strings[i + 1]); |
| 63 | + LOGGER.info("Player \"" + player.name + "\"'s mods: " + clientMods.entrySet().stream().map(stringStringEntry -> "modid=" + stringStringEntry.getKey() + " version=" + stringStringEntry.getValue()).collect(Collectors.joining(", ", "[", "]"))); |
| 64 | + String modid; |
| 65 | + String clientVersion; |
| 66 | + String serverVersion; |
| 67 | + for (ModContainer serverMod : CLIENT_REQUIRED_MODS) { |
| 68 | + ModMetadata modMetadata = serverMod.getMetadata(); |
| 69 | + modid = modMetadata.getId(); |
| 70 | + serverVersion = modMetadata.getVersion().getFriendlyString(); |
| 71 | + if (clientMods.containsKey(modid)) { |
| 72 | + clientVersion = clientMods.get(modid); |
| 73 | + if (clientVersion == null || !clientVersion.equals(serverVersion)) { |
| 74 | + LOGGER.error("Player \"" + player.name + "\" has a mismatching " + modMetadata.getName() + " (" + modid + ")" + " version \"" + clientVersion + "\", disconnecting."); |
| 75 | + serverPlayer.field_255.method_833(I18n.getTranslation("disconnect." + NAMESPACE + ".modVersionMismatch", modMetadata.getName(), modid, serverVersion, clientVersion == null ? "null" : clientVersion)); |
| 76 | + return; |
| 77 | + } |
| 78 | + } else { |
| 79 | + LOGGER.error("Player \"" + player.name + "\" has a missing mod " + modMetadata.getName() + " (" + modid + "), disconnecting."); |
| 80 | + serverPlayer.field_255.method_833(I18n.getTranslation("disconnect." + NAMESPACE + ".missingMod", modMetadata.getName(), modid, serverVersion)); |
| 81 | + return; |
| 82 | + } |
| 83 | + } |
| 84 | + LOGGER.info("Player \"" + player.name + "\"'s mods have passed verification."); |
| 85 | + } |
| 86 | + }); |
| 87 | + } |
| 88 | +} |
0 commit comments