diff --git a/api/pom.xml b/api/pom.xml
index 31487d7c7..a0cbdf87f 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -16,5 +16,11 @@
1.18.4
compile
+
+ com.google.code.gson
+ gson
+ 2.8.2
+ compile
+
\ No newline at end of file
diff --git a/api/src/main/java/org/geysermc/api/Player.java b/api/src/main/java/org/geysermc/api/Player.java
new file mode 100644
index 000000000..7df58f46a
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/Player.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 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.api;
+
+import org.geysermc.api.command.CommandSender;
+import org.geysermc.api.session.AuthData;
+import org.geysermc.api.window.FormWindow;
+
+public interface Player extends CommandSender {
+
+ /**
+ * Connects the player to the remote server
+ *
+ * @param remoteServer the remote server to connect to
+ */
+ void connect(RemoteServer remoteServer);
+
+ /**
+ * Disconnect the player for the specified reason
+ *
+ * @param reason the reason to disconnect the player for
+ */
+ void disconnect(String reason);
+
+ /**
+ * Returns the authentication data of the player. This is not the
+ * player's Minecraft credentials; it's simply what is given to the server
+ * (Name, UUID, Xbox UUID) to verify the player can/actually exists.
+ *
+ * @return the authentication data of the player
+ */
+ AuthData getAuthenticationData();
+
+ /**
+ * Sends a form window
+ *
+ * @param window the window form to send
+ */
+ void sendForm(FormWindow window);
+
+ /**
+ * Sends a form window with the given ID
+ *
+ * @param window the window to send
+ * @param id the id of the window
+ */
+ void sendForm(FormWindow window, int id);
+}
diff --git a/api/src/main/java/org/geysermc/api/RemoteServer.java b/api/src/main/java/org/geysermc/api/RemoteServer.java
new file mode 100644
index 000000000..8004cbd16
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/RemoteServer.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019 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.api;
+
+public interface RemoteServer {
+
+ /**
+ * Returns the IP address of the remote server
+ *
+ * @return the IP address of the remote server
+ */
+ String getAddress();
+
+ /**
+ * Returns the port of the remote server
+ *
+ * @return the port of the remote server
+ */
+ int getPort();
+}
diff --git a/api/src/main/java/org/geysermc/api/events/EventHandler.java b/api/src/main/java/org/geysermc/api/events/EventHandler.java
new file mode 100644
index 000000000..d25c14ff1
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/events/EventHandler.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019 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.api.events;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The annotation to put on all methods that are events.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface EventHandler {
+
+ /**
+ * @return the order to execute events.
+ * @see EventPriority
+ */
+ EventPriority value() default EventPriority.NORMAL;
+
+ /**
+ * When an eventHandler should be run.
+ * The names mostly explain.
+ */
+ enum EventPriority {
+ FIRST,
+ NORMAL,
+ LAST,
+ READ_ONLY;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/events/Listener.java b/api/src/main/java/org/geysermc/api/events/Listener.java
new file mode 100644
index 000000000..3288c6821
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/events/Listener.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019 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.api.events;
+
+/**
+ * A marker class which says that a specific class uses events.
+ * @see EventHandler
+ */
+public interface Listener {
+}
diff --git a/api/src/main/java/org/geysermc/api/events/PingEvent.java b/api/src/main/java/org/geysermc/api/events/PingEvent.java
new file mode 100644
index 000000000..541657d81
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/events/PingEvent.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019 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.api.events;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.net.InetSocketAddress;
+
+@Getter
+@Setter
+public class PingEvent {
+
+ public PingEvent(InetSocketAddress address) {
+ this.address = address;
+ }
+
+ private InetSocketAddress address;
+
+ private String edition;
+ private String motd;
+ private int protocolVersion;
+ private String version;
+ private int playerCount;
+ private int maximumPlayerCount;
+ private long serverId;
+ private String subMotd;
+ private String gameType;
+ private boolean nintendoLimited;
+}
diff --git a/api/src/main/java/org/geysermc/api/events/player/PlayerEvent.java b/api/src/main/java/org/geysermc/api/events/player/PlayerEvent.java
new file mode 100644
index 000000000..ab4e98a61
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/events/player/PlayerEvent.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019 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.api.events.player;
+
+import lombok.Getter;
+import org.geysermc.api.Player;
+
+public class PlayerEvent {
+
+ @Getter
+ private Player player;
+
+ public PlayerEvent(Player player) {
+ this.player = player;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/events/player/PlayerFormResponseEvent.java b/api/src/main/java/org/geysermc/api/events/player/PlayerFormResponseEvent.java
new file mode 100644
index 000000000..b68170b2a
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/events/player/PlayerFormResponseEvent.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019 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.api.events.player;
+
+import lombok.Getter;
+import org.geysermc.api.Player;
+import org.geysermc.api.window.FormWindow;
+import org.geysermc.api.window.response.FormResponse;
+
+/**
+ * Called when a player interacts with a form
+ */
+public class PlayerFormResponseEvent extends PlayerEvent {
+
+ @Getter
+ private int formID;
+
+ @Getter
+ private FormWindow window;
+
+ /**
+ * Constructs a new PlayerFormResponseEvent instance
+ *
+ * @param player the player interacting with the form
+ * @param formID the id of the form
+ * @param window the window
+ */
+ public PlayerFormResponseEvent(Player player, int formID, FormWindow window) {
+ super(player);
+
+ this.formID = formID;
+ this.window = window;
+ }
+
+ /**
+ * Returns the response of the window, can be null
+ * if the player closed the window
+ *
+ * @return the response of the window
+ */
+ public FormResponse getResponse() {
+ return window.getResponse();
+ }
+
+ /**
+ * Returns if the window is closed
+ *
+ * @return if the window is closed
+ */
+ public boolean isClosed() {
+ return window.isClosed();
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/plugin/Plugin.java b/api/src/main/java/org/geysermc/api/plugin/Plugin.java
index 1cc995d35..8209cade0 100644
--- a/api/src/main/java/org/geysermc/api/plugin/Plugin.java
+++ b/api/src/main/java/org/geysermc/api/plugin/Plugin.java
@@ -33,7 +33,14 @@ import lombok.Setter;
* The first init point is the constructor, followed by onLoad, and finally onEnable.
*/
public class Plugin {
+ protected String name;
+ protected String version;
+ /**
+ * Returns if the plugin is enabled
+ *
+ * @return if the plugin is enabled
+ */
@Getter
@Setter
private boolean enabled = true;
@@ -60,9 +67,18 @@ public class Plugin {
}
/**
- * Called when th server is reloaded
+ * Called when the server is reloaded
*/
public void onReload() {
}
+
+ public final String getName() {
+ return name;
+ }
+
+ @Override
+ public final String toString() {
+ return getName();
+ }
}
diff --git a/api/src/main/java/org/geysermc/api/plugin/PluginManager.java b/api/src/main/java/org/geysermc/api/plugin/PluginManager.java
index dfa9a52f9..2cc183046 100644
--- a/api/src/main/java/org/geysermc/api/plugin/PluginManager.java
+++ b/api/src/main/java/org/geysermc/api/plugin/PluginManager.java
@@ -25,6 +25,8 @@
package org.geysermc.api.plugin;
+import org.geysermc.api.events.Listener;
+
import java.util.Set;
public interface PluginManager {
@@ -63,4 +65,23 @@ public interface PluginManager {
* @return a set of the loaded plugins
*/
Set getPlugins();
+
+ /**
+ * @param name The name of the plugin you want to get.
+ * @return The plugin with the String name in the parameters.
+ */
+ Plugin getPluginByName(String name);
+
+ /**
+ * Registers a listener to be run when an event is executed
+ * @param plugin the plugin registering the listener
+ * @param listener the listener which will contain the event methods
+ */
+ void registerEventListener(Plugin plugin, Listener listener);
+
+ /**
+ * Run an event
+ * @param o the event object.
+ */
+ void runEvent(Object o);
}
diff --git a/api/src/main/java/org/geysermc/api/session/AuthData.java b/api/src/main/java/org/geysermc/api/session/AuthData.java
new file mode 100644
index 000000000..a8b0a1f8a
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/session/AuthData.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 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.api.session;
+
+import java.util.UUID;
+
+public interface AuthData {
+
+ String getName();
+
+ UUID getUUID();
+ String getXboxUUID();
+}
diff --git a/api/src/main/java/org/geysermc/api/window/CustomFormBuilder.java b/api/src/main/java/org/geysermc/api/window/CustomFormBuilder.java
new file mode 100644
index 000000000..094ed5f44
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/CustomFormBuilder.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2019 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.api.window;
+
+import lombok.Getter;
+import org.geysermc.api.window.button.FormImage;
+import org.geysermc.api.window.component.FormComponent;
+import org.geysermc.api.window.response.CustomFormResponse;
+
+public class CustomFormBuilder {
+
+ @Getter
+ private CustomFormWindow form;
+
+ public CustomFormBuilder(String title) {
+ form = new CustomFormWindow(title);
+ }
+
+ public CustomFormBuilder setTitle(String title) {
+ form.setTitle(title);
+ return this;
+ }
+
+ public CustomFormBuilder setIcon(FormImage icon) {
+ form.setIcon(icon);
+ return this;
+ }
+
+ public CustomFormBuilder setResponse(String data) {
+ form.setResponse(data);
+ return this;
+ }
+
+ public CustomFormBuilder setResponse(CustomFormResponse response) {
+ form.setResponse(response);
+ return this;
+ }
+
+ public CustomFormBuilder addComponent(FormComponent component) {
+ form.addComponent(component);
+ return this;
+ }
+
+ public CustomFormWindow build() {
+ return form;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/CustomFormWindow.java b/api/src/main/java/org/geysermc/api/window/CustomFormWindow.java
new file mode 100644
index 000000000..afc6d72c0
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/CustomFormWindow.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2019 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.api.window;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import lombok.Getter;
+import lombok.Setter;
+import org.geysermc.api.window.button.FormImage;
+import org.geysermc.api.window.component.DropdownComponent;
+import org.geysermc.api.window.component.FormComponent;
+import org.geysermc.api.window.component.InputComponent;
+import org.geysermc.api.window.component.LabelComponent;
+import org.geysermc.api.window.component.SliderComponent;
+import org.geysermc.api.window.component.StepSliderComponent;
+import org.geysermc.api.window.component.ToggleComponent;
+import org.geysermc.api.window.response.CustomFormResponse;
+import org.geysermc.api.window.response.FormResponseData;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CustomFormWindow extends FormWindow {
+
+ @Getter
+ @Setter
+ private String title;
+
+ @Getter
+ @Setter
+ private FormImage icon;
+
+ @Getter
+ private List content;
+
+ public CustomFormWindow(String title) {
+ this(title, new ArrayList<>());
+ }
+
+ public CustomFormWindow(String title, List content) {
+ this(title, content, (FormImage) null);
+ }
+
+ public CustomFormWindow(String title, List content, String icon) {
+ this(title, content, new FormImage(FormImage.FormImageType.URL, icon));
+ }
+
+ public CustomFormWindow(String title, List content, FormImage icon) {
+ super("custom_form");
+
+ this.title = title;
+ this.content = content;
+ this.icon = icon;
+ }
+
+ public void addComponent(FormComponent component) {
+ content.add(component);
+ }
+
+ public String getJSONData() {
+ String toModify = new Gson().toJson(this);
+ //We need to replace this due to Java not supporting declaring class field 'default'
+ return toModify.replace("defaultOptionIndex", "default")
+ .replace("defaultText", "default")
+ .replace("defaultValue", "default")
+ .replace("defaultStepIndex", "default");
+ }
+
+ public void setResponse(String data) {
+ if (data == null || data.equalsIgnoreCase("null")) {
+ closed = true;
+ return;
+ }
+
+ int i = 0;
+ Map dropdownResponses = new HashMap();
+ Map inputResponses = new HashMap();
+ Map sliderResponses = new HashMap();
+ Map stepSliderResponses = new HashMap();
+ Map toggleResponses = new HashMap();
+ Map responses = new HashMap();
+ Map labelResponses = new HashMap();
+
+ List componentResponses = new Gson().fromJson(data, new TypeToken>() { }.getType());
+ for (String response : componentResponses) {
+ if (i >= content.size()) {
+ break;
+ }
+
+ FormComponent component = content.get(i);
+ if (component == null)
+ return;
+
+ if (component instanceof LabelComponent) {
+ LabelComponent labelComponent = (LabelComponent) component;
+ labelResponses.put(i, labelComponent.getText());
+ }
+
+ if (component instanceof DropdownComponent) {
+ DropdownComponent dropdownComponent = (DropdownComponent) component;
+ String option = dropdownComponent.getOptions().get(Integer.parseInt(response));
+
+ dropdownResponses.put(i, new FormResponseData(Integer.parseInt(response), option));
+ responses.put(i, option);
+ }
+
+ if (component instanceof InputComponent) {
+ inputResponses.put(i, response);
+ responses.put(i, response);
+ }
+
+ if (component instanceof SliderComponent) {
+ float value = Float.parseFloat(response);
+ sliderResponses.put(i, value);
+ responses.put(i, value);
+ }
+
+ if (component instanceof StepSliderComponent) {
+ StepSliderComponent stepSliderComponent = (StepSliderComponent) component;
+ String step = stepSliderComponent.getSteps().get(Integer.parseInt(response));
+ stepSliderResponses.put(i, new FormResponseData(Integer.parseInt(response), step));
+ responses.put(i, step);
+ }
+
+ if (component instanceof ToggleComponent) {
+ boolean answer = Boolean.parseBoolean(response);
+ toggleResponses.put(i, answer);
+ responses.put(i, answer);
+ }
+ i++;
+ }
+
+ this.response = new CustomFormResponse(responses, dropdownResponses, inputResponses,
+ sliderResponses, stepSliderResponses, toggleResponses, labelResponses);
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/FormWindow.java b/api/src/main/java/org/geysermc/api/window/FormWindow.java
new file mode 100644
index 000000000..d193950ca
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/FormWindow.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2019 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.api.window;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.geysermc.api.window.response.FormResponse;
+
+public abstract class FormWindow {
+
+ @Getter
+ private final String type;
+
+ @Getter
+ protected FormResponse response;
+
+ @Getter
+ @Setter
+ protected boolean closed;
+
+ public FormWindow(String type) {
+ this.type = type;
+ }
+
+ // Lombok won't work here, so we need to make our own method
+ public void setResponse(FormResponse response) {
+ this.response = response;
+ }
+
+ public abstract String getJSONData();
+
+ public abstract void setResponse(String response);
+
+}
diff --git a/api/src/main/java/org/geysermc/api/window/ModalFormWindow.java b/api/src/main/java/org/geysermc/api/window/ModalFormWindow.java
new file mode 100644
index 000000000..6a419775c
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/ModalFormWindow.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2019 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.api.window;
+
+import com.google.gson.Gson;
+import lombok.Getter;
+import lombok.Setter;
+import org.geysermc.api.window.response.ModalFormResponse;
+
+public class ModalFormWindow extends FormWindow {
+
+ @Getter
+ @Setter
+ private String title;
+
+ @Getter
+ @Setter
+ private String content;
+
+ @Getter
+ @Setter
+ private String button1;
+
+ @Getter
+ @Setter
+ private String button2;
+
+ public ModalFormWindow(String title, String content, String button1, String button2) {
+ super("modal");
+
+ this.title = title;
+ this.content = content;
+ this.button1 = button1;
+ this.button2 = button2;
+ }
+
+ @Override
+ public String getJSONData() {
+ return new Gson().toJson(this);
+ }
+
+ public void setResponse(String data) {
+ if (data == null || data.equalsIgnoreCase("null")) {
+ closed = true;
+ return;
+ }
+
+ if (Boolean.parseBoolean(data)) {
+ response = new ModalFormResponse(0, button1);
+ } else {
+ response = new ModalFormResponse(1, button2);
+ }
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/SimpleFormWindow.java b/api/src/main/java/org/geysermc/api/window/SimpleFormWindow.java
new file mode 100644
index 000000000..4a46aaf43
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/SimpleFormWindow.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019 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.api.window;
+
+import com.google.gson.Gson;
+import lombok.Getter;
+import lombok.Setter;
+import org.geysermc.api.window.button.FormButton;
+import org.geysermc.api.window.response.SimpleFormResponse;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class SimpleFormWindow extends FormWindow {
+
+ @Getter
+ @Setter
+ private String title;
+
+ @Getter
+ @Setter
+ private String content;
+
+ @Getter
+ @Setter
+ private List buttons;
+
+ public SimpleFormWindow(String title, String content) {
+ this(title, content, new ArrayList());
+ }
+
+ public SimpleFormWindow(String title, String content, List buttons) {
+ super("form");
+
+ this.title = title;
+ this.content = content;
+ this.buttons = buttons;
+ }
+
+ @Override
+ public String getJSONData() {
+ return new Gson().toJson(this);
+ }
+
+ public void setResponse(String data) {
+ if (data == null || data.equalsIgnoreCase("null")) {
+ closed = true;
+ return;
+ }
+
+ int buttonID;
+ try {
+ buttonID = Integer.parseInt(data);
+ } catch (Exception ex) {
+ return;
+ }
+
+ if (buttonID >= buttons.size()) {
+ response = new SimpleFormResponse(buttonID, null);
+ return;
+ }
+
+ response = new SimpleFormResponse(buttonID, buttons.get(buttonID));
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/button/FormButton.java b/api/src/main/java/org/geysermc/api/window/button/FormButton.java
new file mode 100644
index 000000000..859bf9382
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/button/FormButton.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019 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.api.window.button;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class FormButton {
+
+ @Getter
+ @Setter
+ private String text;
+
+ @Getter
+ private FormImage image;
+
+ public FormButton(String text, FormImage image) {
+ this.text = text;
+
+ if (image.getData() != null && !image.getData().isEmpty()) {
+ this.image = image;
+ }
+ }
+
+ public void setImage(FormImage image) {
+ if (image.getData() != null && !image.getData().isEmpty()) {
+ this.image = image;
+ }
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/button/FormImage.java b/api/src/main/java/org/geysermc/api/window/button/FormImage.java
new file mode 100644
index 000000000..17c472306
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/button/FormImage.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2019 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.api.window.button;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class FormImage {
+
+ @Getter
+ @Setter
+ private FormImageType type;
+
+ @Getter
+ @Setter
+ private String data;
+
+ public FormImage(FormImageType type, String data) {
+ this.type = type;
+ this.data = data;
+ }
+
+ public enum FormImageType {
+ PATH("path"),
+ URL("url");
+
+ @Getter
+ private String name;
+
+ FormImageType(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/component/DropdownComponent.java b/api/src/main/java/org/geysermc/api/window/component/DropdownComponent.java
new file mode 100644
index 000000000..99e1bca62
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/component/DropdownComponent.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019 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.api.window.component;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+public class DropdownComponent extends FormComponent {
+
+ @Getter
+ @Setter
+ private String text;
+
+ @Getter
+ @Setter
+ private List options;
+
+ @Getter
+ @Setter
+ private int defaultOptionIndex;
+
+ public DropdownComponent() {
+ super("dropdown");
+ }
+
+ public void addOption(String option, boolean isDefault) {
+ options.add(option);
+ if (isDefault)
+ defaultOptionIndex = options.size() - 1;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/component/FormComponent.java b/api/src/main/java/org/geysermc/api/window/component/FormComponent.java
new file mode 100644
index 000000000..506cae687
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/component/FormComponent.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 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.api.window.component;
+
+import lombok.Getter;
+
+public abstract class FormComponent {
+
+ @Getter
+ private final String type;
+
+ public FormComponent(String type) {
+ this.type = type;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/component/InputComponent.java b/api/src/main/java/org/geysermc/api/window/component/InputComponent.java
new file mode 100644
index 000000000..12af18268
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/component/InputComponent.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019 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.api.window.component;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class InputComponent extends FormComponent {
+
+ @Getter
+ @Setter
+ private String text;
+
+ @Getter
+ @Setter
+ private String placeholder;
+
+ @Getter
+ @Setter
+ private String defaultText;
+
+ public InputComponent(String text, String placeholder, String defaultText) {
+ super("input");
+
+ this.text = text;
+ this.placeholder = placeholder;
+ this.defaultText = defaultText;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/component/LabelComponent.java b/api/src/main/java/org/geysermc/api/window/component/LabelComponent.java
new file mode 100644
index 000000000..9ba68ee4a
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/component/LabelComponent.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 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.api.window.component;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class LabelComponent extends FormComponent {
+
+ @Getter
+ @Setter
+ private String text;
+
+ public LabelComponent(String text) {
+ super("label");
+
+ this.text = text;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/component/SliderComponent.java b/api/src/main/java/org/geysermc/api/window/component/SliderComponent.java
new file mode 100644
index 000000000..468b700ec
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/component/SliderComponent.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019 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.api.window.component;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class SliderComponent extends FormComponent {
+
+ @Getter
+ @Setter
+ private String text;
+
+ @Getter
+ @Setter
+ private float min;
+
+ @Getter
+ @Setter
+ private float max;
+
+ @Getter
+ @Setter
+ private int step;
+
+ @Getter
+ @Setter
+ private float defaultValue;
+
+ public SliderComponent(String text, float min, float max, int step, float defaultValue) {
+ super("slider");
+
+ this.text = text;
+ this.min = min < 0f ? 0f : min;
+ this.max = max > this.min ? max : this.min;
+ if (step != -1f && step > 0)
+ this.step = step;
+
+ if (defaultValue != -1f)
+ this.defaultValue = defaultValue;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/component/StepSliderComponent.java b/api/src/main/java/org/geysermc/api/window/component/StepSliderComponent.java
new file mode 100644
index 000000000..aa934f062
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/component/StepSliderComponent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2019 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.api.window.component;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class StepSliderComponent extends FormComponent {
+
+ @Getter
+ @Setter
+ private String text;
+
+ @Getter
+ private List steps;
+
+ @Getter
+ @Setter
+ private int defaultStepIndex;
+
+ public StepSliderComponent(String text) {
+ this(text, new ArrayList());
+ }
+
+ public StepSliderComponent(String text, List steps) {
+ this(text, steps, 0);
+ }
+
+ public StepSliderComponent(String text, List steps, int defaultStepIndex) {
+ super("step_slider");
+
+ this.text = text;
+ this.steps = steps;
+ this.defaultStepIndex = defaultStepIndex;
+ }
+
+ public void addStep(String step, boolean isDefault) {
+ steps.add(step);
+
+ if (isDefault)
+ defaultStepIndex = steps.size() - 1;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/component/ToggleComponent.java b/api/src/main/java/org/geysermc/api/window/component/ToggleComponent.java
new file mode 100644
index 000000000..41b292a61
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/component/ToggleComponent.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019 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.api.window.component;
+
+public class ToggleComponent extends FormComponent {
+
+ private String text;
+ private boolean defaultValue;
+
+ public ToggleComponent(String text) {
+ this(text, false);
+ }
+
+ public ToggleComponent(String text, boolean defaultValue) {
+ super("toggle");
+
+ this.text = text;
+ this.defaultValue = defaultValue;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/api/window/response/CustomFormResponse.java b/api/src/main/java/org/geysermc/api/window/response/CustomFormResponse.java
new file mode 100644
index 000000000..f32c43462
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/response/CustomFormResponse.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019 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.api.window.response;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Map;
+
+@Getter
+@AllArgsConstructor
+public class CustomFormResponse implements FormResponse {
+
+ private Map responses;
+ private Map dropdownResponses;
+ private Map inputResponses;
+ private Map sliderResponses;
+ private Map stepSliderResponses;
+ private Map toggleResponses;
+ private Map labelResponses;
+}
diff --git a/api/src/main/java/org/geysermc/api/window/response/FormResponse.java b/api/src/main/java/org/geysermc/api/window/response/FormResponse.java
new file mode 100644
index 000000000..0286bef1a
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/response/FormResponse.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2019 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.api.window.response;
+
+public interface FormResponse {
+}
diff --git a/api/src/main/java/org/geysermc/api/window/response/FormResponseData.java b/api/src/main/java/org/geysermc/api/window/response/FormResponseData.java
new file mode 100644
index 000000000..b97fb0521
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/response/FormResponseData.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019 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.api.window.response;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public class FormResponseData {
+
+ private int elementID;
+ private String elementContent;
+}
diff --git a/api/src/main/java/org/geysermc/api/window/response/ModalFormResponse.java b/api/src/main/java/org/geysermc/api/window/response/ModalFormResponse.java
new file mode 100644
index 000000000..a62953b0d
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/response/ModalFormResponse.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019 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.api.window.response;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public class ModalFormResponse implements FormResponse {
+
+ private int clickedButtonId;
+ private String clickedButtonText;
+}
diff --git a/api/src/main/java/org/geysermc/api/window/response/SimpleFormResponse.java b/api/src/main/java/org/geysermc/api/window/response/SimpleFormResponse.java
new file mode 100644
index 000000000..4271d7546
--- /dev/null
+++ b/api/src/main/java/org/geysermc/api/window/response/SimpleFormResponse.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 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.api.window.response;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.geysermc.api.window.button.FormButton;
+
+@Getter
+@AllArgsConstructor
+public class SimpleFormResponse implements FormResponse {
+
+ private int clickedButtonId;
+ private FormButton clickedButton;
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java
index b43025acf..5d125dff4 100644
--- a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java
+++ b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java
@@ -30,6 +30,7 @@ import com.nukkitx.protocol.bedrock.BedrockPong;
import com.nukkitx.protocol.bedrock.BedrockServerEventHandler;
import com.nukkitx.protocol.bedrock.BedrockServerSession;
import com.nukkitx.protocol.bedrock.v361.Bedrock_v361;
+import org.geysermc.api.events.PingEvent;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.console.GeyserLogger;
@@ -54,16 +55,16 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
@Override
public BedrockPong onQuery(InetSocketAddress inetSocketAddress) {
+ PingEvent pong = new PingEvent(inetSocketAddress);
GeyserLogger.DEFAULT.debug(inetSocketAddress + " has pinged you!");
GeyserConfiguration config = connector.getConfig();
- BedrockPong pong = new BedrockPong();
pong.setEdition("MCPE");
pong.setGameType("Default");
pong.setNintendoLimited(false);
pong.setProtocolVersion(GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion());
pong.setVersion("1.12.0");
- pong.setIpv4Port(19132);
+ connector.getPluginManager().runEvent(pong);
if (connector.getConfig().isPingPassthrough()) {
ServerStatusInfo serverInfo = connector.getPassthroughThread().getInfo();
@@ -79,7 +80,22 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
pong.setMotd(config.getBedrock().getMotd1());
pong.setSubMotd(config.getBedrock().getMotd2());
}
- return pong;
+
+ BedrockPong c = new BedrockPong();
+
+ c.setEdition(pong.getEdition());
+ c.setGameType(pong.getGameType());
+ c.setNintendoLimited(pong.isNintendoLimited());
+ c.setProtocolVersion(pong.getProtocolVersion());
+ c.setVersion(pong.getVersion());
+
+ c.setMotd(pong.getMotd());
+ c.setSubMotd(pong.getSubMotd());
+ c.setPlayerCount(pong.getPlayerCount());
+ c.setMaximumPlayerCount(pong.getMaximumPlayerCount());
+
+ return c;
+
}
@Override
diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java
index ede584cb4..886f86fa5 100644
--- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java
+++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java
@@ -34,8 +34,12 @@ import com.nukkitx.protocol.bedrock.packet.*;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import net.minidev.json.JSONValue;
+import org.geysermc.api.events.player.PlayerFormResponseEvent;
+import org.geysermc.api.window.FormWindow;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.session.auth.BedrockAuthData;
+import org.geysermc.connector.network.session.cache.WindowCache;
import java.util.UUID;
@@ -58,6 +62,8 @@ public class UpstreamPacketHandler implements BedrockPacketHandler {
return true;
}
+ session.getUpstream().setPacketCodec(GeyserConnector.BEDROCK_PACKET_CODEC);
+
try {
JSONObject chainData = (JSONObject) JSONValue.parse(loginPacket.getChainData().array());
JSONArray chainArray = (JSONArray) chainData.get("chain");
@@ -67,7 +73,7 @@ public class UpstreamPacketHandler implements BedrockPacketHandler {
JWSObject identity = JWSObject.parse((String) identityObject);
JSONObject extraData = (JSONObject) identity.getPayload().toJSONObject().get("extraData");
- session.setAuthenticationData(extraData.getAsString("displayName"), UUID.fromString(extraData.getAsString("identity")), extraData.getAsString("XUID"));
+ session.setAuthenticationData(new BedrockAuthData(extraData.getAsString("displayName"), UUID.fromString(extraData.getAsString("identity")), extraData.getAsString("XUID")));
} catch (Exception ex) {
session.getUpstream().disconnect("An internal error occurred when connecting to this server.");
ex.printStackTrace();
@@ -81,6 +87,17 @@ public class UpstreamPacketHandler implements BedrockPacketHandler {
ResourcePacksInfoPacket resourcePacksInfo = new ResourcePacksInfoPacket();
session.getUpstream().sendPacketImmediately(resourcePacksInfo);
+ // TODO: Implement this
+ /**
+ CustomFormWindow window = new CustomFormBuilder("Login")
+ .addComponent(new LabelComponent("Minecraft: Java Edition account authentication."))
+ .addComponent(new LabelComponent("Enter the credentials for your Minecraft: Java Edition account below."))
+ .addComponent(new InputComponent("Email/Username", "account@geysermc.org", ""))
+ .addComponent(new InputComponent("Password", "123456", ""))
+ .build();
+
+ session.sendForm(window, 1);
+ */
return true;
}
@@ -303,7 +320,16 @@ public class UpstreamPacketHandler implements BedrockPacketHandler {
@Override
public boolean handle(ModalFormResponsePacket packet) {
connector.getLogger().debug("Handled packet: " + packet.getClass().getSimpleName());
- return false;
+ WindowCache windowCache = session.getWindowCache();
+ if (!windowCache.getWindows().containsKey(packet.getFormId()))
+ return false;
+
+ FormWindow window = windowCache.getWindows().remove(packet.getFormId());
+ window.setResponse(packet.getFormData().trim());
+
+ PlayerFormResponseEvent event = new PlayerFormResponseEvent(session, packet.getFormId(), window);
+ connector.getPluginManager().runEvent(event);
+ return true;
}
@Override
diff --git a/connector/src/main/java/org/geysermc/connector/network/remote/RemoteJavaServer.java b/connector/src/main/java/org/geysermc/connector/network/remote/RemoteJavaServer.java
index ee32a8082..d335ba946 100644
--- a/connector/src/main/java/org/geysermc/connector/network/remote/RemoteJavaServer.java
+++ b/connector/src/main/java/org/geysermc/connector/network/remote/RemoteJavaServer.java
@@ -27,10 +27,11 @@ package org.geysermc.connector.network.remote;
import lombok.AllArgsConstructor;
import lombok.Getter;
+import org.geysermc.api.RemoteServer;
@Getter
@AllArgsConstructor
-public class RemoteJavaServer {
+public class RemoteJavaServer implements RemoteServer {
private String address;
private int port;
diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java
index a1b9b11a6..2fa274765 100644
--- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java
+++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java
@@ -25,7 +25,6 @@
package org.geysermc.connector.network.session;
-import com.github.steveice10.mc.auth.exception.request.RequestException;
import com.github.steveice10.mc.protocol.MinecraftProtocol;
import com.github.steveice10.packetlib.Client;
import com.github.steveice10.packetlib.event.session.ConnectedEvent;
@@ -37,22 +36,21 @@ import com.nukkitx.network.util.DisconnectReason;
import com.nukkitx.protocol.PlayerSession;
import com.nukkitx.protocol.bedrock.BedrockServerSession;
import com.nukkitx.protocol.bedrock.packet.TextPacket;
-import lombok.AllArgsConstructor;
import lombok.Getter;
-import org.geysermc.api.command.CommandSender;
+import org.geysermc.api.Player;
+import org.geysermc.api.RemoteServer;
+import org.geysermc.api.session.AuthData;
+import org.geysermc.api.window.FormWindow;
import org.geysermc.connector.GeyserConnector;
-import org.geysermc.connector.network.remote.RemoteJavaServer;
-import org.geysermc.connector.network.session.cache.ScoreboardCache;
+import org.geysermc.connector.network.session.cache.WindowCache;
import org.geysermc.connector.network.translators.Registry;
-import java.util.UUID;
-
-public class GeyserSession implements PlayerSession, CommandSender {
+public class GeyserSession implements PlayerSession, Player {
private GeyserConnector connector;
@Getter
- private RemoteJavaServer remoteServer;
+ private RemoteServer remoteServer;
@Getter
private BedrockServerSession upstream;
@@ -63,10 +61,10 @@ public class GeyserSession implements PlayerSession, CommandSender {
private final GeyserSession THIS = this;
@Getter
- private AuthenticationData authenticationData;
+ private AuthData authenticationData;
@Getter
- private ScoreboardCache scoreboardCache;
+ private WindowCache windowCache;
private boolean closed;
@@ -74,10 +72,10 @@ public class GeyserSession implements PlayerSession, CommandSender {
this.connector = connector;
this.upstream = bedrockServerSession;
- this.scoreboardCache = new ScoreboardCache(this);
+ this.windowCache = new WindowCache(this);
}
- public void connect(RemoteJavaServer remoteServer) {
+ public void connect(RemoteServer remoteServer) {
MinecraftProtocol protocol = new MinecraftProtocol(authenticationData.getName());
downstream = new Client(remoteServer.getAddress(), remoteServer.getPort(), protocol, new TcpSessionFactory());
downstream.getSession().addListener(new SessionAdapter() {
@@ -130,8 +128,8 @@ public class GeyserSession implements PlayerSession, CommandSender {
downstream.getSession().disconnect("Disconnected from server. Reason: " + reason);
}
- public void setAuthenticationData(String name, UUID uuid, String xboxUUID) {
- authenticationData = new AuthenticationData(name, uuid, xboxUUID);
+ public void setAuthenticationData(AuthData authData) {
+ authenticationData = authData;
}
@Override
@@ -159,12 +157,11 @@ public class GeyserSession implements PlayerSession, CommandSender {
}
}
- @Getter
- @AllArgsConstructor
- public class AuthenticationData {
+ public void sendForm(FormWindow window, int id) {
+ windowCache.showWindow(window, id);
+ }
- private String name;
- private UUID uuid;
- private String xboxUUID;
+ public void sendForm(FormWindow window) {
+ windowCache.showWindow(window);
}
}
\ No newline at end of file
diff --git a/connector/src/main/java/org/geysermc/connector/network/session/auth/BedrockAuthData.java b/connector/src/main/java/org/geysermc/connector/network/session/auth/BedrockAuthData.java
new file mode 100644
index 000000000..47d79ed85
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/session/auth/BedrockAuthData.java
@@ -0,0 +1,16 @@
+package org.geysermc.connector.network.session.auth;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.geysermc.api.session.AuthData;
+
+import java.util.UUID;
+
+@Getter
+@AllArgsConstructor
+public class BedrockAuthData implements AuthData {
+
+ private String name;
+ private UUID UUID;
+ private String xboxUUID;
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/WindowCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/WindowCache.java
new file mode 100644
index 000000000..0ce8b7c04
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/WindowCache.java
@@ -0,0 +1,54 @@
+package org.geysermc.connector.network.session.cache;
+
+import com.nukkitx.protocol.bedrock.packet.ModalFormRequestPacket;
+import lombok.Getter;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.api.window.FormWindow;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class WindowCache {
+
+ private GeyserSession session;
+
+ public WindowCache(GeyserSession session) {
+ this.session = session;
+ }
+
+ @Getter
+ private Map windows = new HashMap();
+
+ public void addWindow(FormWindow window) {
+ windows.put(windows.size() + 1, window);
+ }
+
+ public void addWindow(FormWindow window, int id) {
+ windows.put(id, window);
+ }
+
+ public void showWindow(FormWindow window) {
+ showWindow(window, windows.size() + 1);
+ }
+
+ public void showWindow(int id) {
+ if (!windows.containsKey(id))
+ return;
+
+ ModalFormRequestPacket formRequestPacket = new ModalFormRequestPacket();
+ formRequestPacket.setFormId(id);
+ formRequestPacket.setFormData(windows.get(id).getJSONData());
+
+ session.getUpstream().sendPacket(formRequestPacket);
+ }
+
+ public void showWindow(FormWindow window, int id) {
+ ModalFormRequestPacket formRequestPacket = new ModalFormRequestPacket();
+ formRequestPacket.setFormId(id);
+ formRequestPacket.setFormData(window.getJSONData());
+
+ session.getUpstream().sendPacket(formRequestPacket);
+
+ addWindow(window, id);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java
index 538965f7f..da8a344e6 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java
@@ -28,8 +28,6 @@ package org.geysermc.connector.network.translators;
import com.flowpowered.math.vector.Vector2f;
import com.flowpowered.math.vector.Vector3f;
import com.flowpowered.math.vector.Vector3i;
-import com.github.steveice10.mc.protocol.data.game.scoreboard.ObjectiveAction;
-import com.github.steveice10.mc.protocol.data.message.ChatFormat;
import com.github.steveice10.mc.protocol.data.message.TranslationMessage;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerChatPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerJoinGamePacket;
@@ -38,10 +36,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntit
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityPositionRotationPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityTeleportPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityVelocityPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerDisplayScoreboardPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerScoreboardObjectivePacket;
-import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerTeamPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerUpdateScorePacket;
+import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerNotifyClientPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateTimePacket;
import com.nukkitx.nbt.CompoundTagBuilder;
import com.nukkitx.nbt.NbtUtils;
@@ -50,16 +45,12 @@ import com.nukkitx.nbt.tag.CompoundTag;
import com.nukkitx.protocol.bedrock.data.GamePublishSetting;
import com.nukkitx.protocol.bedrock.data.GameRule;
import com.nukkitx.protocol.bedrock.packet.*;
-import org.geysermc.api.ChatColor;
-import org.geysermc.connector.network.session.cache.ScoreboardCache;
-import org.geysermc.connector.network.translators.scoreboard.Score;
-import org.geysermc.connector.network.translators.scoreboard.Scoreboard;
-import org.geysermc.connector.network.translators.scoreboard.ScoreboardObjective;
import org.geysermc.connector.utils.MessageUtils;
import org.geysermc.connector.utils.Toolbox;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.util.concurrent.ThreadLocalRandom;
public class TranslatorsInit {
@@ -86,7 +77,7 @@ public class TranslatorsInit {
addTitlePackets();
addTimePackets();
addEntityPackets();
- addScoreboardPackets();
+ addNotifyPackets();
}
private static void addLoginPackets() {
@@ -284,175 +275,34 @@ public class TranslatorsInit {
});
}
- public static void addScoreboardPackets() {
- Registry.add(ServerDisplayScoreboardPacket.class, (packet, session) -> {
- try {
- ScoreboardCache cache = session.getScoreboardCache();
- Scoreboard scoreboard = new Scoreboard(session);
+ public static void addNotifyPackets() {
+ Registry.add(ServerNotifyClientPacket.class, (packet, session) -> {
+ switch (packet.getNotification()) {
+ case START_RAIN:
+ LevelEventPacket startRainPacket = new LevelEventPacket();
+ startRainPacket.setEvent(LevelEventPacket.Event.START_RAIN);
+ startRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000);
+ startRainPacket.setPosition(new Vector3f(0, 0, 0));
- /*
- if (cache.getScoreboard() != null)
- cache.setScoreboard(scoreboard);
- */
- System.out.println("added scoreboard " + packet.getScoreboardName());
- // scoreboard.onUpdate();
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- });
+ session.getUpstream().sendPacket(startRainPacket);
+ break;
+ case STOP_RAIN:
+ LevelEventPacket stopRainPacket = new LevelEventPacket();
+ stopRainPacket.setEvent(LevelEventPacket.Event.STOP_RAIN);
+ stopRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000);
+ stopRainPacket.setPosition(new Vector3f(0, 0, 0));
- Registry.add(ServerScoreboardObjectivePacket.class, (packet, session) -> {
- try {
- ScoreboardCache cache = session.getScoreboardCache();
- Scoreboard scoreboard = new Scoreboard(session);
- if (cache.getScoreboard() != null)
- scoreboard = cache.getScoreboard();
-
- System.out.println("new objective registered with " + packet.getName());
- switch (packet.getAction()) {
- case ADD:
- ScoreboardObjective objective = scoreboard.registerNewObjective(packet.getName());
- objective.setDisplaySlot(ScoreboardObjective.DisplaySlot.SIDEBAR);
- objective.setDisplayName(MessageUtils.getBedrockMessage(packet.getDisplayName()));
- break;
- case UPDATE:
- ScoreboardObjective updateObj = scoreboard.getObjective(packet.getName());
- updateObj.setDisplayName(MessageUtils.getBedrockMessage(packet.getDisplayName()));
- break;
- case REMOVE:
- scoreboard.unregisterObjective(packet.getName());
- break;
- }
-
- scoreboard.onUpdate();
- cache.setScoreboard(scoreboard);
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- });
-
- Registry.add(ServerUpdateScorePacket.class, (packet, session) -> {
- try {
- ScoreboardCache cache = session.getScoreboardCache();
- Scoreboard scoreboard = new Scoreboard(session);
- if (cache.getScoreboard() != null)
- scoreboard = cache.getScoreboard();
-
- ScoreboardObjective objective = scoreboard.getObjective(packet.getObjective());
- if (objective == null) {
- objective = scoreboard.registerNewObjective(packet.getObjective());
- }
-
- System.out.println(packet.getEntry() + " <-> objective = " + packet.getObjective() + " val " + packet.getValue());
- switch (packet.getAction()) {
- case REMOVE:
- objective.registerScore(packet.getEntry(), packet.getEntry(), packet.getValue(), SetScorePacket.Action.REMOVE);
- break;
- case ADD_OR_UPDATE:
- objective.registerScore(packet.getEntry(), packet.getEntry(), packet.getValue(), SetScorePacket.Action.SET);
- break;
- }
- cache.setScoreboard(scoreboard);
- scoreboard.onUpdate();
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- });
-
- Registry.add(ServerTeamPacket.class, (packet, session) -> {
- try {
- ScoreboardCache cache = session.getScoreboardCache();
- Scoreboard scoreboard = new Scoreboard(session);
- if (cache.getScoreboard() != null)
- scoreboard = cache.getScoreboard();
-
- ScoreboardObjective objective = scoreboard.getObjective();
- if (objective == null) {
- return;
- }
-
- System.out.println("Team name: " + packet.getTeamName());
- // System.out.println("Team Name: " + packet.getTeamName() + " displ: " + packet.getDisplayName() + " <-> objective team = " + packet.getTeamName());
- String scoreboardText = MessageUtils.getBedrockMessage(packet.getPrefix()) + MessageUtils.getBedrockMessage(packet.getSuffix());
-
- // System.out.println("scoreboard text: " + scoreboardText);
- switch (packet.getAction()) {
- case REMOVE:
- case REMOVE_PLAYER:
- objective.registerScore(packet.getTeamName(), scoreboardText, Integer.parseInt(packet.getTeamName()), SetScorePacket.Action.REMOVE);
- objective.setScoreText(packet.getTeamName(), scoreboardText);
- break;
- case UPDATE:
- objective.setScoreText(packet.getTeamName(), scoreboardText);
- case ADD_PLAYER:
- case CREATE:
- objective.registerScore(packet.getTeamName(), scoreboardText, Integer.parseInt(packet.getTeamName()), SetScorePacket.Action.SET);
- objective.setScoreText(packet.getTeamName(), scoreboardText);
- break;
- }
-
- cache.setScoreboard(scoreboard);
- scoreboard.onUpdate();
- } catch (Exception ex) {
- ex.printStackTrace();
+ session.getUpstream().sendPacket(stopRainPacket);
+ break;
+ case ENTER_CREDITS:
+ // ShowCreditsPacket showCreditsPacket = new ShowCreditsPacket();
+ // showCreditsPacket.setStatus(ShowCreditsPacket.Status.START_CREDITS);
+ // showCreditsPacket.setRuntimeEntityId(runtimeEntityId);
+ // session.getUpstream().sendPacket(showCreditsPacket);
+ break;
+ default:
+ break;
}
});
}
-
- /*
- public static void addScoreboardPackets() {
- Registry.add(ServerDisplayScoreboardPacket.class, (packet, session) -> {
- SetDisplayObjectivePacket objectivePacket = new SetDisplayObjectivePacket();
- objectivePacket.setCriteria("dummy");
- objectivePacket.setDisplaySlot("sidebar");
- objectivePacket.setDisplayName(packet.getScoreboardName());
- objectivePacket.setSortOrder(1);
- objectivePacket.setObjectiveId(UUID.randomUUID().toString()); // uhh
-
- session.getUpstream().sendPacket(objectivePacket);
-
- System.out.println("added scoreboard " + packet.getScoreboardName());
- });
-
- Registry.add(ServerScoreboardObjectivePacket.class, (packet, session) -> {
- if (packet.getAction() == ObjectiveAction.REMOVE) {
- RemoveObjectivePacket objectivePacket = new RemoveObjectivePacket();
- objectivePacket.setObjectiveId(packet.getDisplayName().getFullText());
-
- session.getUpstream().sendPacket(objectivePacket);
- } else {
- SetDisplayObjectivePacket objectivePacket = new SetDisplayObjectivePacket();
- objectivePacket.setCriteria("dummy");
- objectivePacket.setDisplaySlot("sidebar");
- objectivePacket.setDisplayName(packet.getDisplayName().getFullText());
- objectivePacket.setSortOrder(1);
- objectivePacket.setObjectiveId(packet.getName()); // uhh
-
- session.getUpstream().sendPacket(objectivePacket);
- }
-
- System.out.println("new objective registered with " + packet.getName());
- });
-
- Registry.add(ServerUpdateScorePacket.class, (packet, session) -> {
- if (packet.getAction() == ScoreboardAction.ADD_OR_UPDATE) {
- SetDisplayObjectivePacket objectivePacket = new SetDisplayObjectivePacket();
- objectivePacket.setObjectiveId(packet.getObjective());
- objectivePacket.setDisplaySlot("sidebar");
- objectivePacket.setCriteria("dummy");
- objectivePacket.setDisplayName(packet.getEntry());
- objectivePacket.setSortOrder(1);
-
- session.getUpstream().sendPacket(objectivePacket);
- } else {
- RemoveObjectivePacket objectivePacket = new RemoveObjectivePacket();
- objectivePacket.setObjectiveId(packet.getObjective());
-
- session.getUpstream().sendPacket(objectivePacket);
- }
-
- System.out.println(packet.getEntry() + " <-> objective = " + packet.getObjective() + " val " + packet.getValue());
- });
- }
- */
}
diff --git a/connector/src/main/java/org/geysermc/connector/plugin/GeyserPluginLoader.java b/connector/src/main/java/org/geysermc/connector/plugin/GeyserPluginLoader.java
index 7df06ee88..894b34475 100644
--- a/connector/src/main/java/org/geysermc/connector/plugin/GeyserPluginLoader.java
+++ b/connector/src/main/java/org/geysermc/connector/plugin/GeyserPluginLoader.java
@@ -32,6 +32,7 @@ import org.geysermc.api.Connector;
import org.geysermc.api.plugin.Plugin;
import java.io.File;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -51,7 +52,7 @@ public class GeyserPluginLoader extends ClassLoader {
}
for (File f : dir.listFiles()) {
- if (!f.getName().endsWith(".jar"))
+ if (!f.getName().toLowerCase().endsWith(".jar"))
continue;
try {
@@ -83,6 +84,19 @@ public class GeyserPluginLoader extends ClassLoader {
PluginYML yml = mapper.readValue(is, PluginYML.class);
is.close();
Plugin plugin = (Plugin) Class.forName(yml.main, true, this).newInstance();
+
+ Class cl = Plugin.class;
+
+ Field name = cl.getDeclaredField("name");
+ name.setAccessible(true);
+
+ Field version = cl.getDeclaredField("version");
+ version.setAccessible(true);
+
+ name.set(plugin, yml.name);
+
+ version.set(plugin, yml.version);
+
connector.getLogger().info("Loading plugin " + yml.name + " version " + yml.version);
connector.getPluginManager().loadPlugin(plugin);
} catch (Exception e) {
diff --git a/connector/src/main/java/org/geysermc/connector/plugin/GeyserPluginManager.java b/connector/src/main/java/org/geysermc/connector/plugin/GeyserPluginManager.java
index f9096bd5a..470dd23e0 100644
--- a/connector/src/main/java/org/geysermc/connector/plugin/GeyserPluginManager.java
+++ b/connector/src/main/java/org/geysermc/connector/plugin/GeyserPluginManager.java
@@ -26,19 +26,23 @@
package org.geysermc.connector.plugin;
import lombok.Getter;
+import org.geysermc.api.events.EventHandler;
+import org.geysermc.api.events.Listener;
import org.geysermc.api.plugin.Plugin;
import org.geysermc.api.plugin.PluginManager;
-import java.util.HashSet;
-import java.util.Set;
+import java.awt.*;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.List;
public class GeyserPluginManager implements PluginManager {
+ private final List EVENTS = new ArrayList<>();
@Getter
private GeyserPluginLoader loader;
- @Getter
- private Set plugins = new HashSet();
+ private Map plugins = new HashMap<>();
public GeyserPluginManager(GeyserPluginLoader loader) {
this.loader = loader;
@@ -46,7 +50,7 @@ public class GeyserPluginManager implements PluginManager {
public void loadPlugin(Plugin plugin) {
loader.loadPlugin(plugin);
- plugins.add(plugin);
+ plugins.put(plugin.getName(), plugin);
}
public void unloadPlugin(Plugin plugin) {
@@ -62,6 +66,42 @@ public class GeyserPluginManager implements PluginManager {
}
public Set getPlugins() {
- return plugins;
+ return new HashSet<>(plugins.values());
+ }
+
+ @Override
+ public void registerEventListener(Plugin p, Listener l) {
+ try {
+ Class extends Listener> clazz = l.getClass();
+
+ for(Method m : clazz.getMethods()) {
+ if(m.getAnnotation(EventHandler.class) != null) {
+ PluginListener listener = new PluginListener();
+
+ listener.plugin = p;
+ listener.listener = l;
+ listener.clazz = m.getParameterTypes()[0];
+ listener.priority = m.getAnnotation(EventHandler.class).value();
+ listener.run = m;
+ EVENTS.add(listener);
+ }
+ }
+ } catch (Exception e) {
+ //
+ }
+ }
+
+ @Override
+ public void runEvent(Object o) {
+ for(EventHandler.EventPriority p : EventHandler.EventPriority.values()) {
+ for (PluginListener listener : EVENTS) {
+ listener.runIfNeeded(p, o);
+ }
+ }
+ }
+
+ @Override
+ public Plugin getPluginByName(String name) {
+ return plugins.get(name);
}
}
\ No newline at end of file
diff --git a/connector/src/main/java/org/geysermc/connector/plugin/PluginListener.java b/connector/src/main/java/org/geysermc/connector/plugin/PluginListener.java
new file mode 100644
index 000000000..605572f19
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/plugin/PluginListener.java
@@ -0,0 +1,28 @@
+package org.geysermc.connector.plugin;
+
+import org.geysermc.api.events.EventHandler;
+import org.geysermc.api.events.Listener;
+import org.geysermc.api.plugin.Plugin;
+import org.geysermc.connector.console.GeyserLogger;
+
+import java.lang.reflect.Method;
+
+public class PluginListener {
+ Method run;
+ Plugin plugin;
+ Listener listener;
+ Class clazz;
+ EventHandler.EventPriority priority;
+
+ void runIfNeeded(EventHandler.EventPriority p, Object o) {
+ if(p.equals(priority) && clazz.isInstance(o)) {
+ try {
+ run.invoke(listener, o);
+ } catch (ReflectiveOperationException ex) {
+ GeyserLogger.DEFAULT.severe("Exception while trying to run event! Contact the maintainer of " + plugin.getName());
+
+ ex.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/GeyserUtils.java b/connector/src/main/java/org/geysermc/connector/utils/GeyserUtils.java
index 1e95a3e3f..13a188205 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/GeyserUtils.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/GeyserUtils.java
@@ -649,5 +649,14 @@ public class GeyserUtils {
}
+ public static boolean instanceOf(Class clazz, Object o) {
+ try {
+ T t = (T) o;
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
}