I came up with a solution that could work in your scenario, but it works a little bit differently than what you initially wanted to solve (the resolving of super calls):
public class OpenInitialHandler extends InitialServerLegacyDelegate {
public OpenInitialHandler(BungeeCord bungee, ListenerInfo listener) {
super(bungee, listener);
}
public OpenInitialHandler(ProxyServer proxyServer, ListenerInfo listener) {
super(proxyServer, listener);
}
}
public class InitialServerLegacyDelegate /* implements and extends whatever you need */ {
private static final Constructor<InitialDelegate> targetConstructor = InitialServer.getConstructors()[0];
private final InitialServer delegate;
protected InitialServerLegacyDelegate(BungeeCord bungee, ListenerInfo listener) {
this(bungee, listener);
}
protected InitialServerLegacyDelegate(ProxyServer proxyServer, ListenerInfo listener) {
try {
// This is the critical part.
// Instead of binding/checking the constructor parameter types
// at compile-time, this will be resolved at runtime.
delegate = targetConstructor.newInstance(proxyServer, listener);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// implement all neccessary interface methods here
// and simply make them delegate methods
}
Essentially, the InitialServerLegacyDelegate handles this legacy behaviour. It looks like a valid superclass (because it implements the same interfaces like InitialServer, but in reality it just delegates all calls to an instance of InitialServer which it resolves at runtime.
One problem you might be facing is: If your class gets a input at OpenInitialHandler(ProxyServer proxyServer, ListenerInfo listener) where ProxyServer is not of type BungeeCord. In this case, the implementation will fail with a ClassCastException if the newer dependency (with the BungeeCord constructor) is present and it gets a non-BungeeCord-input.
Delegate methods can easily be generated by Eclipse. For more detail, see this question on how to generate delegate methods in Eclipse.