From ac96b1a4019957da9d70ca4cf67f0da38dbe3065 Mon Sep 17 00:00:00 2001
From: Dennisbonke <dennisb@kabelfoon.net>
Date: Wed, 15 Apr 2015 12:35:02 +0200
Subject: [PATCH] Added environment checks, IMC Handlers and obfuscation utils.
 Updated error messages, bumped version to 0.2.1B4.

---
 VERSION                                       |   2 +-
 build.gradle                                  |   2 +-
 .../java/com/advancedmods/amcore/AMCore.java  | 107 +++++++++--
 .../advancedmods/amcore/core/AMCoreProps.java |   2 +-
 .../amcore/core/environment/CheckEnv.java     |  27 ---
 .../core/environment/EnviromentChecks.java    |  76 ++++++++
 .../amcore/core/environment/IMCHandler.java   |  21 +++
 .../amcore/core/environment/ObfUtil.java      | 169 ++++++++++++++++++
 8 files changed, 366 insertions(+), 40 deletions(-)
 delete mode 100644 src/main/java/com/advancedmods/amcore/core/environment/CheckEnv.java
 create mode 100644 src/main/java/com/advancedmods/amcore/core/environment/EnviromentChecks.java
 create mode 100644 src/main/java/com/advancedmods/amcore/core/environment/IMCHandler.java
 create mode 100644 src/main/java/com/advancedmods/amcore/core/environment/ObfUtil.java

diff --git a/VERSION b/VERSION
index fc4e8f2..11f40b6 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.7.10R0.2.1B3 Beta 3! Updated the Update Checker and added Tooltips.
\ No newline at end of file
+1.7.10R0.2.1B4 Beta 4! Now with better environment checks!.
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index f19527f..c216faa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -30,7 +30,7 @@ else
     println "!! No build number set !!"
 }
 
-version = "1.7.10-0.2.1-B3" + "-" + project.buildnumber
+version = "1.7.10-0.2.1-B4" + "-" + project.buildnumber
 group= "com.advancedmods.amcore" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
 archivesBaseName = "AMCore"
 
diff --git a/src/main/java/com/advancedmods/amcore/AMCore.java b/src/main/java/com/advancedmods/amcore/AMCore.java
index 44ee427..cf6c0e6 100644
--- a/src/main/java/com/advancedmods/amcore/AMCore.java
+++ b/src/main/java/com/advancedmods/amcore/AMCore.java
@@ -4,7 +4,8 @@ import com.advancedmods.amcore.common.CommonPlayerTracker;
 import com.advancedmods.amcore.common.CommonProxy;
 import com.advancedmods.amcore.common.handler.ConfigurationHandler;
 import com.advancedmods.amcore.core.AMCoreProps;
-import com.advancedmods.amcore.core.environment.CheckEnv;
+import com.advancedmods.amcore.core.environment.EnviromentChecks;
+import com.advancedmods.amcore.core.environment.IMCHandler;
 import com.advancedmods.amcore.core.mod.BaseMod;
 import com.advancedmods.amcore.core.mod.updater.UpdateManager;
 import cpw.mods.fml.common.FMLCommonHandler;
@@ -13,6 +14,8 @@ import cpw.mods.fml.common.Mod.EventHandler;
 import cpw.mods.fml.common.Mod.Instance;
 import cpw.mods.fml.common.SidedProxy;
 import cpw.mods.fml.common.event.FMLInitializationEvent;
+import cpw.mods.fml.common.event.FMLInterModComms;
+import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
 import cpw.mods.fml.common.event.FMLPostInitializationEvent;
 import cpw.mods.fml.common.event.FMLPreInitializationEvent;
 import org.apache.logging.log4j.LogManager;
