diff options
18 files changed, 750 insertions, 154 deletions
diff --git a/.github/perspectivemod.png b/.github/perspectivemod.png Binary files differindex 13cb20e..4f1c8a9 100644 --- a/.github/perspectivemod.png +++ b/.github/perspectivemod.png @@ -7,8 +7,11 @@ A remake of [Perspective Mod v3 by canelex](https://github.com/Canelex/Perspecti Features: - Mouse button support - Nametags face camera +- Config GUI - Mod can be enabled/disabled - Hold and toggle modes +- Invert pitch/Y axis mode +- Sk1er ModCore Integration Mod can be enabled and disabled, and the mode can be changed with the `/perspectivemod` or `/pmod` commands. diff --git a/build.gradle b/build.gradle index 492b0ca..c5b0b3d 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,8 @@ buildscript { name = "forge" url = "https://files.minecraftforge.net/maven" } - maven { url = "https://repo.spongepowered.org/maven" } + + flatDir dirs: 'libs' } dependencies { classpath "net.minecraftforge.gradle:ForgeGradle:2.1-SNAPSHOT" @@ -33,6 +34,10 @@ minecraft { clientJvmArgs += "-Dfml.coreMods.load=me.djtheredstoner.perspectivemod.forge.PerspectiveModTweaker" } +dependencies { + provided files("libs/modcore.jar") +} + jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE @@ -62,4 +67,6 @@ processResources from(sourceSets.main.resources.srcDirs) { exclude 'mcmod.info' } + + from(file("LICENSE")) } diff --git a/gradle.properties b/gradle.properties index f484552..0068e23 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs=-Xmx2G # These are in here and not in build.gradle so that github actions can read them modid = djperspectivemod archivesBaseName = PerspectiveModv4 -version = 4.1
\ No newline at end of file +version = 4.2
\ No newline at end of file diff --git a/libs/modcore.jar b/libs/modcore.jar Binary files differnew file mode 100644 index 0000000..c1e7436 --- /dev/null +++ b/libs/modcore.jar diff --git a/src/main/java/me/djtheredstoner/perspectivemod/ModCoreInstaller.java b/src/main/java/me/djtheredstoner/perspectivemod/ModCoreInstaller.java new file mode 100644 index 0000000..cda3837 --- /dev/null +++ b/src/main/java/me/djtheredstoner/perspectivemod/ModCoreInstaller.java @@ -0,0 +1,506 @@ +package me.djtheredstoner.perspectivemod; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import net.minecraft.launchwrapper.Launch; +import net.minecraft.launchwrapper.LaunchClassLoader; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; + +import javax.swing.GroupLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JProgressBar; +import javax.swing.LayoutStyle; +import javax.swing.SwingConstants; +import javax.swing.UIManager; +import java.awt.Font; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/* + Created by Sk1er for use in all mods. Install under exact package name each time. + */ +public class ModCoreInstaller { + + + private static final String VERSION_URL = "https://api.sk1er.club/modcore_versions"; + private static final String className = "club.sk1er.mods.core.ModCore"; + private static boolean errored = false; + private static String error; + private static File dataDir = null; + private static boolean isRunningModCore = false; + + public static boolean isIsRunningModCore() { + return isRunningModCore; + } + + private static boolean isInitalized() { + try { + LinkedHashSet<String> objects = new LinkedHashSet<>(); + objects.add(className); + Launch.classLoader.clearNegativeEntries(objects); + Field invalidClasses = LaunchClassLoader.class.getDeclaredField("invalidClasses"); + invalidClasses.setAccessible(true); + Object obj = invalidClasses.get(ModCoreInstaller.class.getClassLoader()); + ((Set<String>) obj).remove(className); + return Class.forName("club.sk1er.mods.core.ModCore") != null; + } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException ignored) { + ignored.printStackTrace(); + } + return false; + } + + public static boolean isErrored() { + return errored; + } + + public static String getError() { + return error; + } + + private static void bail(String error) { + errored = true; + ModCoreInstaller.error = error; + } + + private static JsonHolder readFile(File in) { + try { + return new JsonHolder(FileUtils.readFileToString(in)); + } catch (IOException ignored) { + + } + return new JsonHolder(); + } + + public static void initializeModCore(File gameDir) { + if (!isIsRunningModCore()) { + return; + } + try { + Class<?> modCore = Class.forName(className); + Method instanceMethod = modCore.getMethod("getInstance"); + Method initialize = modCore.getMethod("initialize", File.class); + Object modCoreObject = instanceMethod.invoke(null); + initialize.invoke(modCoreObject, gameDir); + System.out.println("Loaded ModCore Successfully"); + return; + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + System.out.println("Did NOT ModCore Successfully"); + } + + public static int initialize(File gameDir, String minecraftVersion) { + if (isInitalized()) return -1; + dataDir = new File(gameDir, "modcore"); + if (!dataDir.exists()) { + if (!dataDir.mkdirs()) { + bail("Unable to create necessary files"); + return 1; + } + } + JsonHolder jsonHolder = fetchJSON(VERSION_URL); + String latestRemote = jsonHolder.optString(minecraftVersion); + boolean failed = jsonHolder.getKeys().size() == 0 || (jsonHolder.has("success") && !jsonHolder.optBoolean("success")); + + File metadataFile = new File(dataDir, "metadata.json"); + JsonHolder localMetadata = readFile(metadataFile); + if (failed) latestRemote = localMetadata.optString(minecraftVersion); + File modcoreFile = new File(dataDir, "Sk1er Modcore-" + latestRemote + " (" + minecraftVersion + ").jar"); + + if (!modcoreFile.exists() || !localMetadata.optString(minecraftVersion).equalsIgnoreCase(latestRemote) && !failed) { + //File does not exist, or is out of date, download it + File old = new File(dataDir, "Sk1er Modcore-" + localMetadata.optString(minecraftVersion) + " (" + minecraftVersion + ").jar"); + if (old.exists()) old.delete(); + + if (!download("https://static.sk1er.club/repo/mods/modcore/" + latestRemote + "/" + minecraftVersion + "/ModCore-" + latestRemote + " (" + minecraftVersion + ").jar", latestRemote, modcoreFile, minecraftVersion, localMetadata)) { + bail("Unable to download"); + return 2; + } + + } + + addToClasspath(modcoreFile); + + if (!isInitalized()) { + bail("Something went wrong and it did not add the jar to the class path. Local file exists? " + modcoreFile.exists()); + return 3; + } + isRunningModCore = true; + return 0; + } + + + public static void addToClasspath(File file) { + try { + URL url = file.toURI().toURL(); + + ClassLoader classLoader = ModCoreInstaller.class.getClassLoader(); + Method method = classLoader.getClass().getDeclaredMethod("addURL", URL.class); + method.setAccessible(true); + method.invoke(classLoader, url); + } catch (Exception e) { + throw new RuntimeException("Unexpected exception", e); + } + } + + private static boolean download(String url, String version, File file, String mcver, JsonHolder versionData) { + url = url.replace(" ", "%20"); + System.out.println("Downloading ModCore " + " version " + version + " from: " + url); + + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + e.printStackTrace(); + } + + JFrame frame = new JFrame("ModCore Initializer"); + JProgressBar bar = new JProgressBar(); + JLabel label = new JLabel("Downloading ModCore " + version, SwingConstants.CENTER); + label.setSize(600, 120); + frame.getContentPane().add(label); + frame.getContentPane().add(bar); + GroupLayout layout = new GroupLayout(frame.getContentPane()); + frame.getContentPane().setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(label, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE) + .addComponent(bar, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap())); + layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(label, GroupLayout.PREFERRED_SIZE, 55, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(bar, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE) + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); + frame.setResizable(false); + bar.setBorderPainted(true); + bar.setMinimum(0); + bar.setStringPainted(true); + Font font = bar.getFont(); + bar.setFont(new Font(font.getName(), font.getStyle(), font.getSize() * 2)); + label.setFont(new Font(font.getName(), font.getStyle(), font.getSize() * 2)); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + + HttpURLConnection connection = null; + InputStream is = null; + try (FileOutputStream outputStream = new FileOutputStream(file)) { + URL u = new URL(url); + connection = (HttpURLConnection) u.openConnection(); + connection.setRequestMethod("GET"); + connection.setUseCaches(true); + connection.addRequestProperty("User-Agent", "Mozilla/4.76 (Sk1er Modcore Initializer)"); + connection.setReadTimeout(15000); + connection.setConnectTimeout(15000); + connection.setDoOutput(true); + is = connection.getInputStream(); + int contentLength = connection.getContentLength(); + byte[] buffer = new byte[1024]; + System.out.println("MAX: " + contentLength); + bar.setMaximum(contentLength); + int read; + bar.setValue(0); + while ((read = is.read(buffer)) > 0) { + outputStream.write(buffer, 0, read); + bar.setValue(bar.getValue() + 1024); + } + FileUtils.write(new File(dataDir, "metadata.json"), versionData.put(mcver, version).toString()); + } catch (Exception e) { + e.printStackTrace(); + frame.dispose(); + return false; + } finally { + try { + if (connection != null) { + connection.disconnect(); + } + + if (is != null) { + is.close(); + } + } catch (Exception e) { + System.out.println("Failed cleaning up ModCoreInstaller#download"); + e.printStackTrace(); + } + } + + frame.dispose(); + return true; + } + + public static JsonHolder fetchJSON(String url) { + return new JsonHolder(fetchString(url)); + } + + public static String fetchString(String url) { + url = url.replace(" ", "%20"); + System.out.println("Fetching " + url); + + HttpURLConnection connection = null; + InputStream is = null; + try { + URL u = new URL(url); + connection = (HttpURLConnection) u.openConnection(); + connection.setRequestMethod("GET"); + connection.setUseCaches(true); + connection.addRequestProperty("User-Agent", "Mozilla/4.76 (Sk1er ModCore)"); + connection.setReadTimeout(15000); + connection.setConnectTimeout(15000); + connection.setDoOutput(true); + is = connection.getInputStream(); + return IOUtils.toString(is, Charset.defaultCharset()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (connection != null) { + connection.disconnect(); + } + + if (is != null) { + is.close(); + } + } catch (Exception e) { + System.out.println("Failed cleaning up ModCoreInstaller#fetchString"); + e.printStackTrace(); + } + } + + return "Failed to fetch"; + } + + + //Added because we need to use before ModCore is loaded + static class JsonHolder { + private JsonObject object; + + public JsonHolder(JsonObject object) { + this.object = object; + } + + public JsonHolder(String raw) { + if (raw == null) + object = new JsonObject(); + else + try { + this.object = new JsonParser().parse(raw).getAsJsonObject(); + } catch (Exception e) { + this.object = new JsonObject(); + e.printStackTrace(); + } + } + + public JsonHolder() { + this(new JsonObject()); + } + + @Override + public String toString() { + if (object != null) + return object.toString(); + return "{}"; + } + + public JsonHolder put(String key, boolean value) { + object.addProperty(key, value); + return this; + } + + public void mergeNotOverride(JsonHolder merge) { + merge(merge, false); + } + + public void mergeOverride(JsonHolder merge) { + merge(merge, true); + } + + public void merge(JsonHolder merge, boolean override) { + JsonObject object = merge.getObject(); + for (String s : merge.getKeys()) { + if (override || !this.has(s)) + put(s, object.get(s)); + } + } + + private void put(String s, JsonElement element) { + this.object.add(s, element); + } + + public JsonHolder put(String key, String value) { + object.addProperty(key, value); + return this; + } + + public JsonHolder put(String key, int value) { + object.addProperty(key, value); + return this; + } + + public JsonHolder put(String key, double value) { + object.addProperty(key, value); + return this; + } + + public JsonHolder put(String key, long value) { + object.addProperty(key, value); + return this; + } + + private JsonHolder defaultOptJSONObject(String key, JsonObject fallBack) { + try { + return new JsonHolder(object.get(key).getAsJsonObject()); + } catch (Exception e) { + return new JsonHolder(fallBack); + } + } + + public JsonArray defaultOptJSONArray(String key, JsonArray fallback) { + try { + return object.get(key).getAsJsonArray(); + } catch (Exception e) { + return fallback; + } + } + + public JsonArray optJSONArray(String key) { + return defaultOptJSONArray(key, new JsonArray()); + } + + + public boolean has(String key) { + return object.has(key); + } + + public long optLong(String key, long fallback) { + try { + return object.get(key).getAsLong(); + } catch (Exception e) { + return fallback; + } + } + + public long optLong(String key) { + return optLong(key, 0); + } + + public boolean optBoolean(String key, boolean fallback) { + try { + return object.get(key).getAsBoolean(); + } catch (Exception e) { + return fallback; + } + } + + public boolean optBoolean(String key) { + return optBoolean(key, false); + } + + public JsonObject optActualJSONObject(String key) { + try { + return object.get(key).getAsJsonObject(); + } catch (Exception e) { + return new JsonObject(); + } + } + + public JsonHolder optJSONObject(String key) { + return defaultOptJSONObject(key, new JsonObject()); + } + + + public int optInt(String key, int fallBack) { + try { + return object.get(key).getAsInt(); + } catch (Exception e) { + return fallBack; + } + } + + public int optInt(String key) { + return optInt(key, 0); + } + + + public String defaultOptString(String key, String fallBack) { + try { + return object.get(key).getAsString(); + } catch (Exception e) { + return fallBack; + } + } + + public String optString(String key) { + return defaultOptString(key, ""); + } + + + public double optDouble(String key, double fallBack) { + try { + return object.get(key).getAsDouble(); + } catch (Exception e) { + return fallBack; + } + } + + public List<String> getKeys() { + List<String> tmp = new ArrayList<>(); + for (Map.Entry<String, JsonElement> e : object.entrySet()) { + tmp.add(e.getKey()); + } + return tmp; + } + + public double optDouble(String key) { + return optDouble(key, 0.0); + } + + + public JsonObject getObject() { + return object; + } + + public boolean isNull(String key) { + return object.has(key) && object.get(key).isJsonNull(); + } + + public JsonHolder put(String values, JsonHolder values1) { + return put(values, values1.getObject()); + } + + public JsonHolder put(String values, JsonObject object) { + this.object.add(values, object); + return this; + } + + public void put(String blacklisted, JsonArray jsonElements) { + this.object.add(blacklisted, jsonElements); + } + + public void remove(String header) { + object.remove(header); + } + } + + +}
\ No newline at end of file diff --git a/src/main/java/me/djtheredstoner/perspectivemod/PerspectiveMod.java b/src/main/java/me/djtheredstoner/perspectivemod/PerspectiveMod.java index 75a0a5e..0133ff1 100644 --- a/src/main/java/me/djtheredstoner/perspectivemod/PerspectiveMod.java +++ b/src/main/java/me/djtheredstoner/perspectivemod/PerspectiveMod.java @@ -1,7 +1,6 @@ package me.djtheredstoner.perspectivemod; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; +import me.djtheredstoner.perspectivemod.commands.PerspectiveModCommand; import me.djtheredstoner.perspectivemod.config.PerspectiveModConfig; import net.minecraft.client.Minecraft; import net.minecraft.client.settings.KeyBinding; @@ -12,23 +11,18 @@ import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.event.FMLInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.InputEvent; -import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.Display; -import java.io.File; - -@Mod(modid = "djperspectivemod", name = "Perspective Mod v4", version = "4.1", acceptedMinecraftVersions = "[1.8.9]", clientSideOnly = true) +@Mod(modid = "djperspectivemod", name = "Perspective Mod v4", version = "4.2", acceptedMinecraftVersions = "[1.8.9]", clientSideOnly = true) public class PerspectiveMod { private static final Minecraft mc = Minecraft.getMinecraft(); - private static final Gson gson = new GsonBuilder().setPrettyPrinting().create(); private static final KeyBinding perspectiveKey = new KeyBinding("Perspective", Keyboard.KEY_LMENU, "Perspective Mod"); private static final Logger logger = LogManager.getLogger("Perspective Mod v4"); @@ -40,14 +34,12 @@ public class PerspectiveMod { private static int previousPerspective = 0; @Mod.EventHandler - public void preInit(FMLPreInitializationEvent event) { - File configFile = new File(event.getModConfigurationDirectory(), "perspectivemodv4.json"); - loadConfig(configFile); - Runtime.getRuntime().addShutdownHook(new Thread(() -> saveConfig(configFile))); - } - - @Mod.EventHandler public void init(FMLInitializationEvent event) { + ModCoreInstaller.initializeModCore(Minecraft.getMinecraft().mcDataDir); + + config = new PerspectiveModConfig(); + config.preload(); + ClientRegistry.registerKeyBinding(perspectiveKey); ClientCommandHandler.instance.registerCommand(new PerspectiveModCommand()); MinecraftForge.EVENT_BUS.register(this); @@ -117,6 +109,10 @@ public class PerspectiveMod { float f3 = (float) mc.mouseHelper.deltaX * f2; float f4 = (float) mc.mouseHelper.deltaY * f2; + if(config.invertPitch) { + f4 = -f4; + } + cameraYaw += f3 * 0.15F; cameraPitch += f4 * 0.15F; @@ -131,28 +127,4 @@ public class PerspectiveMod { perspectiveToggled = false; mc.gameSettings.thirdPersonView = previousPerspective; } - - public static void loadConfig(File configFile) { - if (configFile.exists()) { - try { - String json = FileUtils.readFileToString(configFile); - config = gson.fromJson(json, PerspectiveModConfig.class); - } catch (Exception e) { - logger.error("Error Loading Config, try deleting the file."); - e.printStackTrace(); - } - } else { - config = new PerspectiveModConfig(); - saveConfig(configFile); - } - } - - public static void saveConfig(File configFile) { - try { - String json = gson.toJson(config); - FileUtils.write(configFile, json); - } catch (Exception e) { - e.printStackTrace(); - } - } } diff --git a/src/main/java/me/djtheredstoner/perspectivemod/PerspectiveModCommand.java b/src/main/java/me/djtheredstoner/perspectivemod/PerspectiveModCommand.java deleted file mode 100644 index 3eae96a..0000000 --- a/src/main/java/me/djtheredstoner/perspectivemod/PerspectiveModCommand.java +++ /dev/null @@ -1,86 +0,0 @@ -package me.djtheredstoner.perspectivemod; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; -import net.minecraft.util.ChatComponentText; - -import java.util.Collections; -import java.util.List; - -public class PerspectiveModCommand extends CommandBase { - - private final String PREFIX = "§c[§6Perspective Mod§c] §r"; - - @Override - public String getCommandName() { - return "perspectivemod"; - } - - @Override - public List<String> getCommandAliases() { - return Collections.singletonList("pmod"); - } - - @Override - public String getCommandUsage(ICommandSender sender) { - return "§6Perspective Mod Help\n" + - "§b/pmod <enable|disable> §7- Enables or disables the mod.\n" + - "§b/pmod mode <hold|toggle> §7- Changes the mode.\n" + - "§7Edit the keybind in the minecraft controls menu."; - } - - @Override - public void processCommand(ICommandSender sender, String[] args) throws CommandException { - if (args.length > 0 && args.length < 3) { - String arg = args[0]; - if (arg.equalsIgnoreCase("enable")) { - PerspectiveMod.config.modEnabled = true; - - sendMessage(sender, "§bMod §aEnabled§b."); - } else if (arg.equalsIgnoreCase("disable")) { - PerspectiveMod.config.modEnabled = false; - - sendMessage(sender, "§bMod §cDisabled§b."); - } else if (arg.equalsIgnoreCase("mode")) { - if (args.length == 2) { - String mode = args[1]; - if (mode.equalsIgnoreCase("hold")) { - PerspectiveMod.config.holdMode = true; - - sendMessage(sender, "§bMode set to hold."); - } else if (mode.equalsIgnoreCase("toggle")) { - PerspectiveMod.config.holdMode = false; - - sendMessage(sender, "§bMode set to toggle."); - } else { - sendMessage(sender, "§cInvalid mode. Valid mode are hold and toggle."); - } - } else { - sendMessage(sender, "§cYou must specify a mode. Valid Modes are hold and toggle."); - } - } else { - sendHelp(sender); - } - } else { - sendHelp(sender); - } - } - - @Override - public int getRequiredPermissionLevel() { - return -1; - } - - private void sendHelp(ICommandSender sender) { - sendMessage(sender, getCommandUsage(sender), false); - } - - private void sendMessage(ICommandSender sender, String message, boolean addPrefix) { - sender.addChatMessage(new ChatComponentText((addPrefix ? PREFIX : "") + message)); - } - - private void sendMessage(ICommandSender sender, String message) { - sendMessage(sender, message, true); - } -} diff --git a/src/main/java/me/djtheredstoner/perspectivemod/asm/ClassTransformer.java b/src/main/java/me/djtheredstoner/perspectivemod/asm/ClassTransformer.java index 63f693e..c7db68b 100644 --- a/src/main/java/me/djtheredstoner/perspectivemod/asm/ClassTransformer.java +++ b/src/main/java/me/djtheredstoner/perspectivemod/asm/ClassTransformer.java @@ -2,6 +2,7 @@ package me.djtheredstoner.perspectivemod.asm; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; +import me.djtheredstoner.perspectivemod.asm.transformers.ActiveRenderInfoTransformer; import me.djtheredstoner.perspectivemod.asm.transformers.EntityRendererTransformer; import me.djtheredstoner.perspectivemod.asm.transformers.MinecraftTransformer; import me.djtheredstoner.perspectivemod.asm.transformers.RenderManagerTransformer; @@ -34,6 +35,7 @@ public class ClassTransformer implements IClassTransformer { registerTransformer(new EntityRendererTransformer()); registerTransformer(new RenderManagerTransformer()); registerTransformer(new MinecraftTransformer()); + registerTransformer(new ActiveRenderInfoTransformer()); } private void registerTransformer(ITransformer transformer) { diff --git a/src/main/java/me/djtheredstoner/perspectivemod/asm/hooks/ActiveRenderInfoHook.java b/src/main/java/me/djtheredstoner/perspectivemod/asm/hooks/ActiveRenderInfoHook.java new file mode 100644 index 0000000..e60ede4 --- /dev/null +++ b/src/main/java/me/djtheredstoner/perspectivemod/asm/hooks/ActiveRenderInfoHook.java @@ -0,0 +1,16 @@ +package me.djtheredstoner.perspectivemod.asm.hooks; + +import me.djtheredstoner.perspectivemod.PerspectiveMod; +import net.minecraft.entity.player.EntityPlayer; + +public class ActiveRenderInfoHook { + + public static float rotationYawHook(EntityPlayer entity) { + return PerspectiveMod.perspectiveToggled ? PerspectiveMod.cameraYaw : entity.rotationYaw; + } + + public static float rotationPitchHook(EntityPlayer entity) { + return PerspectiveMod.perspectiveToggled ? PerspectiveMod.cameraPitch : entity.rotationPitch; + } + +} diff --git a/src/main/java/me/djtheredstoner/perspectivemod/asm/hooks/EntityRendererHook.java b/src/main/java/me/djtheredstoner/perspectivemod/asm/hooks/EntityRendererHook.java index 3ee3c9e..193affb 100644 --- a/src/main/java/me/djtheredstoner/perspectivemod/asm/hooks/EntityRendererHook.java +++ b/src/main/java/me/djtheredstoner/perspectivemod/asm/hooks/EntityRendererHook.java @@ -26,4 +26,7 @@ public class EntityRendererHook { return PerspectiveMod.overrideMouse(); } + public static double distanceHook(double value) { + return value; + } } diff --git a/src/main/java/me/djtheredstoner/perspectivemod/asm/transformers/ActiveRenderInfoTransformer.java b/src/main/java/me/djtheredstoner/perspectivemod/asm/transformers/ActiveRenderInfoTransformer.java new file mode 100644 index 0000000..531ec90 --- /dev/null +++ b/src/main/java/me/djtheredstoner/perspectivemod/asm/transformers/ActiveRenderInfoTransformer.java @@ -0,0 +1,68 @@ +package me.djtheredstoner.perspectivemod.asm.transformers; + +import me.djtheredstoner.perspectivemod.asm.ITransformer; +import org.objectweb.asm.tree.*; + +import java.util.ListIterator; + +import static org.objectweb.asm.Opcodes.*; + +public class ActiveRenderInfoTransformer implements ITransformer { + + private static final String HOOK_CLASS = "me/djtheredstoner/perspectivemod/asm/hooks/ActiveRenderInfoHook"; + + @Override + public String[] getClassName() { + return new String[]{"net.minecraft.client.renderer.ActiveRenderInfo"}; + } + + @Override + public void transform(ClassNode classNode, String name) { + for (MethodNode method : classNode.methods) { + String methodName = mapMethodName(classNode, method); + + if (methodName.equals("updateRenderInfo") || methodName.equals("func_74583_a")) { + ListIterator<AbstractInsnNode> iterator = method.instructions.iterator(); + + while (iterator.hasNext()) { + AbstractInsnNode next = iterator.next(); + + if(next.getOpcode() == GETFIELD) { + FieldInsnNode insn = (FieldInsnNode) next; + + String ownerName = mapClassName(insn.owner); + String fieldName = mapClassName(insn.name); + + if(ownerName.equals("net/minecraft/entity/player/EntityPlayer") && insn.desc.equals("F")) { + InsnList insnList = null; + + switch (fieldName) { + case "rotationPitch": + case "field_70125_A": + insnList = insertRotationHook("Pitch"); + break; + case "rotationYaw": + case "field_70177_z": + insnList = insertRotationHook("Yaw"); + break; + } + + if(insnList != null) { + method.instructions.insertBefore(insn, insnList); + method.instructions.remove(insn); + } + } + } + } + } + } + } + + private InsnList insertRotationHook(String field) { + InsnList insnList = new InsnList(); + + insnList.add(new MethodInsnNode(INVOKESTATIC, HOOK_CLASS, "rotation" + field + "Hook", "(Lnet/minecraft/entity/player/EntityPlayer;)F", false)); + + return insnList; + } +} diff --git a/src/main/java/me/djtheredstoner/perspectivemod/asm/transformers/EntityRendererTransformer.java b/src/main/java/me/djtheredstoner/perspectivemod/asm/transformers/EntityRendererTransformer.java index dadb1e0..ac47621 100644 --- a/src/main/java/me/djtheredstoner/perspectivemod/asm/transformers/EntityRendererTransformer.java +++ b/src/main/java/me/djtheredstoner/perspectivemod/asm/transformers/EntityRendererTransformer.java @@ -3,6 +3,8 @@ package me.djtheredstoner.perspectivemod.asm.transformers; import me.djtheredstoner.perspectivemod.asm.ITransformer; import org.objectweb.asm.tree.*; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.Iterator; import static org.objectweb.asm.Opcodes.*; @@ -37,7 +39,7 @@ public class EntityRendererTransformer implements ITransformer { String ownerName = mapClassName(insn.owner); String fieldName = mapFieldNameFromNode(insn); - if(ownerName.equals("net/minecraft/entity/Entity" )&& insn.desc.equals("F")) { + if(ownerName.equals("net/minecraft/entity/Entity" ) && insn.desc.equals("F")) { InsnList insnList = null; @@ -65,9 +67,14 @@ public class EntityRendererTransformer implements ITransformer { method.instructions.remove(insn); } } - } - } + } /*else if (next.getOpcode() == DLOAD) { + VarInsnNode insn = (VarInsnNode) next; + if(insn.getPrevious().getOpcode() == FCONST_0 && insn.getNext().getOpcode() == DNEG) { + method.instructions.insert(insn, insertDistanceHook()); + } + }*/ + } } else if (methodName.equals("updateCameraAndRender") || methodName.equals("func_181560_a")) { Iterator<AbstractInsnNode> iterator = method.instructions.iterator(); @@ -89,10 +96,15 @@ public class EntityRendererTransformer implements ITransformer { } } } + //Poggers Ultra FPS Praseodymium mode. + /* else if (methodName.equals("renderWorldPass") || methodName.equals("func_175068_a")) { + + method.instructions.insert(method.instructions.getFirst(), new InsnNode(RETURN)); + }*/ } } - public InsnList insertRotationHook(String field) { + private InsnList insertRotationHook(String field) { InsnList list = new InsnList(); list.add(new MethodInsnNode(INVOKESTATIC, HOOK_CLASS, field + "Hook", "(Lnet/minecraft/entity/Entity;)F", false)); @@ -100,11 +112,19 @@ public class EntityRendererTransformer implements ITransformer { return list; } - public InsnList insertMouseHook() { + private InsnList insertMouseHook() { InsnList list = new InsnList(); list.add(new MethodInsnNode(INVOKESTATIC, HOOK_CLASS, "mouseHook", "(Lnet/minecraft/client/Minecraft;)Z", false)); return list; } + + private InsnList insertDistanceHook() { + InsnList list = new InsnList(); + + list.add(new MethodInsnNode(INVOKESTATIC, HOOK_CLASS, "distanceHook", "(D)D", false)); + + return list; + } } diff --git a/src/main/java/me/djtheredstoner/perspectivemod/commands/PerspectiveModCommand.java b/src/main/java/me/djtheredstoner/perspectivemod/commands/PerspectiveModCommand.java new file mode 100644 index 0000000..68dd051 --- /dev/null +++ b/src/main/java/me/djtheredstoner/perspectivemod/commands/PerspectiveModCommand.java @@ -0,0 +1,60 @@ +package me.djtheredstoner.perspectivemod.commands; + +import club.sk1er.mods.core.ModCore; +import me.djtheredstoner.perspectivemod.PerspectiveMod; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; + +import java.util.Collections; +import java.util.List; + +public class PerspectiveModCommand extends CommandBase { + + private final String PREFIX = "§c[§6Perspective Mod§c] §r"; + + @Override + public String getCommandName() { + return "perspectivemod"; + } + + @Override + public List<String> getCommandAliases() { + return Collections.singletonList("pmod"); + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return "§6Perspective Mod Help\n" + + "§b/pmod <enable|disable> §7- Enables or disables the mod.\n" + + "§b/pmod mode <hold|toggle> §7- Changes the mode.\n" + + "§7Edit the keybind in the minecraft controls menu."; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + if (args.length == 1 && args[0].equals("eW91IGZvdW5kIGEgc2VjcmV0IQo=")) { + sendMessage("you found a secret!"); + } else { + ModCore.getInstance().getGuiHandler().open(PerspectiveMod.config.gui()); + } + } + + @Override + public int getRequiredPermissionLevel() { + return -1; + } + + private void sendHelp() { + sendMessage(getCommandUsage(Minecraft.getMinecraft().thePlayer), false); + } + + private void sendMessage(String message, boolean addPrefix) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText((addPrefix ? PREFIX : "") + message)); + } + + private void sendMessage(String message) { + sendMessage(message, true); + } +} diff --git a/src/main/java/me/djtheredstoner/perspectivemod/config/PerspectiveModConfig.java b/src/main/java/me/djtheredstoner/perspectivemod/config/PerspectiveModConfig.java index d4b1922..3f15069 100644 --- a/src/main/java/me/djtheredstoner/perspectivemod/config/PerspectiveModConfig.java +++ b/src/main/java/me/djtheredstoner/perspectivemod/config/PerspectiveModConfig.java @@ -1,8 +1,42 @@ package me.djtheredstoner.perspectivemod.config; -public class PerspectiveModConfig { +import club.sk1er.vigilance.Vigilant; +import club.sk1er.vigilance.data.Property; +import club.sk1er.vigilance.data.PropertyType; +import java.io.File; + +public class PerspectiveModConfig extends Vigilant { + + @Property( + type = PropertyType.SWITCH, + name = "Perspective Mod", + category = "General", + subcategory = "General", + description = "Toggle Perspective Mod entirely." + ) public boolean modEnabled = true; + + @Property( + type = PropertyType.SWITCH, + name = "Hold Mode", + category = "General", + subcategory = "General", + description = "Return to normal perspective after releasing keybind." + ) public boolean holdMode = true; + @Property( + type = PropertyType.SWITCH, + name = "Invert Pitch", + category = "General", + subcategory = "General", + description = "Invert the pitch while in perspective (same as blc/lunar)." + ) + public boolean invertPitch = false; + + public PerspectiveModConfig() { + super(new File("./config/perspectivemodv4.toml")); + initialize(); + } } diff --git a/src/main/java/me/djtheredstoner/perspectivemod/forge/PerspectiveModTweaker.java b/src/main/java/me/djtheredstoner/perspectivemod/forge/PerspectiveModTweaker.java index 695f7a2..f5128f0 100644 --- a/src/main/java/me/djtheredstoner/perspectivemod/forge/PerspectiveModTweaker.java +++ b/src/main/java/me/djtheredstoner/perspectivemod/forge/PerspectiveModTweaker.java @@ -1,5 +1,6 @@ package me.djtheredstoner.perspectivemod.forge; +import me.djtheredstoner.perspectivemod.ModCoreInstaller; import me.djtheredstoner.perspectivemod.asm.ClassTransformer; import net.minecraft.launchwrapper.Launch; import net.minecraftforge.common.ForgeVersion; @@ -52,6 +53,17 @@ public class PerspectiveModTweaker implements IFMLLoadingPlugin { @Override public String[] getASMTransformerClass() { + int initialize = ModCoreInstaller.initialize(Launch.minecraftHome, "1.8.9"); + + if (ModCoreInstaller.isErrored() || initialize != 0 && initialize != -1) { + System.out.println("Failed to load Sk1er Modcore - " + initialize + " - " + ModCoreInstaller.getError()); + } + // If true the classes are loaded + if (ModCoreInstaller.isIsRunningModCore()) { + // register ModCore's class transformer + return new String[]{"club.sk1er.mods.core.forge.ClassTransformer", ClassTransformer.class.getName()}; + } + return new String[]{ClassTransformer.class.getName()}; } diff --git a/src/main/resources/LICENSE b/src/main/resources/LICENSE deleted file mode 100644 index 45ae6c4..0000000 --- a/src/main/resources/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 DJtheRedstoner - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE.
\ No newline at end of file |