From fdc9dd192f39efb4e2a22b8ea93c272c08c56c67 Mon Sep 17 00:00:00 2001 From: tr7zw Date: Thu, 5 Mar 2020 22:31:50 +0100 Subject: [PATCH] Add config, yapfa command and basic settings --- .../java/de/tr7zw/yapfa/YapfaCommand.java | 129 +++++++++++ src/main/java/de/tr7zw/yapfa/YapfaConfig.java | 219 ++++++++++++++++++ .../net/minecraft/server/DedicatedServer.java | 9 + .../java/net/minecraft/server/Entity.java | 3 +- .../net/minecraft/server/EntityLiving.java | 6 +- 5 files changed, 364 insertions(+), 2 deletions(-) create mode 100644 src/main/java/de/tr7zw/yapfa/YapfaCommand.java create mode 100644 src/main/java/de/tr7zw/yapfa/YapfaConfig.java diff --git a/src/main/java/de/tr7zw/yapfa/YapfaCommand.java b/src/main/java/de/tr7zw/yapfa/YapfaCommand.java new file mode 100644 index 000000000..76d83f3db --- /dev/null +++ b/src/main/java/de/tr7zw/yapfa/YapfaCommand.java @@ -0,0 +1,129 @@ +package de.tr7zw.yapfa; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +import com.google.common.base.Functions; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +import net.minecraft.server.MinecraftKey; +import net.minecraft.server.MinecraftServer; + +public class YapfaCommand extends Command { + + public YapfaCommand(String name) { + super(name); + this.description = "YAPFA related commands"; + this.usageMessage = "/yapfa [help | reload | info | version]"; + this.setPermission("bukkit.command.yapfa"); + } + + @Override + public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { + if (args.length <= 1) + return getListMatchingLast(args, "help", "info", "reload", "version"); + return Collections.emptyList(); + } + + // Code from Mojang - copyright them + public static List getListMatchingLast(String[] args, String... matches) { + return getListMatchingLast(args, (Collection) Arrays.asList(matches)); + } + + public static boolean matches(String s, String s1) { + return s1.regionMatches(true, 0, s, 0, s.length()); + } + + public static List getListMatchingLast(String[] strings, Collection collection) { + String last = strings[strings.length - 1]; + ArrayList results = Lists.newArrayList(); + + if (!collection.isEmpty()) { + Iterator iterator = Iterables.transform(collection, Functions.toStringFunction()).iterator(); + + while (iterator.hasNext()) { + String s1 = (String) iterator.next(); + + if (matches(last, s1)) { + results.add(s1); + } + } + + if (results.isEmpty()) { + iterator = collection.iterator(); + + while (iterator.hasNext()) { + Object object = iterator.next(); + + if (object instanceof MinecraftKey && matches(last, ((MinecraftKey) object).getKey())) { + results.add(String.valueOf(object)); + } + } + } + } + + return results; + } + // end copy stuff + + @Override + public boolean execute(CommandSender sender, String commandLabel, String[] args) { + if (!testPermission(sender)) return true; + + if (args.length == 0) { + sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); + return false; + } + + switch (args[0].toLowerCase(Locale.ENGLISH)) { + case "info": + doInfo(sender); + break; + case "reload": + doReload(sender); + break; + case "ver": + case "version": + Command ver = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version"); + if (ver != null) { + ver.execute(sender, commandLabel, new String[0]); + break; + } + // else - fall through to default + default: + sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); + return false; + } + + return true; + } + + private void doInfo(CommandSender sender) { + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Last tick took " + Bukkit.getLastTickMs() + "ms"); + //TODO + } + + private void doReload(CommandSender sender) { + Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues."); + Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); + + MinecraftServer console = MinecraftServer.getServer(); + de.tr7zw.yapfa.YapfaConfig.init(new File("yapfa.yml")); + console.server.reloadCount++; + + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "YAPFA config reload complete."); + } +} \ No newline at end of file diff --git a/src/main/java/de/tr7zw/yapfa/YapfaConfig.java b/src/main/java/de/tr7zw/yapfa/YapfaConfig.java new file mode 100644 index 000000000..9711cbc52 --- /dev/null +++ b/src/main/java/de/tr7zw/yapfa/YapfaConfig.java @@ -0,0 +1,219 @@ +package de.tr7zw.yapfa; + +import com.destroystokyo.paper.io.chunk.ChunkTaskManager; +import com.google.common.base.Strings; +import com.google.common.base.Throwables; + +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.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.regex.Pattern; + +import com.google.common.collect.Lists; +import net.minecraft.server.MinecraftServer; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import co.aikar.timings.Timings; +import co.aikar.timings.TimingsManager; +import org.spigotmc.SpigotConfig; +import org.spigotmc.WatchdogThread; + +public class YapfaConfig { + + private static File CONFIG_FILE; + private static final String HEADER = "This is the main configuration file for YAPFA.\n" + + "YAPFA contains many breaking changes and settings, so know what you are doing!\n" + + "You have been warned!\n"; + /*========================================================================*/ + public static YamlConfiguration config; + static int version; + static Map commands; + private static boolean verbose; + private static boolean fatalError; + /*========================================================================*/ + private static boolean metricsStarted; + + public static void init(File configFile) { + CONFIG_FILE = configFile; + config = new YamlConfiguration(); + try { + config.load(CONFIG_FILE); + } catch (IOException ex) { + } catch (InvalidConfigurationException ex) { + Bukkit.getLogger().log(Level.SEVERE, "Could not load yapfa.yml, please correct your syntax errors", ex); + throw Throwables.propagate(ex); + } + config.options().header(HEADER); + config.options().copyDefaults(true); + verbose = getBoolean("verbose", false); + + commands = new HashMap(); + commands.put("yapfa", new YapfaCommand("yapfa")); + + version = getInt("config-version", 1); + set("config-version", 1); + readConfig(YapfaConfig.class, null); + } + + protected static void logError(String s) { + Bukkit.getLogger().severe(s); + } + + protected static void fatal(String s) { + fatalError = true; + throw new RuntimeException("Fatal yapfa.yml config error: " + s); + } + + protected static void log(String s) { + if (verbose) { + Bukkit.getLogger().info(s); + } + } + + public static void registerCommands() { + for (Map.Entry entry : commands.entrySet()) { + MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Yapfa", entry.getValue()); + } + } + + 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) { + Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex); + } + } + } + } + + try { + config.save(CONFIG_FILE); + } catch (IOException ex) { + Bukkit.getLogger().log(Level.SEVERE, "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 *= (double) 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, (double) def); + } + + private static int getInt(String path, int def) { + config.addDefault(path, def); + return config.getInt(path, config.getInt(path)); + } + + private static List getList(String path, T def) { + config.addDefault(path, def); + return (List) 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 boolean disableEntityWaterChecks = false; + private static void disableEntityWaterChecks() { + disableEntityWaterChecks = getBoolean("settings.disableEntityWaterChecks", false); + } + + public static boolean disableEntityStuckChecks = false; + private static void disableEntityStuckChecks() { + disableEntityStuckChecks = getBoolean("settings.disableEntityStuckChecks", false); + } + + public static boolean disablePlayerOutOfWorldBorderCheck = false; + private static void disablePlayerOutOfWorldBorderCheck() { + disablePlayerOutOfWorldBorderCheck = getBoolean("settings.disablePlayerOutOfWorldBorderCheck", false); + } + + public static boolean disableEntityCollisions = false; + private static void disableEntityCollisions() { + disableEntityCollisions = getBoolean("settings.disableEntityCollisions", false); + } + + public static int checkEntityBlockCollisionTicks = 1; + private static void checkEntityBlockCollisionTicks() { + checkEntityBlockCollisionTicks = getInt("settings.checkEntityBlockCollisionTicks", 1); + } + + public static boolean disableEntityCollisionboxes = false; + private static void disableEntityCollisionboxes() { + disableEntityCollisionboxes = getBoolean("settings.disableEntityCollisionboxes", false); + } + +} \ No newline at end of file diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java index 610826c9e..2ed69f567 100644 --- a/src/main/java/net/minecraft/server/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/DedicatedServer.java @@ -194,6 +194,15 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer com.destroystokyo.paper.PaperConfig.registerCommands(); com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now // Paper end + // YAPFA start + try { + de.tr7zw.yapfa.YapfaConfig.init(new File("yapfa.yml")); + } catch (Exception e) { + DedicatedServer.LOGGER.error("Unable to load server configuration", e); + return false; + } + de.tr7zw.yapfa.YapfaConfig.registerCommands(); + // YAPFA end com.tuinity.tuinity.config.TuinityConfig.init((File) options.valueOf("tuinity-settings")); // Tuinity - Server Config this.setSpawnAnimals(dedicatedserverproperties.spawnAnimals); diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java index fa1fb7a40..8c21a1e73 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -798,6 +798,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke try { this.inLava = false; + if(MinecraftServer.currentTick % de.tr7zw.yapfa.YapfaConfig.checkEntityBlockCollisionTicks == 0) // YAPFA this.checkBlockCollisions(); } catch (Throwable throwable) { CrashReport crashreport = CrashReport.a(throwable, "Checking entity block collision"); @@ -922,7 +923,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke VoxelShapeCollision voxelshapecollision = VoxelShapeCollision.a(this); VoxelShape voxelshape = this.world.getWorldBorder().a(); Stream stream = VoxelShapes.c(voxelshape, VoxelShapes.a(axisalignedbb.shrink(1.0E-7D)), OperatorBoolean.AND) ? Stream.empty() : Stream.of(voxelshape); - Stream stream1 = this.world.b(this, axisalignedbb.a(vec3d), (Set) ImmutableSet.of()); + Stream stream1 = de.tr7zw.yapfa.YapfaConfig.disableEntityCollisionboxes ? Stream.empty() : this.world.b(this, axisalignedbb.a(vec3d), (Set) ImmutableSet.of()); // YAPFA StreamAccumulator streamaccumulator = new StreamAccumulator<>(Stream.concat(stream1, stream)); Vec3D vec3d1 = vec3d.g() == 0.0D ? vec3d : a(this, vec3d, axisalignedbb, this.world, voxelshapecollision, streamaccumulator); boolean flag = vec3d.x != vec3d1.x; diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java index 5b402690d..839b0f514 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -246,6 +246,7 @@ public abstract class EntityLiving extends Entity { this.world.getMethodProfiler().enter("livingEntityBaseTick"); boolean flag = this instanceof EntityHuman; + if(!de.tr7zw.yapfa.YapfaConfig.disableEntityStuckChecks) { // YAPFA start if (this.isAlive()) { if (this.inBlock()) { this.damageEntity(DamageSource.STUCK, 1.0F); @@ -261,6 +262,7 @@ public abstract class EntityLiving extends Entity { } } } + } // YAPFA end if (this.isFireProof() || this.world.isClientSide) { this.extinguish(); @@ -269,6 +271,7 @@ public abstract class EntityLiving extends Entity { boolean flag1 = flag && ((EntityHuman) this).abilities.isInvulnerable; if (this.isAlive()) { + if(!de.tr7zw.yapfa.YapfaConfig.disableEntityWaterChecks) { // YAPFA start if (this.a(TagsFluid.WATER) && this.world.getType(new BlockPosition(this.locX(), this.getHeadY(), this.locZ())).getBlock() != Blocks.BUBBLE_COLUMN) { if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { // Paper - use OBFHELPER so it can be overridden this.setAirTicks(this.l(this.getAirTicks())); @@ -294,6 +297,7 @@ public abstract class EntityLiving extends Entity { } else if (this.getAirTicks() < this.bw()) { this.setAirTicks(this.m(this.getAirTicks())); } + } // YAPFA end if (!this.world.isClientSide) { BlockPosition blockposition = new BlockPosition(this); @@ -2640,7 +2644,7 @@ public abstract class EntityLiving extends Entity { this.e(new Vec3D((double) this.aZ, (double) this.ba, (double) this.bb)); this.world.getMethodProfiler().exit(); this.world.getMethodProfiler().enter("push"); - if (this.bn > 0) { + if (!de.tr7zw.yapfa.YapfaConfig.disableEntityCollisions && this.bn > 0) { // YAPFA --this.bn; this.a(axisalignedbb, this.getBoundingBox()); } -- 2.25.1.windows.1