Multi-port supports w/ Removes tickable of enchant table
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
package io.akarin.server.core;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import io.akarin.api.LogWrapper;
|
||||
|
||||
public class AkarinGlobalConfig {
|
||||
|
||||
private static File CONFIG_FILE;
|
||||
private static final String HEADER = "This is the global configuration file for Akarin.\n"
|
||||
+ "Some options may impact gameplay, so use with caution,\n"
|
||||
+ "and make sure you know what each option does before configuring.\n"
|
||||
+ "\n"
|
||||
+ "Akarin forums: https://akarin.io/ \n";
|
||||
/*========================================================================*/
|
||||
public static YamlConfiguration config;
|
||||
static int version;
|
||||
/*========================================================================*/
|
||||
public static void init(File configFile) {
|
||||
CONFIG_FILE = configFile;
|
||||
config = new YamlConfiguration();
|
||||
try {
|
||||
config.load(CONFIG_FILE);
|
||||
} catch (IOException ex) {
|
||||
} catch (InvalidConfigurationException ex) {
|
||||
LogWrapper.logger.error("Could not load akarin.yml, please correct your syntax errors", ex);
|
||||
throw Throwables.propagate(ex);
|
||||
}
|
||||
config.options().header(HEADER);
|
||||
config.options().copyDefaults(true);
|
||||
|
||||
version = getInt("config-version", 1);
|
||||
set("config-version", 1);
|
||||
readConfig(AkarinGlobalConfig.class, null);
|
||||
}
|
||||
|
||||
static void readConfig(Class<?> clazz, Object instance) {
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (Modifier.isPrivate(method.getModifiers())) {
|
||||
if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) {
|
||||
try {
|
||||
method.setAccessible(true);
|
||||
method.invoke(instance);
|
||||
} catch (InvocationTargetException ex) {
|
||||
throw Throwables.propagate(ex.getCause());
|
||||
} catch (Exception ex) {
|
||||
LogWrapper.logger.error("Error invoking " + method, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
config.save(CONFIG_FILE);
|
||||
} catch (IOException ex) {
|
||||
LogWrapper.logger.error("Could not save " + CONFIG_FILE, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Pattern SPACE = Pattern.compile(" ");
|
||||
private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]");
|
||||
public static int getSeconds(String str) {
|
||||
str = SPACE.matcher(str).replaceAll("");
|
||||
final char unit = str.charAt(str.length() - 1);
|
||||
str = NOT_NUMERIC.matcher(str).replaceAll("");
|
||||
double num;
|
||||
try {
|
||||
num = Double.parseDouble(str);
|
||||
} catch (Exception e) {
|
||||
num = 0D;
|
||||
}
|
||||
switch (unit) {
|
||||
case 'd': num *= (double) 60*60*24; break;
|
||||
case 'h': num *= (double) 60*60; break;
|
||||
case 'm': num *= 60; break;
|
||||
default: case 's': break;
|
||||
}
|
||||
return (int) num;
|
||||
}
|
||||
|
||||
protected static String timeSummary(int seconds) {
|
||||
String time = "";
|
||||
|
||||
if (seconds > 60 * 60 * 24) {
|
||||
time += TimeUnit.SECONDS.toDays(seconds) + "d";
|
||||
seconds %= 60 * 60 * 24;
|
||||
}
|
||||
|
||||
if (seconds > 60 * 60) {
|
||||
time += TimeUnit.SECONDS.toHours(seconds) + "h";
|
||||
seconds %= 60 * 60;
|
||||
}
|
||||
|
||||
if (seconds > 0) {
|
||||
time += TimeUnit.SECONDS.toMinutes(seconds) + "m";
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
private static void set(String path, Object val) {
|
||||
config.set(path, val);
|
||||
}
|
||||
|
||||
private static boolean getBoolean(String path, boolean def) {
|
||||
config.addDefault(path, def);
|
||||
return config.getBoolean(path, config.getBoolean(path));
|
||||
}
|
||||
|
||||
private static double getDouble(String path, double def) {
|
||||
config.addDefault(path, def);
|
||||
return config.getDouble(path, config.getDouble(path));
|
||||
}
|
||||
|
||||
private static float getFloat(String path, float def) {
|
||||
// TODO: Figure out why getFloat() always returns the default value.
|
||||
return (float) getDouble(path, def);
|
||||
}
|
||||
|
||||
private static int getInt(String path, int def) {
|
||||
config.addDefault(path, def);
|
||||
return config.getInt(path, config.getInt(path));
|
||||
}
|
||||
|
||||
private static <T> List getList(String path, T def) {
|
||||
config.addDefault(path, def);
|
||||
return config.getList(path, config.getList(path));
|
||||
}
|
||||
|
||||
private static String getString(String path, String def) {
|
||||
config.addDefault(path, def);
|
||||
return config.getString(path, config.getString(path));
|
||||
}
|
||||
/*========================================================================*/
|
||||
public static List<String> extraAddress;
|
||||
private static void extraAddress() {
|
||||
extraAddress = getList("network.extra-local-address", Lists.newArrayList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.akarin.server.mixin.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.bukkit.craftbukkit.Main;
|
||||
@@ -10,12 +11,13 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import io.akarin.api.LogWrapper;
|
||||
import io.akarin.server.core.AkarinGlobalConfig;
|
||||
|
||||
@Mixin(value = Main.class, remap = false)
|
||||
public class Bootstrap {
|
||||
@Inject(method = "main([Ljava/lang/String;)V", at = @At("HEAD"))
|
||||
private static void configureMixin(CallbackInfo info) {
|
||||
;
|
||||
private static void premain(CallbackInfo info) {
|
||||
AkarinGlobalConfig.init(new File("akarin.yml"));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package io.akarin.server.mixin.core;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import net.minecraft.server.TileEntityEnchantTable;
|
||||
|
||||
@Mixin(value = TileEntityEnchantTable.class, remap = false)
|
||||
public class MixinTileEntityEnchantTable {
|
||||
@Overwrite
|
||||
public void e() {} // No tickable
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package io.akarin.server.mixin.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -20,6 +21,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import com.google.common.collect.Lists;
|
||||
import io.akarin.api.LocalAddress;
|
||||
import io.akarin.api.WrappedCollections;
|
||||
import io.akarin.server.core.AkarinGlobalConfig;
|
||||
import io.akarin.server.core.ChannelAdapter;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
@@ -76,7 +78,7 @@ public class NonblockingServerConnection {
|
||||
*/
|
||||
@Overwrite
|
||||
public void a(InetAddress address, int port) throws IOException {
|
||||
registerChannels(Collections.singleton(LocalAddress.create(address, port)));
|
||||
registerChannels(Lists.newArrayList(LocalAddress.create(address, port)));
|
||||
}
|
||||
|
||||
public void registerChannels(Collection<LocalAddress> data) throws IOException {
|
||||
@@ -95,6 +97,16 @@ public class NonblockingServerConnection {
|
||||
|
||||
ServerBootstrap bootstrap = new ServerBootstrap().channel(channelClass).childHandler(ChannelAdapter.create(h)).group(loopGroup);
|
||||
synchronized (g) {
|
||||
data.addAll(Lists.transform(AkarinGlobalConfig.extraAddress, s -> {
|
||||
String[] info = s.split(":");
|
||||
try {
|
||||
logger.info("Attempt to bind server on " + s);
|
||||
return LocalAddress.create(InetAddress.getByName(info[0]), Integer.valueOf(info[1]));
|
||||
} catch (NumberFormatException | UnknownHostException ex) {
|
||||
logger.error("Error on lookup additional host, wrong format?", ex);
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
data.forEach(address -> g.add(bootstrap.localAddress(address.host(), address.port()).bind().syncUninterruptibly())); // supports multi-port bind
|
||||
}
|
||||
}
|
||||
@@ -106,7 +118,7 @@ public class NonblockingServerConnection {
|
||||
public void b() {
|
||||
this.d = false;
|
||||
try {
|
||||
synchronized (g) {
|
||||
synchronized (g) { // safe fixes
|
||||
for (ChannelFuture channel : g) channel.channel().close().sync();
|
||||
}
|
||||
} catch (InterruptedException ex) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"MixinPaperConfig",
|
||||
"MixinCraftServer",
|
||||
"MixinVersionCommand",
|
||||
"MixinMinecraftServer"
|
||||
"MixinMinecraftServer",
|
||||
"MixinTileEntityEnchantTable"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user