diff --git a/build.gradle b/build.gradle index ed12ee8..438ae2f 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' apply plugin: 'maven-publish' -version = "1.13-1.7" +version = "1.13-1.7b" group= "net.unladenswallow.minecraft.autofish" // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = "mod_autofish_forge" @@ -69,7 +69,7 @@ dependencies { // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. // The userdev artifact is a special name and will get all sorts of transformations applied to it. - minecraft 'net.minecraftforge:forge:1.13.2-25.0.191' + minecraft 'net.minecraftforge:forge:1.13.2-25.0.219' // You may put jars on which you depend on in ./libs or you may define them like so.. // compile "some.group:artifact:version:classifier" diff --git a/src/main/java/net/unladenswallow/minecraft/autofish/AutoFish.java b/src/main/java/net/unladenswallow/minecraft/autofish/AutoFish.java index 08853fd..ddc3ef9 100644 --- a/src/main/java/net/unladenswallow/minecraft/autofish/AutoFish.java +++ b/src/main/java/net/unladenswallow/minecraft/autofish/AutoFish.java @@ -1,7 +1,5 @@ package net.unladenswallow.minecraft.autofish; -import java.io.PrintWriter; -import java.io.StringWriter; import java.util.Random; import net.minecraft.block.material.Material; @@ -46,7 +44,7 @@ public class AutoFish { // private long exactBobberSplashDetectedAt = 0L; private Random rand; - private static final String NOTIFICATION_TEXT_AUTOFISH_ENABLED = "AutoFish is enabled. Type 'o' while holding a fishing rod for more options"; + private static final String NOTIFICATION_TEXT_AUTOFISH_ENABLED = "AutoFish is %s. Type 'o' while holding a fishing rod for more options"; private static final int TICKS_PER_SECOND = 20; @@ -74,7 +72,7 @@ public class AutoFish { private static final int FAST_FISH_DELAY_VARIANCE = 40; /** The maximum number of ticks that is is reasonable for a fish hook to be flying in the air after a cast */ - private static final int MAX_HOOK_FLYING_TIME_TICKS = 80; + private static final int MAX_HOOK_FLYING_TIME_TICKS = 120; /** The amount of time to wait for a fish before something seems wrong and we want to recast **/ private static final int MAX_WAITING_TIME_SECONDS = 60; @@ -110,7 +108,13 @@ public AutoFish() { * Callback from EventListener for ClientTickEvent */ public void onClientTick() { - update(); + this.player = this.minecraftClient.player; + if (this.player != null && !this.notificationShownToPlayer) { + showNotificationToPlayer(); + } + if (AutoFishModConfig.autofishEnabled()) { + update(); + } } public void onBobberSplashDetected(float x, float y, float z) { @@ -136,25 +140,39 @@ public void onBobberSplashDetected(float x, float y, float z) { * has been programmatically triggered). * */ - public void onPlayerUseItem() { - if (playerIsHoldingRod()) { - if (!rodIsCast()) { - // Player is casting - resetReelDelay(); - resetCastSchedule(); - resetBiteTracking(); - this.isFishing = true; - startCastDelay(); - } else { - // Player is reeling in - this.isFishing = false; - resetCastDelay(); - // Bug in Forge that doesn't delete the fishing hook entity - this.player.fishEntity = null; - } + public void onPlayerUseItem(EnumHand hand) { + if (!playerIsHoldingRod()) { + return; + } + // If player is holding a usable item in MAIN_HAND and a fishing rod in OFF_HAND, + // then this function will be called twice in the same tick, one for each hand. + // We need to ignore the non-fishing rod call. + if (isUseOfNonRodInMainHand(hand)) { + return; + } + if (!rodIsCast()) { + // Player is casting + resetReelDelay(); + resetCastSchedule(); + resetBiteTracking(); + this.isFishing = true; + startCastDelay(); + } else { + // Player is reeling in + this.isFishing = false; + resetCastDelay(); + // Bug in Forge that doesn't delete the fishing hook entity +// Logger.info("fishEntity: %s", this.player.fishEntity); + this.player.fishEntity = null; } } + private boolean isUseOfNonRodInMainHand(EnumHand hand) { + return hand == EnumHand.MAIN_HAND && !isUsableFishingRod(this.player.getHeldItemMainhand()); + } + + + /** * Callback from the WorldEventListener to tell us whenever a WATER_WAKE particle * is spawned in the world. @@ -194,7 +212,6 @@ public void onWaterWakeDetected(double x, double y, double z) { public void onXpOrbAdded(double x, double y, double z) { if (this.player != null) { double distanceFromPlayer = this.player.getPosition().distanceSq(x, y, z); -// AutoFishLogger.info("Entity [%s] spawned at distance %f from player", entity.getDisplayName().getFormattedText(), distanceFromPlayer); if (distanceFromPlayer < 2.0d) { this.xpLastAddedAt = getGameTime(); } @@ -210,12 +227,7 @@ public void onXpOrbAdded(double x, double y, double z) { * and trigger appropriate actions. */ private void update() { - if (!this.minecraftClient.isGamePaused() && this.minecraftClient.player != null) { - this.player = this.minecraftClient.player; - if (!this.notificationShownToPlayer) { - showNotificationToPlayer(); - } - + if (!this.minecraftClient.isGamePaused() && this.player != null) { if (playerIsHoldingRod() || waitingToRecast()) { if ((playerHookInWater(this.player) && !isDuringReelDelay() && isFishBiting()) || somethingSeemsWrong()) { @@ -238,7 +250,7 @@ private void update() { resetBiteTracking(); } - if (AutoFishModConfig.CLIENT.config_autofish_entityClearProtect.get()) { + if (AutoFishModConfig.entityClearProtectEnabled()) { checkForEntityClear(); } @@ -340,8 +352,8 @@ private boolean isFishBiting_fromClientWorld() { private boolean isFishBiting_fromBobberSound() { /** If a bobber sound has been played at the fish hook, a fish is already biting **/ - if (AutoFishModConfig.CLIENT.config_autofish_aggressiveBiteDetection.get() && this.closeBobberSplashDetectedAt > 0) { - Logger.debug("[%d] Detected bite by BOBBER_SPLASH", getGameTime()); + if (AutoFishModConfig.aggressiveBiteDetectionEnabled() && this.closeBobberSplashDetectedAt > 0) { + Logger.debug("Detected bite by BOBBER_SPLASH"); return true; } return false; @@ -349,10 +361,10 @@ private boolean isFishBiting_fromBobberSound() { private boolean isFishBiting_fromWaterWake() { /** An water wake indicates a probable bite "very soon", so make sure enough time has passed **/ - if (AutoFishModConfig.CLIENT.config_autofish_aggressiveBiteDetection.get() + if (AutoFishModConfig.aggressiveBiteDetectionEnabled() && this.closeWaterWakeDetectedAt > 0 && getGameTime() > this.closeWaterWakeDetectedAt + CLOSE_WATER_WAKE_DELAY_TICKS) { - Logger.debug("[%d] Detected bite by WATER_WAKE", getGameTime()); + Logger.debug("Detected bite by WATER_WAKE"); return true; } return false; @@ -365,7 +377,7 @@ private boolean isFishBiting_fromMovement() { && fishEntity.motionX == 0 && fishEntity.motionZ == 0 && fishEntity.motionY < MOTION_Y_THRESHOLD) { - Logger.debug("[%d] Detected bite by MOVEMENT", getGameTime()); + Logger.debug("Detected bite by MOVEMENT"); return true; } return false; @@ -385,7 +397,7 @@ private boolean isFishBiting_fromAll() { && fishEntity.motionY < MOTION_Y_MAYBE_THRESHOLD) { // long totalWorldTime = getGameTime(); if (recentCloseBobberSplash() || recentCloseWaterWake()) { - Logger.debug("[%d] Detected bite by ALL", getGameTime()); + Logger.debug("Detected bite by ALL"); return true; } } @@ -408,18 +420,16 @@ private boolean playerHookInWater(EntityPlayer player) { if (player == null || player.fishEntity == null) { return false; } + // Sometimes, particularly around the time of a bite, the hook entity comes slightly out of the + // water block, so also check a fraction of a block distance lower to see if that is water. + // (EntityFishHook.isInWater() seems to be completely broken in 1.13) IBlockState hookBlockState = player.fishEntity.getEntityWorld().getBlockState(new BlockPos(player.fishEntity)); - boolean hookIsInWater = hookBlockState.getMaterial() == Material.WATER; -// Logger.info("Hook %s in water", hookIsInWater ? "is" : "is not"); -// Logger.info("Hook is at [x: %f, y: %f, z: %f", player.fishEntity.posX, player.fishEntity.posY, player.fishEntity.posZ); + IBlockState justBelowHookBlockState = player.fishEntity.getEntityWorld().getBlockState(new BlockPos(player.fishEntity.posX, player.fishEntity.posY - 0.25, player.fishEntity.posZ)); + boolean hookIsInWater = hookBlockState.getMaterial() == Material.WATER || justBelowHookBlockState.getMaterial() == Material.WATER; return hookIsInWater; -// Logger.info("Hook %s in water", player != null && player.fishEntity != null -// && player.fishEntity.isInWater() ? "is" : "is not"); -// return player != null && player.fishEntity != null -// && player.fishEntity.isInWater(); } - private boolean playerIsHoldingRod() { + public boolean playerIsHoldingRod() { return findActiveFishingRod() != null; } @@ -446,13 +456,14 @@ && getGameTime() > this.closeWaterWakeDetectedAt + CLOSE_WATER_WAKE_DELAY_TICKS) } return false; } + private boolean somethingSeemsWrong() { if (rodIsCast() && !isDuringCastDelay() && !isDuringReelDelay() && hookShouldBeInWater()) { - if ((playerHookInWater(this.player) || AutoFishModConfig.CLIENT.config_autofish_handleProblems.get()) && waitedLongEnough()) { + if ((playerHookInWater(this.player) || AutoFishModConfig.handleProblemsEnabled()) && waitedLongEnough()) { Logger.info("We should have caught something by now."); return true; } - if (AutoFishModConfig.CLIENT.config_autofish_handleProblems.get()) { + if (AutoFishModConfig.handleProblemsEnabled()) { if (hookedAnEntity()) { Logger.info("Oops, we hooked an Entity"); return true; @@ -486,21 +497,15 @@ private boolean rodIsCast() { return false; } ItemStack activeFishingRod = findActiveFishingRod(); -// Logger.info("cast property: %f", activeFishingRod.getItem().getPropertyGetter(new ResourceLocation("cast")).call(activeFishingRod, this.minecraftClient.world, this.player)); return activeFishingRod.getItem().getPropertyGetter(new ResourceLocation("cast")).call(activeFishingRod, this.minecraftClient.world, this.player) > 0F; -// Logger.info("Rod %s cast.", this.rodIsCast ? "is" : "is not"); -// return this.rodIsCast; } private boolean needToSwitchRods() { - return AutoFishModConfig.CLIENT.config_autofish_multirod.get() && !playerCanCast(); + return AutoFishModConfig.multiRodEnabled() && !playerCanCast(); } private boolean isTimeToCast() { - if (this.castScheduledAt > 0 && getGameTime() > this.castScheduledAt + (AutoFishModConfig.CLIENT.config_autofish_recastDelay.get() * TICKS_PER_SECOND)) { - Logger.info("Time to Cast! castScheduledAt: %d; gameTime: %d; delay: %d", this.castScheduledAt, getGameTime(), (AutoFishModConfig.CLIENT.config_autofish_recastDelay.get() * TICKS_PER_SECOND)); - } - return (this.castScheduledAt > 0 && getGameTime() > this.castScheduledAt + (AutoFishModConfig.CLIENT.config_autofish_recastDelay.get() * TICKS_PER_SECOND)); + return (this.castScheduledAt > 0 && getGameTime() > this.castScheduledAt + (AutoFishModConfig.recastDelay() * TICKS_PER_SECOND)); } private boolean waitingToRecast() { @@ -516,13 +521,16 @@ private boolean playerCanCast() { return false; } - return (!AutoFishModConfig.CLIENT.config_autofish_preventBreak.get() + return (!AutoFishModConfig.breakPreventEnabled() || (activeFishingRod.getMaxDamage() - activeFishingRod.getDamage() > AUTOFISH_BREAKPREVENT_THRESHOLD) ); } } private ItemStack findActiveFishingRod() { + if (this.player == null) { + return null; + } ItemStack heldItem = this.player.getHeldItemMainhand(); ItemStack heldItemOffhand = this.player.getHeldItemOffhand(); return isUsableFishingRod(heldItem) ? heldItem : @@ -534,17 +542,12 @@ private ItemStack findActiveFishingRod() { private void showNotificationToPlayer() { - this.player.sendMessage(new TextComponentString(NOTIFICATION_TEXT_AUTOFISH_ENABLED)); + String notification = String.format(NOTIFICATION_TEXT_AUTOFISH_ENABLED, AutoFishModConfig.autofishEnabled() ? "enabled" : "disabled"); + this.player.sendMessage(new TextComponentString(notification)); this.notificationShownToPlayer = true; } -// private void recordLastHookPosition(EntityFishHook fishEntity) { -// this.lastHookPosition = fishEntity.getPosition(); -// } -// - private void reelIn() { - Logger.info("Reeling In"); playerUseRod(); // Bug in Forge that doesn't delete the fishing hook entity this.player.fishEntity = null; @@ -568,7 +571,6 @@ private void resetCastDelay() { private void scheduleNextCast() { this.castScheduledAt = getGameTime(); - Logger.info("Cast scheduled at %d", this.castScheduledAt); } /* @@ -649,11 +651,10 @@ private EntityPlayer getServerPlayerEntity() { } private EnumActionResult playerUseRod() { - Logger.info("Using rod at %d", getGameTime()); return this.minecraftClient.playerController.processRightClick( this.player, this.minecraftClient.world, - EnumHand.MAIN_HAND); + isUsableFishingRod(this.player.getHeldItemMainhand()) ? EnumHand.MAIN_HAND : EnumHand.OFF_HAND); } // private boolean isInOffHand(ItemStack itemStack) { @@ -662,7 +663,6 @@ private EnumActionResult playerUseRod() { private void resetBiteTracking() { this.xpLastAddedAt = 0L; -// this.lastHookPosition = null; this.closeWaterWakeDetectedAt = 0L; // this.exactWaterWakeDetectedAt = 0L; this.closeBobberSplashDetectedAt = 0L; @@ -675,7 +675,7 @@ private void tryToSwitchRods() { ItemStack curItemStack = inventory.mainInventory.get(i); if (curItemStack != null && curItemStack.getItem() instanceof ItemFishingRod - && (!AutoFishModConfig.CLIENT.config_autofish_preventBreak.get() || (curItemStack.getMaxDamage() - curItemStack.getDamage() > AUTOFISH_BREAKPREVENT_THRESHOLD)) + && (!AutoFishModConfig.breakPreventEnabled() || (curItemStack.getMaxDamage() - curItemStack.getDamage() > AUTOFISH_BREAKPREVENT_THRESHOLD)) ) { inventory.currentItem = i; break; @@ -684,6 +684,7 @@ private void tryToSwitchRods() { } private void checkForEntityClear() { +// Logger.info("Checking for Entity Clear. isFishing: %b; fishEntity: %s", this.isFishing, this.player.fishEntity); if (this.isFishing && !isDuringCastDelay() && this.player.fishEntity == null) { Logger.info("Entity Clear detected. Re-casting."); this.isFishing = false; @@ -693,9 +694,8 @@ private void checkForEntityClear() { private void checkForMissedBite() { if (playerHookInWater(this.player)) { -// recordLastHookPosition(this.player.fishEntity); if (this.closeBobberSplashDetectedAt > 0 && getGameTime() > this.closeBobberSplashDetectedAt + 45) { - Logger.debug("[%d] I think we missed a fish", getGameTime()); + Logger.debug("I think we missed a fish"); resetBiteTracking(); } } diff --git a/src/main/java/net/unladenswallow/minecraft/autofish/ModAutoFish.java b/src/main/java/net/unladenswallow/minecraft/autofish/ModAutoFish.java index 1ffa96f..8f75bb4 100644 --- a/src/main/java/net/unladenswallow/minecraft/autofish/ModAutoFish.java +++ b/src/main/java/net/unladenswallow/minecraft/autofish/ModAutoFish.java @@ -2,6 +2,7 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.SubscribeEvent; +//import net.minecraftforge.fml.ExtensionPoint; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; @@ -10,24 +11,13 @@ import net.unladenswallow.minecraft.autofish.config.AutoFishModConfig; import net.unladenswallow.minecraft.autofish.events.EventListener; import net.unladenswallow.minecraft.autofish.events.KeyInputHandler; +//import net.unladenswallow.minecraft.autofish.gui.ConfigGui; import net.unladenswallow.minecraft.autofish.util.Logger; @Mod(ModAutoFish.MODID) -//@Mod.EventBusSubscriber(modid = ModAutoFish.MODID, bus = Mod.EventBusSubscriber.Bus.MOD) public class ModAutoFish { public static final String MODID = "mod_autofish"; -// private static final List propertyOrder = new ArrayList(Arrays.asList(new String[] { -// "Enable AutoFish", -// "Enable MultiRod", -// "Enable Break Protection", -// "Re-Cast Delay", -// "Enable Entity Clear Protection", -// "Enable Aggressive Bite Detection", -// "Handle Problems", -// "Enable Fast Fishing" -// })); - public static AutoFish autoFish = new AutoFish(); public static EventListener eventListener = new EventListener(autoFish); @@ -40,6 +30,7 @@ public ModAutoFish() { FMLJavaModLoadingContext.get().getModEventBus().register(AutoFishModConfig.class); MinecraftForge.EVENT_BUS.register(this); AutoFishModConfig.register(ModLoadingContext.get()); +// ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> (mc, screen) -> new ConfigGui(screen)); } @SubscribeEvent @@ -53,19 +44,4 @@ public void clientInit (final FMLClientSetupEvent event) { MinecraftForge.EVENT_BUS.register(new KeyInputHandler()); } -// public static void syncConfig() { -// config_autofish_enable = configFile.getBoolean("Enable AutoFish", Configuration.CATEGORY_GENERAL, CONFIG_DEFAULT_AUTOFISH_ENABLE, "Automatically reel in and re-cast when a fish nibbles the hook. If set to false, all other AutoFish functionality is disabled."); -// config_autofish_multirod = configFile.getBoolean("Enable MultiRod", Configuration.CATEGORY_GENERAL, CONFIG_DEFAULT_AUTOFISH_MULTIROD, "Automatically switch to a new fishing rod when the current rod breaks, if one is available in the hotbar."); -// config_autofish_preventBreak = configFile.getBoolean("Enable Break Protection", Configuration.CATEGORY_GENERAL, CONFIG_DEFAULT_AUTOFISH_PREVENTBREAK, "Stop fishing or switch to a new rod just before the current rod breaks. Useful if you want to repair your enchanted fishing rods."); -// config_autofish_entityClearProtect = configFile.getBoolean("Enable Entity Clear Protection", Configuration.CATEGORY_GENERAL, CONFIG_DEFAULT_AUTOFISH_ENTITYCLEARPROTECT, "When playing on a server, re-cast after the server clears entities. Useful if you are playing on a server that periodically deletes all entities (including fishing hooks) from the world, which causes you to stop fishing."); -// config_autofish_recastDelay = configFile.getInt("Re-Cast Delay", Configuration.CATEGORY_GENERAL, CONFIG_DEFAULT_AUTOFISH_RECASTDELAY, 1, 10, "Time (in seconds) to wait before automatically re-casting. Increase this value if server lag causes re-casting to fail."); -// config_autofish_fastFishing = configFile.getBoolean("Enable Fast Fishing", Configuration.CATEGORY_GENERAL, CONFIG_DEFAULT_AUTOFISH_FASTFISHING, "[SINGLE PLAYER ONLY] Fish will bite right after casting."); -// config_autofish_aggressiveBiteDetection = configFile.getBoolean("Enable Aggressive Bite Detection", Configuration.CATEGORY_GENERAL, CONFIG_DEFAULT_AUTOFISH_AGGRESSIVEBITEDETECTION, "When playing on a server, be more aggressive about detecting fish bites. Improves multiplayer bite detection from ~85% to ~95%, but false positives will be more likely, especially if other players are fishing very close by."); -// config_autofish_handleProblems = configFile.getBoolean("Handle Problems", Configuration.CATEGORY_GENERAL, CONFIG_DEFAULT_AUTOFISH_HANDLEPROBLEMS, "[HAS SIDE EFFECTS] Re-cast when problems detected (e.g. if not in water or if a MOB has been hooked). If enabled, non-fishing use of the fishing rod (e.g. intentionally hooking MOBs) will be affected."); -// -// if (configFile.hasChanged()) { -// configFile.save(); -// } -// } - } diff --git a/src/main/java/net/unladenswallow/minecraft/autofish/config/AutoFishModConfig.java b/src/main/java/net/unladenswallow/minecraft/autofish/config/AutoFishModConfig.java index e18cf94..427fd94 100644 --- a/src/main/java/net/unladenswallow/minecraft/autofish/config/AutoFishModConfig.java +++ b/src/main/java/net/unladenswallow/minecraft/autofish/config/AutoFishModConfig.java @@ -1,18 +1,41 @@ package net.unladenswallow.minecraft.autofish.config; +import java.util.ArrayList; +import java.util.List; import org.apache.commons.lang3.tuple.Pair; + +import com.electronwill.nightconfig.core.file.CommentedFileConfig; +import com.google.common.base.Joiner; + import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec.BooleanValue; import net.minecraftforge.common.ForgeConfigSpec.IntValue; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.config.ModConfig; +import net.unladenswallow.minecraft.autofish.config.ConfigOption.ValueType; import net.unladenswallow.minecraft.autofish.util.Logger; import net.minecraftforge.fml.ModLoadingContext; public class AutoFishModConfig { + /* + * This is probably an overly-complicated way of handling configs, but I can't for the + * life of me figure out how to write changes to the config file any other way. + */ + private static final boolean CONFIG_DEFAULT_AUTOFISH_ENABLE = true; + private static final boolean CONFIG_DEFAULT_AUTOFISH_MULTIROD = false; + private static final boolean CONFIG_DEFAULT_AUTOFISH_PREVENTBREAK = false; + private static final boolean CONFIG_DEFAULT_AUTOFISH_ENTITYCLEARPROTECT = false; + private static final int CONFIG_DEFAULT_AUTOFISH_RECASTDELAY = 2; + private static final boolean CONFIG_DEFAULT_AUTOFISH_FASTFISHING = false; + private static final boolean CONFIG_DEFAULT_AUTOFISH_AGGRESSIVEBITEDETECTION = false; + private static final boolean CONFIG_DEFAULT_AUTOFISH_HANDLEPROBLEMS = false; + + private static final Joiner DotJoiner = Joiner.on("."); private static final ForgeConfigSpec clientSpec; - public static final ClientConfig CLIENT; + private static final ClientConfig CLIENT; + private static String ConfigFilePath; + private static List configOptions; static { final Pair specPair = new ForgeConfigSpec.Builder().configure(ClientConfig::new); @@ -21,28 +44,20 @@ public class AutoFishModConfig { } public static class ClientConfig { - public static BooleanValue config_autofish_enable; - private static final boolean CONFIG_DEFAULT_AUTOFISH_ENABLE = true; - public static BooleanValue config_autofish_multirod; - private static final boolean CONFIG_DEFAULT_AUTOFISH_MULTIROD = false; - public static BooleanValue config_autofish_preventBreak; - private static final boolean CONFIG_DEFAULT_AUTOFISH_PREVENTBREAK = false; - public static BooleanValue config_autofish_entityClearProtect; - private static final boolean CONFIG_DEFAULT_AUTOFISH_ENTITYCLEARPROTECT = false; - public static IntValue config_autofish_recastDelay; - private static final int CONFIG_DEFAULT_AUTOFISH_RECASTDELAY = 2; - public static BooleanValue config_autofish_fastFishing; - private static final boolean CONFIG_DEFAULT_AUTOFISH_FASTFISHING = false; - public static BooleanValue config_autofish_aggressiveBiteDetection; - private static final boolean CONFIG_DEFAULT_AUTOFISH_AGGRESSIVEBITEDETECTION = false; - public static BooleanValue config_autofish_handleProblems; - private static final boolean CONFIG_DEFAULT_AUTOFISH_HANDLEPROBLEMS = false; + public BooleanValue config_autofish_enable; + public BooleanValue config_autofish_multirod; + public BooleanValue config_autofish_preventBreak; + public BooleanValue config_autofish_entityClearProtect; + public IntValue config_autofish_recastDelay; + public BooleanValue config_autofish_fastFishing; + public BooleanValue config_autofish_aggressiveBiteDetection; + public BooleanValue config_autofish_handleProblems; ClientConfig(final ForgeConfigSpec.Builder builder) { builder.comment("Client config settings") .push("client"); config_autofish_enable = builder - .comment("Enable AutoFish") + .comment("Enable AutoFish", "Automatically reel in and re-cast when a fish nibbles the hook. If set to false, all other AutoFish functionality is disabled.") .define("config_autofish_enable", CONFIG_DEFAULT_AUTOFISH_ENABLE); config_autofish_multirod = builder .comment("Enable MultiRod") @@ -74,15 +89,117 @@ public static void register(final ModLoadingContext context) { context.registerConfig(ModConfig.Type.CLIENT, clientSpec); } + + @SubscribeEvent public static void onLoad(final ModConfig.Loading configEvent) { - Logger.debug("Loaded AutoFishMod config file {}", configEvent.getConfig().getFileName()); + Logger.info("Loaded AutoFishMod config file {}", configEvent.getConfig().getFileName()); + ConfigFilePath = configEvent.getConfig().getFullPath().toString(); + configOptions = new ArrayList(); + configOptions.add(new ConfigOption(CLIENT.config_autofish_enable.getPath(), CLIENT.config_autofish_enable.get(), "AutoFish")); + configOptions.add(new ConfigOption(CLIENT.config_autofish_multirod.getPath(), CLIENT.config_autofish_multirod.get(), "MultiRod")); + configOptions.add(new ConfigOption(CLIENT.config_autofish_preventBreak.getPath(), CLIENT.config_autofish_preventBreak.get(), "Break Protection")); + configOptions.add(new ConfigOption(CLIENT.config_autofish_recastDelay.getPath(), CLIENT.config_autofish_recastDelay.get(), "Re-Cast Delay")); +// configOptions.add(new ConfigOption(CLIENT.config_autofish_entityClearProtect.getPath(), CLIENT.config_autofish_entityClearProtect.get(), "Entity Clear Protection")); + configOptions.add(new ConfigOption(CLIENT.config_autofish_aggressiveBiteDetection.getPath(),CLIENT.config_autofish_aggressiveBiteDetection.get(), "Aggressive Bite Detection")); + configOptions.add(new ConfigOption(CLIENT.config_autofish_handleProblems.getPath(), CLIENT.config_autofish_handleProblems.get(), "Handle Problems")); + configOptions.add(new ConfigOption(CLIENT.config_autofish_fastFishing.getPath(), CLIENT.config_autofish_fastFishing.get(), "Fast Fishing")); } - @SubscribeEvent - public static void onFileChange(final ModConfig.ConfigReloading configEvent) { - Logger.fatal("AutoFishMod config just got changed on the file system!"); + public static List getOrderedConfigValues() { + return configOptions; } + + public static void toggleConfigValue(List configPath) { + ConfigOption option = findConfigOption(configPath); + if (option == null) { + Logger.warning("Unknown config option path: %s", configPath); + } + if (option.valueType == ValueType.BOOL) { + option.boolValue = !option.boolValue; + saveConfigChange(option.configPath, option.boolValue); + } else if (option.valueType == ValueType.INT) { + int minVal, maxVal; + if (DotJoiner.join(option.configPath).equals(DotJoiner.join(CLIENT.config_autofish_recastDelay.getPath()))) { + minVal = 1; + maxVal = 10; + } else { + minVal = 0; + maxVal = 0; + } + option.intValue++; + if (option.intValue > maxVal) { + option.intValue = minVal; + } + saveConfigChange(option.configPath, option.intValue); + } + } + + + private static void saveConfigChange(List configPath, boolean newValue) { + CommentedFileConfig commentedFileConfig = CommentedFileConfig.of(AutoFishModConfig.ConfigFilePath); + commentedFileConfig.load(); + commentedFileConfig.set(configPath, newValue); + AutoFishModConfig.clientSpec.setConfig(commentedFileConfig); + commentedFileConfig.save(); + commentedFileConfig.close(); + } + + private static void saveConfigChange(List configPath, int newValue) { + CommentedFileConfig commentedFileConfig = CommentedFileConfig.of(AutoFishModConfig.ConfigFilePath); + commentedFileConfig.load(); + commentedFileConfig.set(configPath, newValue); + AutoFishModConfig.clientSpec.setConfig(commentedFileConfig); + commentedFileConfig.save(); + commentedFileConfig.close(); + } + + private static ConfigOption findConfigOption(List configPath) { + if (configPath == null) return null; + + for (ConfigOption option : configOptions) { + if (option.configPath.equals(configPath)) { + return option; + } + } + + return null; + } + + public static boolean autofishEnabled() { + ConfigOption option = findConfigOption(CLIENT.config_autofish_enable.getPath()); + return option == null ? false : option.boolValue; + } + public static boolean multiRodEnabled() { + ConfigOption option = findConfigOption(CLIENT.config_autofish_multirod.getPath()); + return option == null ? false : option.boolValue; + } + public static boolean breakPreventEnabled() { + ConfigOption option = findConfigOption(CLIENT.config_autofish_preventBreak.getPath()); + return option == null ? false : option.boolValue; + } + public static boolean entityClearProtectEnabled() { + ConfigOption option = findConfigOption(CLIENT.config_autofish_entityClearProtect.getPath()); + return option == null ? false : option.boolValue; + } + public static boolean fashFishingEnabled() { + ConfigOption option = findConfigOption(CLIENT.config_autofish_fastFishing.getPath()); + return option == null ? false : option.boolValue; + } + public static boolean aggressiveBiteDetectionEnabled() { + ConfigOption option = findConfigOption(CLIENT.config_autofish_aggressiveBiteDetection.getPath()); + return option == null ? false : option.boolValue; + } + public static boolean handleProblemsEnabled() { + ConfigOption option = findConfigOption(CLIENT.config_autofish_handleProblems.getPath()); + return option == null ? false : option.boolValue; + } + public static int recastDelay() { + ConfigOption option = findConfigOption(CLIENT.config_autofish_recastDelay.getPath()); + return option == null ? CONFIG_DEFAULT_AUTOFISH_RECASTDELAY : option.intValue; + } + } + diff --git a/src/main/java/net/unladenswallow/minecraft/autofish/config/ConfigOption.java b/src/main/java/net/unladenswallow/minecraft/autofish/config/ConfigOption.java new file mode 100644 index 0000000..a1dc195 --- /dev/null +++ b/src/main/java/net/unladenswallow/minecraft/autofish/config/ConfigOption.java @@ -0,0 +1,30 @@ +package net.unladenswallow.minecraft.autofish.config; + +import java.util.List; + +public class ConfigOption { + public ConfigOption(List path, boolean value, String label) { + valueType = ValueType.BOOL; + configPath = path; + boolValue = value; + configLabel = label; + } + + public ConfigOption(List path, int value, String label) { + valueType = ValueType.INT; + configPath = path; + intValue = value; + configLabel = label; + } + + public enum ValueType { + BOOL, + INT + } + + public ValueType valueType; + public List configPath; + public boolean boolValue; + public int intValue; + public String configLabel; +} diff --git a/src/main/java/net/unladenswallow/minecraft/autofish/events/EventListener.java b/src/main/java/net/unladenswallow/minecraft/autofish/events/EventListener.java index 87f7673..2f59213 100644 --- a/src/main/java/net/unladenswallow/minecraft/autofish/events/EventListener.java +++ b/src/main/java/net/unladenswallow/minecraft/autofish/events/EventListener.java @@ -23,7 +23,6 @@ import net.unladenswallow.minecraft.autofish.AutoFish; import net.unladenswallow.minecraft.autofish.ModAutoFish; import net.unladenswallow.minecraft.autofish.config.AutoFishModConfig; -import net.unladenswallow.minecraft.autofish.util.Logger; public class EventListener implements IWorldEventListener { @@ -47,7 +46,7 @@ public EventListener(AutoFish autoFish) { */ @SubscribeEvent public void onClientTickEvent(ClientTickEvent event) { - if (AutoFishModConfig.CLIENT.config_autofish_enable.get() && event.phase == Phase.END) { + if (event.phase == Phase.END) { _autoFish.onClientTick(); } } @@ -64,7 +63,7 @@ public void onServerTickEvent(ServerTickEvent event) { * all players, so that it will also affect all players that join a single player game that has * been opened to LAN play. */ - if (AutoFishModConfig.CLIENT.config_autofish_enable.get() && AutoFishModConfig.CLIENT.config_autofish_fastFishing.get() && event.phase == Phase.END) { + if (AutoFishModConfig.autofishEnabled() && AutoFishModConfig.fashFishingEnabled() && event.phase == Phase.END) { _autoFish.triggerBites(); } } @@ -76,7 +75,7 @@ public void onServerTickEvent(ServerTickEvent event) { */ @SubscribeEvent public void onPlaySoundEvent(PlaySoundEvent event) { - if (AutoFishModConfig.CLIENT.config_autofish_enable.get() && SoundEvents.ENTITY_FISHING_BOBBER_SPLASH.getName() == event.getSound().getSoundLocation()) { + if (AutoFishModConfig.autofishEnabled() && SoundEvents.ENTITY_FISHING_BOBBER_SPLASH.getName() == event.getSound().getSoundLocation()) { _autoFish.onBobberSplashDetected(event.getSound().getX(), event.getSound().getY(), event.getSound().getZ()); } } @@ -102,8 +101,8 @@ public void onWorldEvent_Load(WorldEvent.Load event) { @SubscribeEvent public void onPlayerUseItem(PlayerInteractEvent.RightClickItem event) { // Only do this on the client side - if (AutoFishModConfig.CLIENT.config_autofish_enable.get() && event.getWorld().isRemote) { - _autoFish.onPlayerUseItem(); + if (AutoFishModConfig.autofishEnabled() && event.getWorld().isRemote) { + _autoFish.onPlayerUseItem(event.getHand()); } } @@ -137,14 +136,14 @@ public void addParticle(IParticleData particleData, boolean alwaysRender, double @Override public void addParticle(IParticleData particleData, boolean ignoreRange, boolean minimizeLevel, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { - if (AutoFishModConfig.CLIENT.config_autofish_enable.get() && particleData.getType() == Particles.FISHING) { + if (AutoFishModConfig.autofishEnabled() && particleData.getType() == Particles.FISHING) { _autoFish.onWaterWakeDetected(x, y, z); } } @Override public void onEntityAdded(Entity entityIn) { - if (AutoFishModConfig.CLIENT.config_autofish_enable.get() && entityIn instanceof EntityXPOrb) { + if (AutoFishModConfig.autofishEnabled() && entityIn instanceof EntityXPOrb) { _autoFish.onXpOrbAdded(entityIn.posX, entityIn.posY, entityIn.posZ); } } diff --git a/src/main/java/net/unladenswallow/minecraft/autofish/events/KeyInputHandler.java b/src/main/java/net/unladenswallow/minecraft/autofish/events/KeyInputHandler.java index f43347e..a77c7e6 100644 --- a/src/main/java/net/unladenswallow/minecraft/autofish/events/KeyInputHandler.java +++ b/src/main/java/net/unladenswallow/minecraft/autofish/events/KeyInputHandler.java @@ -3,12 +3,11 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.util.InputMappings; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemFishingRod; import net.minecraftforge.client.event.InputEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.client.registry.ClientRegistry; -import net.unladenswallow.minecraft.autofish.util.Logger; +import net.unladenswallow.minecraft.autofish.ModAutoFish; +import net.unladenswallow.minecraft.autofish.gui.ConfigGui; public class KeyInputHandler { @@ -26,18 +25,10 @@ public void init() { @SubscribeEvent public void onKeyInput(InputEvent.KeyInputEvent event) { if (this.options.isPressed()) { - EntityPlayer player = Minecraft.getInstance().player; - if (playerIsHoldingFishingRod(player)) { -// Minecraft.getInstance().displayGuiScreen(new ConfigGui(Minecraft.getInstance().currentScreen)); + if (ModAutoFish.autoFish.playerIsHoldingRod()) { + Minecraft.getInstance().displayGuiScreen(new ConfigGui(Minecraft.getInstance().currentScreen)); } } } - private boolean playerIsHoldingFishingRod(EntityPlayer player) { - return (!Minecraft.getInstance().isGamePaused() - && player != null - && player.getHeldItemMainhand() != null - && player.getHeldItemMainhand().getItem() instanceof ItemFishingRod); - } - } diff --git a/src/main/java/net/unladenswallow/minecraft/autofish/gui/ConfigGui.java b/src/main/java/net/unladenswallow/minecraft/autofish/gui/ConfigGui.java index 22810bc..5b27f41 100644 --- a/src/main/java/net/unladenswallow/minecraft/autofish/gui/ConfigGui.java +++ b/src/main/java/net/unladenswallow/minecraft/autofish/gui/ConfigGui.java @@ -1,18 +1,120 @@ package net.unladenswallow.minecraft.autofish.gui; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; -//import net.minecraftforge.common.config.ConfigElement; -//import net.minecraftforge.common.config.Configuration; -//import net.minecraftforge.fml.client.config.GuiConfig; -import net.unladenswallow.minecraft.autofish.ModAutoFish; - -public class ConfigGui /* extends GuiConfig */ { - -// public ConfigGui(GuiScreen parent) { -// super(parent, -// new ConfigElement(ModAutoFish.configFile.getCategory(Configuration.CATEGORY_GENERAL)).getChildElements(), -// ModAutoFish.MODID, false, false, "AutoFish Forge Mod Options" -// ); -// this.titleLine2 = GuiConfig.getAbridgedConfigPath(ModAutoFish.configFile.toString()); -// } +import net.unladenswallow.minecraft.autofish.config.AutoFishModConfig; +import net.unladenswallow.minecraft.autofish.config.ConfigOption; +import net.unladenswallow.minecraft.autofish.config.ConfigOption.ValueType; +import net.unladenswallow.minecraft.autofish.util.Logger; + +public class ConfigGui extends GuiScreen { + + private static final int BUTTON_HEIGHT = 16; + private static final int BUTTON_WIDTH = 80; + private static final int BUTTON_START_Y = 40; + private static final int LABEL_X = 60; + private static final int BUTTON_X = 260; + // I don't know what this magic number means, but I saw it in Forge code, so there you go. + private static final int DRAW_STRING_MAGIC_NUMBER = 16777215; + private static final String BUTTON_TRUE_DISPLAY = "ON"; + private static final String BUTTON_FALSE_DISPLAY = "OFF"; + + private List