diff --git a/README.md b/README.md
index b6cabe3..e8151cd 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,56 @@
-# AutoReconnect
+# AutoReconnect [1.16+][Fabric]
-### Description
+This mod will automatically try to reconnect you back to a server if you got disconnected.
+By default, it will make 4 attempts after 3, 10, 30 and 60 seconds.
-This mod allows you to afk without fear of getting disconnected. It will make 4 attempts to reconnect you to the server you were disconnected from, with a delay of 3, 10, 60 and 300 seconds.
-After 4 failed attempts it will no longer try to reconnect.
+### Features
-(Btw you can exit the disconnect screen with Esc)
+* Multiple individually delayed reconnect attempts
+* Displays a countdown on the disconnect screen
+* Allows you to exit the disconnect screen quickly by pressing the escape key
+* Customizable
+ * Amount of attempts
+ * Delay between each attempt
+* Client side commands
+ * `/autoreconnect reload` Reloads the config and displays the settings in chat
+ * `/autoreconnect config []` Sets the delay between each attempt
+ `[]` must be a Nbt List Tag containing Integers, e.g. `[3, 10, 30, 60]` or `[I;3, 10, 30, 60]`
+* Support for several mods
+
+### Installation
+
+1. [Download](https://fabricmc.net/use/) and install Fabric
+2. Download [Fabric API]() and put the jar file into the mods folder
+3. Do the same for this mod
+
+### Compatibility
+
+* [ModMenu](https://www.curseforge.com/minecraft/mc-mods/modmenu)
+ Properly shows the mod icon, name and author
+ and provides a link for the curseforge project page and the github issues page
+* [AuthMe](https://www.curseforge.com/minecraft/mc-mods/auth-me)
+ Pauses the countdown if you click on the Re-authenticate button to revalidate the session of the game
+
+### Common questions
+
+* _Can I change the delay?_
+ Yes, you finally can with the latest version of this mod.
+* _Forge version?_
+ Simply no. I am not interested in developing mods using Forge.
+* _Version for 1.13.x or lower?_
+ Fabric does not exist for those versions.
+* _Version for 1.14.x or 1.15.x?_
+ If there is enough demand for it I might make a version for those versions of the game.
### Screenshots
-
+
-
-
-(Mod doesn't change the background or the font, I was using a resource pack when I took the screenshots)
+
### License
-This mod is available under the CC0 license. Feel free to learn from it and incorporate it in your own projects.
\ No newline at end of file
+This mod is available under the CC0 license.
+Feel free to learn from it and incorporate it in your own projects.
+If you actually just copy code or use this mod in a mod pack I would appreciate it if you mention me
+by linking the github page or the curseforge project page.
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 57d8e16..44215e3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
plugins {
- id 'fabric-loom' version '0.4-SNAPSHOT'
+ id 'fabric-loom' version '0.5-SNAPSHOT'
id 'maven-publish'
}
@@ -11,12 +11,12 @@ version = project.mod_version
group = project.maven_group
dependencies {
- minecraft "com.mojang:minecraft:1.16.1"
- mappings "net.fabricmc:yarn:1.16.1+build.21:v2"
- modImplementation "net.fabricmc:fabric-loader:0.9.3+build.207"
+ minecraft "com.mojang:minecraft:1.16"
+ mappings "net.fabricmc:yarn:1.16+build.4:v2"
+ modImplementation "net.fabricmc:fabric-loader:0.10.8"
//Fabric api
- modImplementation "net.fabricmc.fabric-api:fabric-api:0.18.0+build.387-1.16.1"
+ modImplementation "net.fabricmc.fabric-api:fabric-api:0.29.2+1.16"
}
processResources {
diff --git a/gradle.properties b/gradle.properties
index 932f5b9..b20611b 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -3,15 +3,15 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://fabricmc.net/use
- minecraft_version=1.16.1
- yarn_mappings=1.16.1+build.21
- loader_version=0.9.3+build.207
+ minecraft_version=1.16
+ yarn_mappings=1.16+build.4
+ loader_version=0.10.8
# Mod Properties
- mod_version = 1.0.1
+ mod_version = 1.1.0
maven_group = net.autoreconnect
- archives_base_name = auto-reconnect
+ archives_base_name = autoreconnect
# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
- fabric_version=0.18.0+build.387-1.16.1
\ No newline at end of file
+ fabric_version=0.29.2+1.16
\ No newline at end of file
diff --git a/src/main/java/net/autoreconnect/AutoReconnect.java b/src/main/java/net/autoreconnect/AutoReconnect.java
index 5f3f87c..f3bd1ca 100644
--- a/src/main/java/net/autoreconnect/AutoReconnect.java
+++ b/src/main/java/net/autoreconnect/AutoReconnect.java
@@ -1,57 +1,126 @@
package net.autoreconnect;
+import com.google.gson.Gson;
+import com.google.gson.JsonParseException;
+import com.mojang.brigadier.context.CommandContext;
import net.fabricmc.api.ModInitializer;
+import net.fabricmc.loader.api.FabricLoader;
+import net.minecraft.client.network.ClientCommandSource;
+import net.minecraft.client.network.ServerInfo;
+import net.minecraft.nbt.*;
+import net.minecraft.util.Formatting;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.stream.IntStream;
+
+import static com.mojang.brigadier.Command.SINGLE_SUCCESS;
+import static net.autoreconnect.ClientCommands.*;
+import static net.autoreconnect.Util.*;
+import static net.minecraft.command.arguments.NbtTagArgumentType.nbtTag;
+import static net.minecraft.util.Formatting.*;
public class AutoReconnect implements ModInitializer
{
- public static int attempt = 0;
- public static boolean connect = false;
-
- private static final AtomicInteger countdown = new AtomicInteger();
- private static Timer timer = null;
+ public static final String MOD_ID = "autoreconnect";
+ public static int[] delayList = { 3, 10, 30, 60 };
+ public static int ticks = -1;
+ public static int attempt = -1;
+ public static ServerInfo lastServerEntry = null;
+ public static boolean pause = false;
@Override
- public void onInitialize() { }
-
- public static void startCountdown(int seconds)
+ public void onInitialize()
{
- countdown.set(seconds);
- timer = new Timer();
- timer.scheduleAtFixedRate(new TimerTask()
+ ClientCommands.register(literal("reload").executes(AutoReconnect::cmdReload));
+ ClientCommands.register(literal("config").then(argument("delayList", nbtTag()).executes(AutoReconnect::cmdConfig)));
+ loadConfig();
+ }
+
+ private static int cmdReload(CommandContext ctx)
+ {
+ loadConfig();
+ return SINGLE_SUCCESS;
+ }
+
+ private static int cmdConfig(CommandContext ctx)
+ {
+ Tag tag = ctx.getArgument("delayList", Tag.class);
+ try
{
- @Override
- public void run()
+ // if tag is not a list or a list not containing integers it will pass null or an empty list
+ setDelayList(tag instanceof AbstractListTag ? ((AbstractListTag extends Tag>) tag).stream().filter(IntTag.class::isInstance).map(IntTag.class::cast).mapToInt(IntTag::getInt).toArray() : null);
+ saveConfig();
+ send(colored("Current configuration: " + Arrays.toString(delayList), GREEN));
+ }
+ catch (IOException | IllegalArgumentException ex)
+ {
+ send(err(ex));
+ }
+ return SINGLE_SUCCESS;
+ }
+
+ private static void loadConfig()
+ {
+ Path configPath = FabricLoader.getInstance().getConfigDir().resolve(MOD_ID + ".json");
+ try
+ {
+ setDelayList(new Gson().fromJson(Files.newBufferedReader(configPath), int[].class));
+ send(colored("Current configuration: " + Arrays.toString(delayList), GREEN));
+ }
+ catch (IOException | IllegalArgumentException | JsonParseException ex)
+ {
+ send(err(ex));
+ try
{
- if (countdown.decrementAndGet() <= 0)
- {
- connect = true;
- cancel();
- }
+ send(colored("Creating default config...", GREEN));
+ saveConfig();
}
- }, 1000, 1000);
+ catch (IOException ex2)
+ {
+ send(err(ex2));
+ }
+ }
}
- private static void cancel()
+ private static void saveConfig() throws IOException
{
- if (timer == null) return;
- timer.cancel();
- timer = null;
+ Path configPath = FabricLoader.getInstance().getConfigDir().resolve(MOD_ID + ".json");
+ File configFile = configPath.toFile();
+ // if file already exists or could successfully be created
+ if (configFile.exists() || configFile.createNewFile())
+ {
+ Files.write(configPath, new Gson().toJson(delayList).getBytes());
+ send(colored("Saved config", GREEN));
+ }
}
- public static void reset()
+ private static void setDelayList(int[] delayList) throws IllegalArgumentException
{
- cancel();
- attempt = 0;
- connect = false;
- System.out.println("reset");
+ // if null or empty or contains negatives or zeros
+ if (delayList == null || delayList.length == 0 || IntStream.of(delayList).anyMatch(i -> i <= 0))
+ throw new IllegalArgumentException("delayList must be a non-empty list of strictly positive integers");
+ AutoReconnect.delayList = delayList;
}
- public static int getCountdown()
+ public static void resetAttempts()
{
- return countdown.get();
+ ticks = -1;
+ attempt = -1;
+ log("reset");
}
-}
+
+ public static String getMessage()
+ {
+ return attempt < 0 ? "Could not reconnect" : String.format("Reconnect in %d...", ticks / 20 + 1);
+ }
+
+ public static int getColor()
+ {
+ return Optional.of(attempt < 0 ? RED : GREEN).filter(Formatting::isColor).map(Formatting::getColorValue).orElse(0xFFFFFF);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/autoreconnect/ClientCommands.java b/src/main/java/net/autoreconnect/ClientCommands.java
new file mode 100644
index 0000000..c34cab5
--- /dev/null
+++ b/src/main/java/net/autoreconnect/ClientCommands.java
@@ -0,0 +1,47 @@
+package net.autoreconnect;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.ArgumentType;
+import com.mojang.brigadier.builder.LiteralArgumentBuilder;
+import com.mojang.brigadier.builder.RequiredArgumentBuilder;
+import net.minecraft.client.network.ClientCommandSource;
+
+import java.util.*;
+
+import static net.autoreconnect.AutoReconnect.MOD_ID;
+
+public final class ClientCommands
+{
+ private ClientCommands() { }
+
+ private static final List> commands = new ArrayList<>();
+
+ public static boolean contains(String command)
+ {
+ // checks if command starts with ' ' and looks for a command literal to match the second word in the command
+ return command.startsWith(MOD_ID + " ") && commands.stream().map(LiteralArgumentBuilder::getLiteral).anyMatch(command.substring(MOD_ID.length() + 1).split(" ", 2)[0]::equals);
+ }
+
+ // register commands more or less the usual way
+ public static void register(LiteralArgumentBuilder command)
+ {
+ commands.add(command);
+ }
+
+ // variants of static methods literal and argument from net.minecraft.server.command.CommandManager replacing ServerCommandSource with ClientCommandSource
+ public static LiteralArgumentBuilder literal(String literal)
+ {
+ return LiteralArgumentBuilder.literal(literal);
+ }
+
+ public static RequiredArgumentBuilder argument(String name, ArgumentType type)
+ {
+ return RequiredArgumentBuilder.argument(name, type);
+ }
+
+ // actually register the commands and add the prefix node
+ public static void register(CommandDispatcher dispatcher)
+ {
+ commands.stream().map(literal(MOD_ID)::then).forEach(dispatcher::register);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/autoreconnect/Util.java b/src/main/java/net/autoreconnect/Util.java
new file mode 100644
index 0000000..76059df
--- /dev/null
+++ b/src/main/java/net/autoreconnect/Util.java
@@ -0,0 +1,55 @@
+package net.autoreconnect;
+
+import net.minecraft.SharedConstants;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.network.ClientPlayerEntity;
+import net.minecraft.text.LiteralText;
+import net.minecraft.text.Text;
+import net.minecraft.text.TextColor;
+import net.minecraft.util.Formatting;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.Objects;
+
+import static net.minecraft.util.Formatting.RED;
+
+public class Util
+{
+ // sends message to player if in game or logs to console with prefix '[]'
+ public static void send(Text text)
+ {
+ ClientPlayerEntity player = MinecraftClient.getInstance().player;
+ if (player == null)
+ {
+ // if player is not in game then print to console in error or default stream depending on weather the text is red or not
+ Logger logger = LogManager.getLogger("AutoReconnect");
+ if (Objects.equals(text.getStyle().getColor(), TextColor.fromFormatting(RED)))
+ {
+ logger.error("[AutoReconnect] " + text.getString());
+ }
+ else
+ {
+ logger.info("[AutoReconnect] " + text.getString());
+ }
+ }
+ else player.sendMessage(text, false);
+ }
+
+ // logs in console with prefix '[]'
+ public static void log(String format, Object... args)
+ {
+ LogManager.getLogger("AutoReconnect").info("[AutoReconnect] " + String.format(format, args));
+ }
+
+ // easy text creation methods
+ public static Text colored(String text, Formatting formatting)
+ {
+ return new LiteralText(text).formatted(formatting);
+ }
+
+ public static Text err(Exception ex)
+ {
+ return colored(ex.getClass().getSimpleName() + ": " + ex.getLocalizedMessage(), RED);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/autoreconnect/mixin/MixinClientPlayNetworkHandler.java b/src/main/java/net/autoreconnect/mixin/MixinClientPlayNetworkHandler.java
new file mode 100644
index 0000000..52ee1ad
--- /dev/null
+++ b/src/main/java/net/autoreconnect/mixin/MixinClientPlayNetworkHandler.java
@@ -0,0 +1,40 @@
+package net.autoreconnect.mixin;
+
+import com.mojang.authlib.GameProfile;
+import com.mojang.brigadier.CommandDispatcher;
+import net.autoreconnect.ClientCommands;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.network.ClientCommandSource;
+import net.minecraft.client.network.ClientPlayNetworkHandler;
+import net.minecraft.network.ClientConnection;
+import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket;
+import net.minecraft.server.command.CommandSource;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(ClientPlayNetworkHandler.class)
+public class MixinClientPlayNetworkHandler
+{
+ @Shadow
+ private CommandDispatcher commandDispatcher;
+
+ @SuppressWarnings("unchecked")
+ @Inject(method = "", at = @At("RETURN"))
+ private void init(MinecraftClient client, Screen screen, ClientConnection connection, GameProfile profile, CallbackInfo info)
+ {
+ // register commands to the initial dispatcher
+ ClientCommands.register((CommandDispatcher) (Object) commandDispatcher);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Inject(method = "onCommandTree", at = @At("TAIL"))
+ private void onCommandTree(CommandTreeS2CPacket packet, CallbackInfo info)
+ {
+ // register commands to the new dispatcher
+ ClientCommands.register((CommandDispatcher) (Object) commandDispatcher);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/autoreconnect/mixin/MixinClientPlayerEntity.java b/src/main/java/net/autoreconnect/mixin/MixinClientPlayerEntity.java
new file mode 100644
index 0000000..1432c4c
--- /dev/null
+++ b/src/main/java/net/autoreconnect/mixin/MixinClientPlayerEntity.java
@@ -0,0 +1,49 @@
+package net.autoreconnect.mixin;
+
+import net.autoreconnect.ClientCommands;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.network.ClientCommandSource;
+import net.minecraft.client.network.ClientPlayNetworkHandler;
+import net.minecraft.client.network.ClientPlayerEntity;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import static net.autoreconnect.Util.err;
+import static net.autoreconnect.Util.send;
+
+@Mixin(ClientPlayerEntity.class)
+public abstract class MixinClientPlayerEntity
+{
+ @Shadow @Final
+ protected MinecraftClient client;
+
+ @Shadow @Final
+ public ClientPlayNetworkHandler networkHandler;
+
+
+ @Inject(at = @At("HEAD"), method = "sendChatMessage", cancellable = true)
+ private void sendChatMessage(String message, CallbackInfo info)
+ {
+ if (message.charAt(0) == '/')
+ {
+ String command = message.substring(1);
+ if(ClientCommands.contains(command))
+ {
+ // prevent message from being sent
+ info.cancel();
+ try
+ {
+ networkHandler.getCommandDispatcher().execute(command, new ClientCommandSource(networkHandler, client));
+ }
+ catch (Exception ex)
+ {
+ send(err(ex));
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/autoreconnect/mixin/MixinDisconnectedScreen.java b/src/main/java/net/autoreconnect/mixin/MixinDisconnectedScreen.java
index 52e5ddb..d523122 100644
--- a/src/main/java/net/autoreconnect/mixin/MixinDisconnectedScreen.java
+++ b/src/main/java/net/autoreconnect/mixin/MixinDisconnectedScreen.java
@@ -6,32 +6,37 @@ import net.minecraft.client.gui.screen.DisconnectedScreen;
import net.minecraft.client.util.Window;
import net.minecraft.client.util.math.MatrixStack;
import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
-import static net.autoreconnect.AutoReconnect.attempt;
-import static net.autoreconnect.AutoReconnect.getCountdown;
+import static net.autoreconnect.AutoReconnect.*;
@Mixin(DisconnectedScreen.class)
public class MixinDisconnectedScreen
{
+ @Shadow
+ private int reasonHeight;
+
+ // make this screen closable by pressing escape
@Inject(at = @At("RETURN"), method = "shouldCloseOnEsc", cancellable = true)
private void shouldCloseOnEsc(CallbackInfoReturnable info)
{
info.setReturnValue(true);
}
+ // render the text overlay
@Inject(at = @At("RETURN"), method = "render")
private void render(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo info)
{
Window window = MinecraftClient.getInstance().getWindow();
TextRenderer renderer = MinecraftClient.getInstance().textRenderer;
- String text = attempt == -1 ? "Can not reconnect!" : "Reconnecting in " + getCountdown() + "...";
+ String text = getMessage();
renderer.draw(matrices, text,
- (window.getScaledWidth() - renderer.getWidth(text)) / 2F,
- (window.getScaledHeight() - renderer.fontHeight) / 3F,
- 0xFF4422);
+ (window.getScaledWidth() - renderer.getWidth(text)) / 2F, // centered
+ (window.getScaledHeight() - reasonHeight) / 2F - 9 * 4, // 9 * 2 higher than the title which is 9 * 2 higher than the disconnect reason
+ getColor());
}
}
\ No newline at end of file
diff --git a/src/main/java/net/autoreconnect/mixin/MixinMinecraftClient.java b/src/main/java/net/autoreconnect/mixin/MixinMinecraftClient.java
index aa65196..376b70a 100644
--- a/src/main/java/net/autoreconnect/mixin/MixinMinecraftClient.java
+++ b/src/main/java/net/autoreconnect/mixin/MixinMinecraftClient.java
@@ -5,76 +5,76 @@ import net.minecraft.client.gui.screen.*;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.network.ServerInfo;
import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static net.autoreconnect.AutoReconnect.*;
+import static net.autoreconnect.Util.log;
@Mixin(MinecraftClient.class)
public class MixinMinecraftClient
{
- private ServerInfo lastServerEntry;
+ @Shadow
+ public Screen currentScreen;
@Inject(at = @At("HEAD"), method = "setCurrentServerEntry")
- private void setCurrentServerEntry(ServerInfo info, CallbackInfo ci)
+ private void setCurrentServerEntry(ServerInfo serverInfo, CallbackInfo info)
{
- if (info != null)
+ //save last known non-null server entry
+ if (serverInfo != null)
{
- lastServerEntry = info;
+ lastServerEntry = serverInfo;
}
}
- @Inject(at = @At("RETURN"), method = "openScreen")
- private void openScreen(Screen screen, CallbackInfo info)
- {
- System.out.println(screen == null ? null : screen.getClass().getSimpleName());
- //TODO interpret disconnect reason
- //TODO revalidate session if needed
- if (screen instanceof DisconnectedScreen)
- {
- if (attempt < 0) return;
- switch (attempt++)
- {
- case 0:
- startCountdown(3);
- break;
- case 1:
- startCountdown(10);
- break;
- case 2:
- startCountdown(60);
- break;
- case 3:
- startCountdown(300);
- break;
- default:
- attempt = -1;
- }
- }
- else if (screen instanceof MultiplayerScreen || MinecraftClient.getInstance().player != null)
- {
- System.out.println(screen == null ? null : screen.getClass().getSimpleName());
- //TODO find better conditions to reset
- reset();
- }
- }
-
- @Inject(at = @At("RETURN"), method = "tick")
+ @Inject(at = @At("HEAD"), method = "tick")
private void tick(CallbackInfo info)
{
- //TODO find better way to call connect on main thread from after timer countdown finished
- if (connect)
+ // if not paused, decrements countdown until its negative, succeeds if its 0
+ if (ticks >= 0 && --ticks == 0)
{
- connect = false;
- MinecraftClient mc = MinecraftClient.getInstance();
if (lastServerEntry == null)
{
- attempt = -1;
- return;
+ resetAttempts();
+ }
+ else
+ {
+ MinecraftClient mc = MinecraftClient.getInstance();
+ mc.openScreen(new ConnectScreen(new MultiplayerScreen(new TitleScreen()), mc, lastServerEntry));
+ }
+ }
+ }
+
+ @Inject(at = @At("INVOKE"), method = "openScreen")
+ private void openScreen(Screen newScreen, CallbackInfo info)
+ {
+ // old and new screen must not be the same type, actually happens very often for some reason
+ if ((currentScreen == null ? null : currentScreen.getClass()) != (newScreen == null ? null : newScreen.getClass()))
+ {
+ if (currentScreen instanceof DisconnectedScreen && ( // exited disconnect screen using...
+ newScreen instanceof MultiplayerScreen || // ...cancel button on disconnect screen
+ newScreen instanceof TitleScreen || // ...escape key
+ newScreen != null && newScreen.getClass().getSimpleName().equals("AuthScreen")) || // ...AuthMe re-authenticate button
+ (currentScreen instanceof ConnectScreen && !(newScreen instanceof DisconnectedScreen))) // connection successful or cancelled using cancel button on connect screen
+ {
+ resetAttempts();
+ }
+ // player got disconnected
+ else if (newScreen instanceof DisconnectedScreen)
+ {
+ // if last known server is not null and next attempt is configured
+ if (lastServerEntry != null && ++attempt < delayList.length)
+ {
+ ticks = delayList[attempt] * 20;
+ }
+ else
+ {
+ resetAttempts();
+ }
+ log("lastServerEntry: %s, attempt: %d", lastServerEntry == null ? "null" : lastServerEntry.name, attempt);
}
- mc.disconnect();
- mc.openScreen(new ConnectScreen(new MultiplayerScreen(new TitleScreen()), mc, lastServerEntry));
}
}
}
\ No newline at end of file
diff --git a/src/main/resources/assets/countdown.png b/src/main/resources/assets/countdown.png
new file mode 100644
index 0000000..f025728
Binary files /dev/null and b/src/main/resources/assets/countdown.png differ
diff --git a/src/main/resources/assets/failed.png b/src/main/resources/assets/failed.png
new file mode 100644
index 0000000..0e5d79d
Binary files /dev/null and b/src/main/resources/assets/failed.png differ
diff --git a/src/main/resources/assets/icon.png b/src/main/resources/assets/icon.png
deleted file mode 100644
index 5d030cf..0000000
Binary files a/src/main/resources/assets/icon.png and /dev/null differ
diff --git a/src/main/resources/assets/icon16.png b/src/main/resources/assets/icon16.png
new file mode 100644
index 0000000..ad848ba
Binary files /dev/null and b/src/main/resources/assets/icon16.png differ
diff --git a/src/main/resources/assets/icon400.png b/src/main/resources/assets/icon400.png
new file mode 100644
index 0000000..fee7859
Binary files /dev/null and b/src/main/resources/assets/icon400.png differ
diff --git a/src/main/resources/assets/screenshot_countdown.png b/src/main/resources/assets/screenshot_countdown.png
deleted file mode 100644
index 3a74919..0000000
Binary files a/src/main/resources/assets/screenshot_countdown.png and /dev/null differ
diff --git a/src/main/resources/assets/screenshot_failed.png b/src/main/resources/assets/screenshot_failed.png
deleted file mode 100644
index 73d2f00..0000000
Binary files a/src/main/resources/assets/screenshot_failed.png and /dev/null differ
diff --git a/src/main/resources/autoreconnect.mixins.json b/src/main/resources/autoreconnect.mixins.json
index dad24b4..15f1cab 100644
--- a/src/main/resources/autoreconnect.mixins.json
+++ b/src/main/resources/autoreconnect.mixins.json
@@ -6,7 +6,9 @@
"mixins": [
],
"client": [
+ "MixinClientPlayNetworkHandler",
"MixinDisconnectedScreen",
+ "MixinClientPlayerEntity",
"MixinMinecraftClient"
],
"injectors": {
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index 75f4d07..54d14dd 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -1,22 +1,23 @@
{
"schemaVersion": 1,
"id": "autoreconnect",
- "version": "1.0.1",
+ "version": "1.1.0",
"name": "AutoReconnect",
- "description": "This mod allows you to afk without fear of getting disconnected. It will make 4 attempts to reconnect you to the server you were disconnected from, with a delay of 3, 10, 60 and 300 seconds.",
+ "description": "This mod will automatically try to reconnect you back to a server if you got disconnected.\nBy default, it will make 4 attempts after 3, 10, 30 and 60 seconds.",
"authors": [
"Bstn1802"
],
"contact": {
- "homepage": "https://github.com/Bstn1802",
- "sources": "https://github.com/Bstn1802/AutoReconnect"
+ "homepage": "https://www.curseforge.com/minecraft/mc-mods/autoreconnect",
+ "sources": "https://github.com/Bstn1802/AutoReconnect",
+ "issues": "https://github.com/Bstn1802/AutoReconnect/issues"
},
"license": "CC0-1.0",
- "icon": "assets/icon.png",
+ "icon": "assets/icon16.png",
- "environment": "*",
+ "environment": "client",
"entrypoints": {
"main": [
"net.autoreconnect.AutoReconnect"
@@ -29,9 +30,6 @@
"depends": {
"fabricloader": ">=0.7.4",
"fabric": "*",
- "minecraft": "1.16.x"
- },
- "suggests": {
- "flamingo": "*"
+ "minecraft": ">=1.16"
}
}