From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Wed, 20 Jan 2021 13:08:53 -0600
Subject: [PATCH] Airplane Configuration

Co-developed-by: Ben Kerllenevich <me@notom3ga.me>

Airplane
Copyright (C) 2020 Technove LLC

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

diff --git a/pom.xml b/pom.xml
index ed18cc4a00761d3a4f435bcccbfd651a3201238d..a148af69be216d2869538d402d9a0d12c81b5df6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -166,6 +166,13 @@
             <version>1.1.0-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
+        <!-- Airplane Config -->
+        <dependency>
+            <groupId>com.github.technove</groupId>
+            <artifactId>AIR</artifactId>
+            <version>fe3dbb4420</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
     <!-- This builds a completely 'ready to start' jar with all dependencies inside -->
diff --git a/src/main/java/gg/airplane/AirplaneCommand.java b/src/main/java/gg/airplane/AirplaneCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..89c89e633f14b5820147e734b1b7ad8cadfdce80
--- /dev/null
+++ b/src/main/java/gg/airplane/AirplaneCommand.java
@@ -0,0 +1,65 @@
+package gg.airplane;
+
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import net.md_5.bungee.api.ChatColor;
+import net.minecraft.server.MinecraftServer;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class AirplaneCommand extends Command {
+
+    public AirplaneCommand() {
+        super("airplane");
+        this.description = "Airplane related commands";
+        this.usageMessage = "/airplane [reload | version]";
+        this.setPermission("bukkit.command.airplane");
+    }
+
+    @Override
+    public List<String> tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException {
+        if (args.length == 1) {
+            return Stream.of("reload", "version")
+              .filter(arg -> arg.startsWith(args[0].toLowerCase()))
+              .collect(Collectors.toList());
+        }
+        return Collections.emptyList();
+    }
+
+    @Override
+    public boolean execute(CommandSender sender, String commandLabel, String[] args) {
+        if (!testPermission(sender)) return true;
+        String prefix = ChatColor.of("#6a7eda") + "" + ChatColor.BOLD + "Airplane ✈ " + ChatColor.of("#e8ebf9");
+
+        if (args.length != 1) {
+            sender.sendMessage(prefix + "Usage: " + usageMessage);
+            args = new String[]{"version"};
+        }
+
+        if (args[0].equalsIgnoreCase("reload")) {
+            MinecraftServer console = MinecraftServer.getServer();
+            try {
+                AirplaneConfig.load();
+            } catch (IOException e) {
+                sender.sendMessage(Component.text("Failed to reload.", NamedTextColor.RED));
+                e.printStackTrace();
+                return true;
+            }
+            console.server.reloadCount++;
+
+            Command.broadcastCommandMessage(sender, prefix + "Airplane configuration has been reloaded.");
+        } else if (args[0].equalsIgnoreCase("version")) {
+            Command.broadcastCommandMessage(sender, prefix + "This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")");
+        }
+
+        return true;
+    }
+}
diff --git a/src/main/java/gg/airplane/AirplaneConfig.java b/src/main/java/gg/airplane/AirplaneConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..ab019b577002677a4ce788106f8e5a1d7757a2ae
--- /dev/null
+++ b/src/main/java/gg/airplane/AirplaneConfig.java
@@ -0,0 +1,50 @@
+package gg.airplane;
+
+import co.technove.air.AIR;
+import net.minecraft.server.MinecraftServer;
+import org.apache.logging.log4j.Level;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+public class AirplaneConfig {
+
+    private static AIR config;
+
+    public static void load() throws IOException {
+        File configFile = new File("airplane.air");
+        if (configFile.exists()) {
+            try (FileInputStream inputStream = new FileInputStream(configFile)) {
+                config = new AIR(inputStream);
+            }
+        } else {
+            config = new AIR();
+        }
+
+        config.setComment("info",
+          "Airplane Configuration",
+          "Read https://blog.airplane.gg/ to find out more about Airplane",
+          "Join our Discord to receive support & optimization help: https://discord.gg/3gtc45q");
+        config.getString("info.version", "1.0");
+
+        for (Method method : AirplaneConfig.class.getDeclaredMethods()) {
+            if (Modifier.isStatic(method.getModifiers()) && Modifier.isPrivate(method.getModifiers())) {
+                method.setAccessible(true);
+                try {
+                    method.invoke(null);
+                } catch (Throwable t) {
+                    MinecraftServer.LOGGER.log(Level.WARN, "Failed to load configuration option from " + method.getName(), t);
+                }
+            }
+        }
+
+        try (FileOutputStream outputStream = new FileOutputStream(configFile)) {
+            config.save(outputStream);
+        }
+    }
+
+}
diff --git a/src/main/java/gg/airplane/commands/AirplaneCommands.java b/src/main/java/gg/airplane/commands/AirplaneCommands.java
new file mode 100644
index 0000000000000000000000000000000000000000..807cf274619b8f7be839e249cb62b9817876ca04
--- /dev/null
+++ b/src/main/java/gg/airplane/commands/AirplaneCommands.java
@@ -0,0 +1,10 @@
+package gg.airplane.commands;
+
+import gg.airplane.AirplaneCommand;
+import net.minecraft.server.MinecraftServer;
+
+public class AirplaneCommands {
+    public static void init() {
+        MinecraftServer.getServer().server.getCommandMap().register("airplane", "Airplane", new AirplaneCommand());
+    }
+}
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index d902efdb8f2d42ea4c3933f7fa76ebe135ee09db..24a46ad36613faa5f5a1a12b70f7af886e1608ae 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -215,6 +215,8 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
         com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
         // Paper end
         com.tuinity.tuinity.config.TuinityConfig.init((java.io.File) options.valueOf("tuinity-settings")); // Tuinity - Server Config
+        gg.airplane.AirplaneConfig.load(); // Airplane - config
+        gg.airplane.commands.AirplaneCommands.init(); // Airplane - command
 
         this.setPVP(dedicatedserverproperties.pvp);
         this.setAllowFlight(dedicatedserverproperties.allowFlight);
