diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml
index b826f61a..6d12b673 100644
--- a/bootstrap/pom.xml
+++ b/bootstrap/pom.xml
@@ -29,12 +29,16 @@
bungeecord-repo
https://oss.sonatype.org/content/repositories/snapshots
+
+ velocity-repo
+ https://repo.velocitypowered.com/snapshots/
+
bukkit
bungeecord
sponge
standalone
-
+ velocity
\ No newline at end of file
diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml
new file mode 100644
index 00000000..22fe9211
--- /dev/null
+++ b/bootstrap/velocity/pom.xml
@@ -0,0 +1,72 @@
+
+
+ 4.0.0
+
+ org.geysermc
+ bootstrap-parent
+ 1.0-SNAPSHOT
+ ../
+
+ bootstrap-velocity
+
+
+ org.geysermc
+ connector
+ 1.0-SNAPSHOT
+ compile
+
+
+ com.velocitypowered
+ velocity-api
+ 1.0.0-SNAPSHOT
+ provided
+
+
+
+ ${outputName}-Velocity
+
+
+ src/main/resources/
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.1
+
+
+ package
+
+ shade
+
+
+ true
+
+
+
+
+
+
+ *:*
+
+ META-INF/*
+
+
+
+
+
+ com.google.code.gson:*
+ io.netty:*
+ org.slf4j:*
+ org.ow2.asm:*
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java
new file mode 100644
index 00000000..2fab448d
--- /dev/null
+++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.platform.velocity;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import lombok.Getter;
+
+import org.geysermc.common.IGeyserConfiguration;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Map;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@Getter
+public class GeyserVelocityConfiguration implements IGeyserConfiguration {
+
+ private BedrockConfiguration bedrock;
+ private RemoteConfiguration remote;
+
+ @JsonProperty("floodgate-key-file")
+ private String floodgateKeyFile;
+
+ private Map userAuths;
+
+ @JsonProperty("ping-passthrough")
+ private boolean pingPassthrough;
+
+ @JsonProperty("max-players")
+ private int maxPlayers;
+
+ @JsonProperty("debug-mode")
+ private boolean debugMode;
+
+ @JsonProperty("general-thread-pool")
+ private int generalThreadPool;
+
+ @JsonProperty("allow-third-party-capes")
+ private boolean allowThirdPartyCapes;
+
+ private MetricsInfo metrics;
+
+ @Override
+ public Path getFloodgateKeyFile() {
+ return Paths.get(floodgateKeyFile);
+ }
+
+ @Getter
+ public static class BedrockConfiguration implements IBedrockConfiguration {
+
+ private String address;
+ private int port;
+
+ private String motd1;
+ private String motd2;
+ }
+
+ @Getter
+ public static class RemoteConfiguration implements IRemoteConfiguration {
+
+ private String address;
+ private int port;
+
+ private String motd1;
+ private String motd2;
+
+ @JsonProperty("auth-type")
+ private String authType;
+ }
+
+ @Getter
+ public static class UserAuthenticationInfo implements IUserAuthenticationInfo {
+ private String email;
+ private String password;
+ }
+
+ @Getter
+ public static class MetricsInfo implements IMetricsInfo {
+
+ private boolean enabled;
+
+ @JsonProperty("uuid")
+ private String uniqueId;
+ }
+}
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityLogger.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityLogger.java
new file mode 100644
index 00000000..623c6481
--- /dev/null
+++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityLogger.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.platform.velocity;
+
+import lombok.AllArgsConstructor;
+
+import org.geysermc.common.logger.IGeyserLogger;
+import org.slf4j.Logger;
+
+@AllArgsConstructor
+public class GeyserVelocityLogger implements IGeyserLogger {
+
+ private Logger logger;
+ private boolean debugMode;
+
+ @Override
+ public void severe(String message) {
+ logger.error(message);
+ }
+
+ @Override
+ public void severe(String message, Throwable error) {
+ logger.error(message, error);
+ }
+
+ @Override
+ public void error(String message) {
+ logger.error(message);
+ }
+
+ @Override
+ public void error(String message, Throwable error) {
+ logger.error(message, error);
+ }
+
+ @Override
+ public void warning(String message) {
+ logger.warn(message);
+ }
+
+ @Override
+ public void info(String message) {
+ logger.info(message);
+ }
+
+ @Override
+ public void debug(String message) {
+ if (debugMode)
+ info(message);
+ }
+
+ @Override
+ public void setDebug(boolean debugMode) {
+ this.debugMode = debugMode;
+ }
+}
\ No newline at end of file
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java
new file mode 100644
index 00000000..4020b81e
--- /dev/null
+++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.platform.velocity;
+
+import com.google.inject.Inject;
+
+import com.velocitypowered.api.event.Subscribe;
+import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
+import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
+import com.velocitypowered.api.plugin.Plugin;
+
+import org.geysermc.common.PlatformType;
+import org.geysermc.common.bootstrap.IGeyserBootstrap;
+import org.geysermc.connector.GeyserConnector;
+import org.geysermc.connector.utils.FileUtils;
+import org.slf4j.Logger;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.UUID;
+
+@Plugin(id = "geyser", name = GeyserConnector.NAME + "-Velocity", version = GeyserConnector.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
+public class GeyserVelocityPlugin implements IGeyserBootstrap {
+
+ @Inject
+ private Logger logger;
+
+ private GeyserVelocityConfiguration geyserConfig;
+ private GeyserVelocityLogger geyserLogger;
+
+
+ @Override
+ public void onEnable() {
+ try {
+ File configDir = new File("plugins/" + GeyserConnector.NAME + "-Velocity/");
+ if (!configDir.exists())
+ configDir.mkdir();
+ File configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
+ geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class);
+ } catch (IOException ex) {
+ logger.warn("Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex);
+ ex.printStackTrace();
+ }
+
+ this.geyserLogger = new GeyserVelocityLogger(logger, geyserConfig.isDebugMode());
+ GeyserConnector.start(PlatformType.VELOCITY, this);
+ }
+
+ @Override
+ public void onDisable() {
+ GeyserConnector.stop();
+ }
+
+ @Override
+ public GeyserVelocityConfiguration getGeyserConfig() {
+ return geyserConfig;
+ }
+
+ @Override
+ public GeyserVelocityLogger getGeyserLogger() {
+ return geyserLogger;
+ }
+
+ @Subscribe
+ public void onInit(ProxyInitializeEvent event) {
+ onEnable();
+ }
+
+ @Subscribe
+ public void onShutdown(ProxyShutdownEvent event) {
+ onDisable();
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java
index e0772464..3070e743 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java
@@ -46,6 +46,7 @@ public class FileUtils {
public static File fileOrCopiedFromResource(File file, String name, Function s) throws IOException {
if (!file.exists()) {
+ file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
InputStream input = GeyserConnector.class.getResourceAsStream("/" + name); // resources need leading "/" prefix