@@ -33,6 +36,7 @@ public class AMCore extends BaseMod {
     @SidedProxy(clientSide = AMCoreProps.clientproxy, serverSide = AMCoreProps.commonproxy)
     public static CommonProxy proxy;
     public static Logger log = LogManager.getLogger("AMCore");
+    public static final String issueURL = "https://github.com/AdvancedMods/AMCore/issues";
     public static final String updateURL = "https://raw.github.com/AdvancedMods/AMCore/master/VERSION";
     public static final String downloadURL = "http://ci.zsinfo.nl/job/AMCore/lastSuccessfulBuild/";
     public static ConfigurationHandler config;
@@ -42,14 +46,49 @@ public class AMCore extends BaseMod {
 
         log.info("Starting AMCore version: " + AMCoreProps.version + "...");
         log.info("Entering Pre-Init...");
+        // MC Version check
         log.debug("Checking MC version...");
-        CheckEnv.checkMCVersion();
+        EnviromentChecks.checkMCVersion();
+        // Optifine check
+        try {
+            EnviromentChecks.log.info("Checking if optifine is installed...");
+            EnviromentChecks.checkOptifine();
+            EnviromentChecks.log.info("Check complete");
+        } catch (Exception e) {
+            EnviromentChecks.log.warn("=============================WARNING!=============================");
+            EnviromentChecks.log.warn("Failed to check for optifine, assuming not installed");
+            EnviromentChecks.log.warn("Bug reports may not be complete!");
+            EnviromentChecks.log.warn("Please report this as a bug report with the stacktrace, the minecraft log, a mod list + version and if you have optifine installed to: " + issueURL);
+            EnviromentChecks.log.warn("=============================WARNING!=============================");
+            e.printStackTrace();
+        }
+        // Obfuscation check
+        try {
+            EnviromentChecks.log.info("Checking if we are in a deobfuscated environment...");
+            EnviromentChecks.checkDeobf();
+            EnviromentChecks.log.info("Check complete");
+        } catch (Exception e) {
+            EnviromentChecks.log.error("=============================ERROR!=============================");
+            EnviromentChecks.log.error("Failed to check obfuscation, assuming we are in a normal enviroment.");
+            EnviromentChecks.log.error("This is a severe error and should be investigated ASAP!");
+            EnviromentChecks.log.error("Please report this as a bug report with the stacktrace, the minecraft log and a mod list + version to: " + issueURL);
+            EnviromentChecks.log.error("=============================ERROR!=============================");
+            e.printStackTrace();
+        }
         // Do PreInit stuff
         // Load the config
-        log.info("Loading config...");
-        ConfigurationHandler.init(event.getSuggestedConfigurationFile());
-        FMLCommonHandler.instance().bus().register(new ConfigurationHandler());
-        log.info("Config loaded");
+        try {
+            log.info("Loading config...");
+            ConfigurationHandler.init(event.getSuggestedConfigurationFile());
+            FMLCommonHandler.instance().bus().register(new ConfigurationHandler());
+            log.info("Config loaded");
+        } catch (Exception e) {
+            log.error("=============================ERROR!=============================");
+            log.error("Failed to load the config, printing stacktrace and using default values...");
+            log.error("Please report this as a bug report with the stacktrace, the minecraft log and a mod list + version to: " + issueURL);
+            log.error("=============================ERROR!=============================");
+            e.printStackTrace();
+        }
         // Loading mod stuff
         // Checking for updated version
         if (config.enableUpdateChecker) {
@@ -58,7 +97,10 @@ public class AMCore extends BaseMod {
                 UpdateManager.registerUpdater(new UpdateManager(this, updateURL, downloadURL));
                 log.info("Update Checker for AMCore started");
             } catch (Exception e) {
+                log.error("=============================ERROR!=============================");
                 log.error("Failed to start the update checker, printing stacktrace...");
+                log.error("Please report this as a bug report with the stacktrace, the minecraft log and a mod list + version to: " + issueURL);
+                log.error("=============================ERROR!=============================");
                 e.printStackTrace();
             }
         } else if (!config.enableUpdateChecker) {
@@ -68,14 +110,25 @@ public class AMCore extends BaseMod {
             try {
                 UpdateManager.registerUpdater(new UpdateManager(this, updateURL, downloadURL));
             } catch (Exception e) {
+                log.error("=============================ERROR!=============================");
                 log.error("Failed to start the update checker, printing stacktrace...");
+                log.error("Please report this as a bug report with the stacktrace, the minecraft log and a mod list + version to: " + issueURL);
+                log.error("=============================ERROR!=============================");
                 e.printStackTrace();
             }
         }
-        log.info("Registering trackers...");
-        FMLCommonHandler.instance().bus().register(new CommonPlayerTracker());
-        proxy.loadTracker();
-        log.info("Trackers Registered");
+        try {
+            log.info("Registering trackers...");
+            FMLCommonHandler.instance().bus().register(new CommonPlayerTracker());
+            proxy.loadTracker();
+            log.info("Trackers Registered");
+        } catch (Exception e) {
+            log.error("=============================ERROR!=============================");
+            log.error("Failed to register the trackers, printing stacktrace...");
+            log.error("Please report this as a bug report with the stacktrace, the minecraft log and a mod list + version to: " + issueURL);
+            log.error("=============================ERROR!=============================");
+            e.printStackTrace();
+        }
         log.info("Pre-Init Finished");
 
     }
@@ -99,6 +152,40 @@ public class AMCore extends BaseMod {
 
     }
 
+    @EventHandler
+    public void handleIMC(FMLInterModComms.IMCEvent event) {
+
+        // IMCHandler
+        try {
+            log.info("Processing IMC messages...");
+            IMCHandler.processIMC(event.getMessages());
+            log.info("IMC Messages processed.");
+        } catch (Exception e) {
+            log.error("=============================ERROR!=============================");
+            log.error("Failed to process IMC Messages, printing stacktrace...");
+            log.error("Please report this as a bug report with the stacktrace, the minecraft log and a mod list + version to: " + issueURL);
+            log.error("=============================ERROR!=============================");
+            e.printStackTrace();
+        }
+    }
+
+    @EventHandler
+    public void loadComplete(FMLLoadCompleteEvent event) {
+
+        // Fetching runtime messages
+        try {
+            log.info("Fetching runtime IMC messages...");
+            IMCHandler.processIMC(FMLInterModComms.fetchRuntimeMessages(this));
+            log.info("Fetched runtime IMC messages.");
+        } catch (Exception e) {
+            log.error("=============================ERROR!=============================");
+            log.error("Failed to fetch IMC Runtime messages, printing stacktrace...");
+            log.error("Please report this as a bug report with the stacktrace, the minecraft log and a mod list + version to: " + issueURL);
+            log.error("=============================ERROR!=============================");
+            e.printStackTrace();
+        }
+    }
+
     @Override
     public String getModId() {
         return AMCoreProps.modid;
diff --git a/src/main/java/com/advancedmods/amcore/core/AMCoreProps.java b/src/main/java/com/advancedmods/amcore/core/AMCoreProps.java
index 68ea857..b7e4cba 100644
--- a/src/main/java/com/advancedmods/amcore/core/AMCoreProps.java
+++ b/src/main/java/com/advancedmods/amcore/core/AMCoreProps.java
@@ -14,7 +14,7 @@ public class AMCoreProps {
     public static final String REQUIRED_FORGE_BASE = "10.13.2.1240";
     public static final String FORGE_VERSION = "[" + REQUIRED_FORGE_BASE + "]";
     public static final String VERSION_BASE = "R0.2.1";
-    public static final String VERSION_IDENTIFIER = "B3";
+    public static final String VERSION_IDENTIFIER = "B4";
     public static final String VERSION_COMPLETE = MC_VERSION + VERSION_BASE + VERSION_IDENTIFIER;
 
     // General Mod Stuff
diff --git a/src/main/java/com/advancedmods/amcore/core/environment/CheckEnv.java b/src/main/java/com/advancedmods/amcore/core/environment/CheckEnv.java
deleted file mode 100644
index 1f8003e..0000000
--- a/src/main/java/com/advancedmods/amcore/core/environment/CheckEnv.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.advancedmods.amcore.core.environment;
-
-import com.advancedmods.amcore.AMCore;
-import com.advancedmods.amcore.core.AMCoreProps;
-import cpw.mods.fml.common.FMLLog;
-import cpw.mods.fml.common.Loader;
-
-/**
- * Environment checker for AMCore
- * Created by Dennisbonke on 9-2-2015.
- *
- * @author Dennis Bonke
- * @since 0.2.0B1
- */
-public class CheckEnv {
-
-    public static void checkMCVersion() {
-
-        if (Loader.MC_VERSION == AMCoreProps.MC_VERSION) {
-            AMCore.log.trace("Using MC Version 1.7.10, proceed");
-        } else {
-            FMLLog.severe("Not using MC version 1.7.10, aborting");
-            System.gc();
-            System.exit(-1);
-        }
-    }
-}
diff --git a/src/main/java/com/advancedmods/amcore/core/environment/EnviromentChecks.java b/src/main/java/com/advancedmods/amcore/core/environment/EnviromentChecks.java
new file mode 100644
index 0000000..9afb097
--- /dev/null
+++ b/src/main/java/com/advancedmods/amcore/core/environment/EnviromentChecks.java
@@ -0,0 +1,76 @@
+package com.advancedmods.amcore.core.environment;
+
+import com.advancedmods.amcore.core.AMCoreProps;
+import cpw.mods.fml.client.FMLClientHandler;
+import cpw.mods.fml.common.FMLCommonHandler;
+import cpw.mods.fml.common.FMLLog;
+import cpw.mods.fml.common.Loader;
+import cpw.mods.fml.relauncher.Side;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * Environment checker for AMCore
+ * Created by Dennisbonke on 9-2-2015.
+ *
+ * @author Dennis Bonke
+ * @since 0.2.0B1
+ */
+public class EnviromentChecks {
+
+    public static boolean hasOptifine;
+    protected static boolean isDeobf;
+    public static Logger log = LogManager.getLogger("AM-Enviroment");
+    public static final String issueURL = "https://github.com/AdvancedMods/AMCore/issues";
+
+    public static void checkOptifine()
+    {
+        try {
+            if ((FMLCommonHandler.instance().getSidedDelegate().getSide() == Side.CLIENT) && ((FMLClientHandler.instance().hasOptifine()) || (Loader.isModLoaded("optifine")))) {
+                hasOptifine = true;
+                log.warn("Optifine has been detected on your Minecraft installation, this can cause (rendering) issues");
+            } else {
+                hasOptifine = false;
+            }
+        } catch (Exception e) {
+            log.warn("=============================WARNING!=============================");
+            log.warn("Failed to check for optifine, assuming not installed");
+            log.warn("Bug reports may not be complete!");
+            log.warn("Please report this as a bug report with the stacktrace, the minecraft log, a mod list + version and if you have optifine installed to: " + issueURL);
+            log.warn("=============================WARNING!=============================");
+            e.printStackTrace();
+            hasOptifine = false;
+        }
+    }
+
+    public static void checkDeobf() {
+
+        try {
+            if (ObfUtil.isObf() == true) {
+                isDeobf = true;
+            } else {
+                isDeobf = false;
+            }
+        } catch (Exception e) {
+            log.error("=============================ERROR!=============================");
+            log.error("Failed to check obfuscation, assuming we are in a normal enviroment.");
+            log.error("This is a severe error and should be investigated ASAP!");
+            log.error("Please report this as a bug report with the stacktrace, the minecraft log and a mod list + version to: " + issueURL);
+            log.error("=============================ERROR!=============================");
+            e.printStackTrace();
+            isDeobf = false;
+        }
+    }
+
+    public static void checkMCVersion() {
+
+        if (Loader.MC_VERSION == AMCoreProps.MC_VERSION) {
+            log.trace("Using MC Version 1.7.10, proceed");
+        } else {
+            FMLLog.log(Level.FATAL, "Not using MC version 1.7.10, aborting");
+            System.gc();
+            System.exit(-1);
+        }
+    }
+}
diff --git a/src/main/java/com/advancedmods/amcore/core/environment/IMCHandler.java b/src/main/java/com/advancedmods/amcore/core/environment/IMCHandler.java
new file mode 100644
index 0000000..79f5aa7
--- /dev/null
+++ b/src/main/java/com/advancedmods/amcore/core/environment/IMCHandler.java
@@ -0,0 +1,21 @@
+package com.advancedmods.amcore.core.environment;
+
+import cpw.mods.fml.common.event.FMLInterModComms;
+
+import java.util.List;
+
+/**
+ * Created by Dennisbonke on 15-4-2015.
+ */
+public final class IMCHandler {
+
+    public static void processIMC(List<FMLInterModComms.IMCMessage> messages)
+    {
+        for (FMLInterModComms.IMCMessage message : messages)
+        {
+            String type = message.key;
+            if ((type == null) || (type.isEmpty())) {}
+        }
+    }
+
+}
diff --git a/src/main/java/com/advancedmods/amcore/core/environment/ObfUtil.java b/src/main/java/com/advancedmods/amcore/core/environment/ObfUtil.java
new file mode 100644
index 0000000..e4ea03a
--- /dev/null
+++ b/src/main/java/com/advancedmods/amcore/core/environment/ObfUtil.java
@@ -0,0 +1,169 @@
+package com.advancedmods.amcore.core.environment;
+
+import cpw.mods.fml.relauncher.ReflectionHelper;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * Created by Dennisbonke on 15-4-2015.
+ */
+public class ObfUtil {
+
+    public static boolean isObf()
+    {
+        try
+        {
+            Field[] fields = Class.forName("net.minecraft.world.World").getDeclaredFields();
+            for (Field f : fields)
+            {
+                f.setAccessible(true);
+                if (f.getName().equalsIgnoreCase("loadedEntityList")) {
+                    return false;
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            return true;
+        }
+        return true;
+    }
+
+    public static boolean isFieldAccessible(Class<?> clazz, String... names)
+    {
+        try
+        {
+            Field[] fields = clazz.getDeclaredFields();
+            for (Field field : fields) {
+                for (String fieldName : names) {
+                    if (field.getName().equalsIgnoreCase(fieldName)) {
+                        return field.isAccessible();
+                    }
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            throw new ReflectionHelper.UnableToFindFieldException(names, e);
+        }
+        return false;
+    }
+
+    public static void setFieldAccessible(Class<?> clazz, String... names)
+    {
+        try
+        {
+            Field field = getField(clazz, names);
+            if (field != null) {
+                field.setAccessible(true);
+            }
+        }
+        catch (Exception e) {}
+    }
+
+    public static <T, E> void setFieldValue(Class<? extends E> clazz, E instance, Object value, String... names)
+    {
+        try
+        {
+            Field field = getField(clazz, names);
+            if (field != null) {
+                field.set(instance, value);
+            }
+        }
+        catch (Exception e) {}
+    }
+
+    public static <T, E> T getFieldValue(Class<? extends E> clazz, E instance, String... names)
+    {
+        try
+        {
+            return (T)getField(clazz, names).get(instance);
+        }
+        catch (Exception e)
+        {
+            throw new ReflectionHelper.UnableToAccessFieldException(names, e);
+        }
+    }
+
+    public static Field getField(Class<?> clazz, String... names)
+    {
+        try
+        {
+            Field[] fields = clazz.getDeclaredFields();
+            for (Field field : fields) {
+                for (String fieldName : names) {
+                    if (field.getName().equalsIgnoreCase(fieldName))
+                    {
+                        field.setAccessible(true);
+                        return field;
+                    }
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            throw new ReflectionHelper.UnableToFindFieldException(names, e);
+        }
+        return null;
+    }
+
+    public static boolean isMethodAccessable(Class<?> clazz, String... names)
+    {
+        try
+        {
+            Method[] methods = clazz.getDeclaredMethods();
+            for (Method method : methods) {
+                for (String methodName : names) {
+                    if (method.getName().equalsIgnoreCase(methodName)) {
+                        return method.isAccessible();
+                    }
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            throw new ReflectionHelper.UnableToFindMethodException(names, e);
+        }
+        return false;
+    }
+
+    public static <T, E> Object invokeMethod(Class<? extends E> clazz, E instance, String[] names, Object... args)
+    {
+        try
+        {
+            Method method = getMethod(clazz, names);
+            if (method != null) {
+                return method.invoke(instance, args);
+            }
+        }
+        catch (Exception e)
+        {
+            throw new ReflectionHelper.UnableToFindMethodException(names, e);
+        }
+        return null;
+    }
+
+    public static Method getMethod(Class<?> clazz, String... names)
+    {
+        try
+        {
+            Method[] methods = clazz.getDeclaredMethods();
+            for (Method method : methods) {
+                for (String methodName : names) {
+                    if (method.getName().equalsIgnoreCase(methodName))
+                    {
+                        method.setAccessible(true);
+                        return method;
+                    }
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            throw new ReflectionHelper.UnableToFindMethodException(names, e);
+        }
+        return null;
+    }
+
+}
-- 
GitLab