Removed debug, fixed mod handling

This commit is contained in:
Verox001 2025-05-14 19:37:23 +02:00
parent f9e78d96e9
commit 2f7bc1de7f
2 changed files with 68 additions and 49 deletions

View File

@ -4,40 +4,26 @@ import com.google.common.reflect.TypeToken;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.mojang.logging.LogUtils; import com.mojang.logging.LogUtils;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.CreativeModeTabs;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.MapColor;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ClientPlayerNetworkEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.BuildCreativeModeTabContentsEvent; import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.forgespi.language.IModInfo; import net.minecraftforge.forgespi.language.IModInfo;
import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.network.simple.SimpleChannel;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -48,16 +34,15 @@ import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.HashMap; import java.util.*;
import java.util.Map; import java.util.concurrent.ConcurrentHashMap;
import java.util.Optional;
@Mod(Ezcheat.MODID) @Mod(Ezcheat.MODID)
public class Ezcheat { public class Ezcheat {
public static final String MODID = "ezcheat"; public static final String MODID = "ezcheat";
static final Logger LOGGER = LogUtils.getLogger();
// Directly reference a slf4j logger public static final Set<UUID> receivedModHashFrom = ConcurrentHashMap.newKeySet();
private static final Logger LOGGER = LogUtils.getLogger(); public static final Map<UUID, Long> pendingModCheck = new ConcurrentHashMap<>();
public static final String PROTOCOL_VERSION = "1"; public static final String PROTOCOL_VERSION = "1";
public static final SimpleChannel NETWORK = NetworkRegistry.newSimpleChannel( public static final SimpleChannel NETWORK = NetworkRegistry.newSimpleChannel(
@ -68,23 +53,28 @@ public class Ezcheat {
public static Map<String, String> getInstalledModHashes() { public static Map<String, String> getInstalledModHashes() {
Map<String, String> modHashes = new HashMap<>(); Map<String, String> modHashes = new HashMap<>();
Path modsDir = Path.of("mods").toAbsolutePath().normalize();
for (IModInfo mod : ModList.get().getMods()) { for (IModInfo mod : ModList.get().getMods()) {
Optional<Path> modFile = Optional.ofNullable(mod.getOwningFile().getFile().getFilePath()); Optional<Path> modFileOpt = Optional.ofNullable(mod.getOwningFile().getFile().getFilePath());
modFile.ifPresent(path -> { if (modFileOpt.isEmpty()) continue;
try (InputStream in = Files.newInputStream(path)) {
String hash = DigestUtils.sha256Hex(in); // Apache Commons Codec Path modFile = modFileOpt.get().toAbsolutePath().normalize();
modHashes.put(mod.getModId(), hash);
} catch (IOException e) { if (!modFile.startsWith(modsDir)) continue;
LOGGER.error("Failed to read mod file for {}: {}", mod.getModId(), e.getMessage());
} try (InputStream in = Files.newInputStream(modFile)) {
}); String hash = DigestUtils.sha256Hex(in);
modHashes.put(hash, mod.getModId());
} catch (IOException e) {
LOGGER.error("Failed to read mod file for {}: {}", mod.getModId(), e.getMessage());
}
} }
return modHashes; return modHashes;
} }
public static void handlePlayerModHashes(ServerPlayer player, Map<String, String> modHashes) { public static void handlePlayerModHashes(ServerPlayer player, Map<String, String> modHashes) {
// Request an external whitelist
MinecraftServer server = player.getServer(); MinecraftServer server = player.getServer();
if (server == null) return; if (server == null) return;
@ -112,19 +102,21 @@ public class Ezcheat {
} }
} }
if (!unallowedMods.isEmpty()) { String message = unallowedMods.toString();
unallowedMods.setLength(unallowedMods.length() - 2); // Remove last comma and space if (!message.equals("Unallowed mods: ")) {
player.connection.disconnect(Component.literal(unallowedMods.toString())); player.connection.disconnect(Component.literal(message.substring(0, message.length() - 2)));
} }
receivedModHashFrom.add(player.getUUID());
pendingModCheck.remove(player.getUUID());
} catch (IOException e) { } catch (IOException e) {
Ezcheat.LOGGER.error("Modprüfung fehlgeschlagen", e); LOGGER.error("Failed Mod verification", e);
} }
}); });
} }
public Ezcheat() { public Ezcheat() {
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.SPEC); ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.SPEC);
NETWORK.registerMessage(0, ModHashesPacket.class, NETWORK.registerMessage(0, ModHashesPacket.class,
ModHashesPacket::encode, ModHashesPacket::encode,
ModHashesPacket::decode, ModHashesPacket::decode,
@ -132,24 +124,50 @@ public class Ezcheat {
); );
} }
// You can use SubscribeEvent and let the Event Bus discover methods to call @Mod.EventBusSubscriber(modid = Ezcheat.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT)
@SubscribeEvent public static class ClientModEvents {
public void onServerStarting(ServerStartingEvent event) { @SubscribeEvent
public static void onPlayerJoinedServer(ClientPlayerNetworkEvent.LoggingIn event) {
Map<String, String> modHashes = Ezcheat.getInstalledModHashes();
Ezcheat.NETWORK.sendToServer(new ModHashesPacket(modHashes));
}
} }
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent @Mod.EventBusSubscriber(modid = Ezcheat.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE)
@Mod.EventBusSubscriber(modid = MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) public static class ServerEvents {
public static class ClientModEvents { @SubscribeEvent
public static void onPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) {
if (event.getEntity() instanceof ServerPlayer player) {
pendingModCheck.put(player.getUUID(), System.currentTimeMillis());
}
}
@SubscribeEvent @SubscribeEvent
public static void onClientSetup(FMLClientSetupEvent event) { public static void onServerTick(TickEvent.ServerTickEvent event) {
event.enqueueWork(() -> { if (event.phase != TickEvent.Phase.END) return;
if (Minecraft.getInstance().getConnection() != null) {
Map<String, String> modHashes = Ezcheat.getInstalledModHashes(); long now = System.currentTimeMillis();
Ezcheat.NETWORK.sendToServer(new ModHashesPacket(modHashes)); pendingModCheck.entrySet().removeIf(entry -> {
UUID uuid = entry.getKey();
long joinedAt = entry.getValue();
if (now - joinedAt > 10000) {
ServerPlayer player = getPlayerByUUID(uuid);
if (player != null) {
player.connection.disconnect(Component.literal("You must have Ezcheat installed."));
LOGGER.info("Kicked {} for not sending mod hashes in time", player.getName().getString());
}
return true;
} }
return false;
}); });
} }
private static ServerPlayer getPlayerByUUID(UUID uuid) {
MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer();
return server.getPlayerList().getPlayer(uuid);
}
} }
} }

View File

@ -6,6 +6,7 @@ import net.minecraftforge.network.NetworkEvent;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier; import java.util.function.Supplier;
public class ModHashesPacket { public class ModHashesPacket {