156 lines
6.3 KiB
Java
Raw Normal View History

2025-05-10 23:05:51 +02:00
package com.cimeyclust.ezcheat;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
2025-05-10 23:05:51 +02:00
import com.mojang.logging.LogUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
2025-05-10 23:05:51 +02:00
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.common.MinecraftForge;
import net.minecraftforge.event.BuildCreativeModeTabContentsEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModList;
2025-05-10 23:05:51 +02:00
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.forgespi.language.IModInfo;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.simple.SimpleChannel;
2025-05-10 23:05:51 +02:00
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import org.apache.commons.codec.digest.DigestUtils;
2025-05-10 23:05:51 +02:00
import org.slf4j.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
2025-05-10 23:05:51 +02:00
@Mod(Ezcheat.MODID)
public class Ezcheat {
public static final String MODID = "ezcheat";
2025-05-10 23:05:51 +02:00
// Directly reference a slf4j logger
private static final Logger LOGGER = LogUtils.getLogger();
public static final String PROTOCOL_VERSION = "1";
public static final SimpleChannel NETWORK = NetworkRegistry.newSimpleChannel(
new ResourceLocation(MODID, "main"),
() -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals
);
public static Map<String, String> getInstalledModHashes() {
Map<String, String> modHashes = new HashMap<>();
for (IModInfo mod : ModList.get().getMods()) {
Optional<Path> modFile = Optional.ofNullable(mod.getOwningFile().getFile().getFilePath());
modFile.ifPresent(path -> {
try (InputStream in = Files.newInputStream(path)) {
String hash = DigestUtils.sha256Hex(in); // Apache Commons Codec
modHashes.put(mod.getModId(), hash);
} catch (IOException e) {
LOGGER.error("Failed to read mod file for {}: {}", mod.getModId(), e.getMessage());
}
});
}
2025-05-10 23:05:51 +02:00
return modHashes;
2025-05-10 23:05:51 +02:00
}
public static void handlePlayerModHashes(ServerPlayer player, Map<String, String> modHashes) {
// Request an external whitelist
MinecraftServer server = player.getServer();
if (server == null) return;
server.execute(() -> {
try {
URL url = new URL(Config.modEndpointUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
InputStream in = conn.getInputStream();
String response = new String(in.readAllBytes());
in.close();
Gson gson = new Gson();
Type type = new TypeToken<Map<String, String>>() {}.getType();
Map<String, String> allowedMods = gson.fromJson(response, type);
StringBuilder unallowedMods = new StringBuilder("Unallowed mods: ");
for (Map.Entry<String, String> entry : modHashes.entrySet()) {
String modid = entry.getKey();
String hash = entry.getValue();
if (!allowedMods.containsKey(modid) || !allowedMods.get(modid).equalsIgnoreCase(hash)) {
unallowedMods.append(modid).append(", ");
}
}
if (!unallowedMods.isEmpty()) {
unallowedMods.setLength(unallowedMods.length() - 2); // Remove last comma and space
player.connection.disconnect(Component.literal(unallowedMods.toString()));
}
} catch (IOException e) {
Ezcheat.LOGGER.error("Modprüfung fehlgeschlagen", e);
}
});
2025-05-10 23:05:51 +02:00
}
public Ezcheat() {
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.SPEC);
NETWORK.registerMessage(0, ModHashesPacket.class,
ModHashesPacket::encode,
ModHashesPacket::decode,
ModHashesPacket::handle
);
2025-05-10 23:05:51 +02:00
}
// You can use SubscribeEvent and let the Event Bus discover methods to call
@SubscribeEvent
public void onServerStarting(ServerStartingEvent event) {
2025-05-10 23:05:51 +02:00
}
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
@Mod.EventBusSubscriber(modid = MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
public static class ClientModEvents {
@SubscribeEvent
public static void onClientSetup(FMLClientSetupEvent event) {
event.enqueueWork(() -> {
if (Minecraft.getInstance().getConnection() != null) {
Map<String, String> modHashes = Ezcheat.getInstalledModHashes();
Ezcheat.NETWORK.sendToServer(new ModHashesPacket(modHashes));
}
});
2025-05-10 23:05:51 +02:00
}
}
}