First version of the Forms rewrite

The next version will split the implementation from the api
This commit is contained in:
Tim203 2020-10-30 00:58:17 +01:00
parent f8939ca5de
commit c9102348de
No known key found for this signature in database
GPG key ID: 064EE9F5BF7C3EE8
37 changed files with 1559 additions and 1112 deletions

View file

@ -0,0 +1,177 @@
/*
* 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.common.form;
import com.google.gson.annotations.JsonAdapter;
import lombok.Getter;
import org.geysermc.common.form.component.*;
import org.geysermc.common.form.response.CustomFormResponse;
import org.geysermc.common.form.util.FormAdaptor;
import org.geysermc.common.form.util.FormImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Getter
@JsonAdapter(FormAdaptor.class)
public final class CustomForm extends Form {
private final String title;
private final FormImage icon;
private final List<Component> content;
private CustomForm(String title, FormImage icon, List<Component> content) {
super(Form.Type.CUSTOM_FORM);
this.title = title;
this.icon = icon;
this.content = Collections.unmodifiableList(content);
}
public static Builder builder() {
return new Builder();
}
public static CustomForm of(String title, FormImage icon, List<Component> content) {
return new CustomForm(title, icon, content);
}
public CustomFormResponse parseResponse(String data) {
if (isClosed(data)) {
return CustomFormResponse.closed();
}
return CustomFormResponse.of(this, data);
}
public static final class Builder extends Form.Builder<Builder, CustomForm> {
private final List<Component> components = new ArrayList<>();
private FormImage icon;
public Builder icon(FormImage.Type type, String data) {
icon = FormImage.of(type, data);
return this;
}
public Builder iconPath(String path) {
return icon(FormImage.Type.PATH, path);
}
public Builder iconUrl(String url) {
return icon(FormImage.Type.URL, url);
}
public Builder component(Component component) {
components.add(component);
return this;
}
public Builder dropdown(DropdownComponent.Builder dropdownBuilder) {
return component(dropdownBuilder.translateAndBuild(this::translate));
}
public Builder dropdown(String text, int defaultOption, String... options) {
List<String> optionsList = new ArrayList<>();
for (String option : options) {
optionsList.add(translate(option));
}
return component(DropdownComponent.of(translate(text), optionsList, defaultOption));
}
public Builder dropdown(String text, String... options) {
return dropdown(text, -1, options);
}
public Builder input(String text, String placeholder, String defaultText) {
return component(InputComponent.of(
translate(text), translate(placeholder), translate(defaultText)
));
}
public Builder input(String text, String placeholder) {
return component(InputComponent.of(translate(text), translate(placeholder)));
}
public Builder input(String text) {
return component(InputComponent.of(translate(text)));
}
public Builder label(String text) {
return component(LabelComponent.of(translate(text)));
}
public Builder slider(String text, float min, float max, int step, float defaultValue) {
return component(SliderComponent.of(text, min, max, step, defaultValue));
}
public Builder slider(String text, float min, float max, int step) {
return slider(text, min, max, step, -1);
}
public Builder slider(String text, float min, float max, float defaultValue) {
return slider(text, min, max, -1, defaultValue);
}
public Builder slider(String text, float min, float max) {
return slider(text, min, max, -1, -1);
}
public Builder stepSlider(StepSliderComponent.Builder stepSliderBuilder) {
return component(stepSliderBuilder.translateAndBuild(this::translate));
}
public Builder stepSlider(String text, int defaultStep, String... steps) {
List<String> stepsList = new ArrayList<>();
for (String option : steps) {
stepsList.add(translate(option));
}
return component(StepSliderComponent.of(translate(text), stepsList, defaultStep));
}
public Builder stepSlider(String text, String... steps) {
return stepSlider(text, -1, steps);
}
public Builder toggle(String text, boolean defaultValue) {
return component(ToggleComponent.of(translate(text), defaultValue));
}
public Builder toggle(String text) {
return component(ToggleComponent.of(translate(text)));
}
@Override
public CustomForm build() {
CustomForm form = of(title, icon, components);
if (biResponseHandler != null) {
form.setResponseHandler(response -> biResponseHandler.accept(form, response));
return form;
}
form.setResponseHandler(responseHandler);
return form;
}
}
}

View file

@ -0,0 +1,137 @@
/*
* 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.common.form;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.geysermc.common.form.response.FormResponse;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
@Getter
public abstract class Form {
protected static final Gson GSON = new Gson();
private final Type type;
@Getter(AccessLevel.NONE)
protected String hardcodedJsonData = null;
@Setter protected Consumer<String> responseHandler;
public Form(Type type) {
this.type = type;
}
public String getJsonData() {
if (hardcodedJsonData != null) {
return hardcodedJsonData;
}
return GSON.toJson(this);
}
public abstract FormResponse parseResponse(String response);
@SuppressWarnings("unchecked")
public <T extends FormResponse> T parseResponseAs(String response) {
return (T) parseResponse(response);
}
public boolean isClosed(String response) {
return response == null || response.isEmpty() || response.equalsIgnoreCase("null");
}
@Getter
@RequiredArgsConstructor
public enum Type {
@SerializedName("form")
SIMPLE_FORM(SimpleForm.class),
@SerializedName("modal")
MODAL_FORM(ModalForm.class),
@SerializedName("custom_form")
CUSTOM_FORM(CustomForm.class);
private static final Type[] VALUES = values();
private final Class<? extends Form> typeClass;
public static Type getByOrdinal(int ordinal) {
return ordinal < VALUES.length ? VALUES[ordinal] : null;
}
}
public static abstract class Builder<T extends Builder<T, F>, F extends Form> {
protected String title = "";
protected BiFunction<String, String, String> translationHandler = null;
protected BiConsumer<F, String> biResponseHandler;
protected Consumer<String> responseHandler;
protected String locale;
public T title(String title) {
this.title = translate(title);
return self();
}
public T translator(BiFunction<String, String, String> translator, String locale) {
this.translationHandler = translator;
this.locale = locale;
return title(title);
}
public T translator(BiFunction<String, String, String> translator) {
return translator(translator, locale);
}
public T responseHandler(BiConsumer<F, String> responseHandler) {
biResponseHandler = responseHandler;
return self();
}
public T responseHandler(Consumer<String> responseHandler) {
this.responseHandler = responseHandler;
return self();
}
public abstract F build();
protected String translate(String text) {
if (translationHandler != null && text != null && !text.isEmpty()) {
return translationHandler.apply(text, locale);
}
return text;
}
@SuppressWarnings("unchecked")
protected T self() {
return (T) this;
}
}
}

View file

@ -0,0 +1,103 @@
/*
* 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.common.form;
import com.google.gson.annotations.JsonAdapter;
import lombok.Getter;
import org.geysermc.common.form.response.ModalFormResponse;
import org.geysermc.common.form.util.FormAdaptor;
@Getter
@JsonAdapter(FormAdaptor.class)
public class ModalForm extends Form {
private final String title;
private final String content;
private final String button1;
private final String button2;
private ModalForm(String title, String content, String button1, String button2) {
super(Type.MODAL_FORM);
this.title = title;
this.content = content;
this.button1 = button1;
this.button2 = button2;
}
public static Builder builder() {
return new Builder();
}
public static ModalForm of(String title, String content, String button1, String button2) {
return new ModalForm(title, content, button1, button2);
}
public ModalFormResponse parseResponse(String data) {
if (isClosed(data)) {
return ModalFormResponse.closed();
}
if ("true".equals(data)) {
return ModalFormResponse.of(0, button1);
} else if ("false".equals(data)) {
return ModalFormResponse.of(1, button2);
}
return ModalFormResponse.invalid();
}
public static final class Builder extends Form.Builder<Builder, ModalForm> {
private String content;
private String button1;
private String button2;
public Builder content(String content) {
this.content = translate(content);
return this;
}
public Builder button1(String button1) {
this.button1 = translate(button1);
return this;
}
public Builder button2(String button2) {
this.button2 = translate(button2);
return this;
}
@Override
public ModalForm build() {
ModalForm form = of(title, content, button1, button2);
if (biResponseHandler != null) {
form.setResponseHandler(response -> biResponseHandler.accept(form, response));
return form;
}
form.setResponseHandler(responseHandler);
return form;
}
}
}

View file

@ -0,0 +1,117 @@
/*
* 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.common.form;
import com.google.gson.annotations.JsonAdapter;
import lombok.Getter;
import org.geysermc.common.form.component.ButtonComponent;
import org.geysermc.common.form.response.SimpleFormResponse;
import org.geysermc.common.form.util.FormAdaptor;
import org.geysermc.common.form.util.FormImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Getter
@JsonAdapter(FormAdaptor.class)
public final class SimpleForm extends Form {
private final String title;
private final String content;
private final List<ButtonComponent> buttons;
private SimpleForm(String title, String content, List<ButtonComponent> buttons) {
super(Type.SIMPLE_FORM);
this.title = title;
this.content = content;
this.buttons = Collections.unmodifiableList(buttons);
}
public static Builder builder() {
return new Builder();
}
public static SimpleForm of(String title, String content, List<ButtonComponent> buttons) {
return new SimpleForm(title, content, buttons);
}
public SimpleFormResponse parseResponse(String data) {
if (isClosed(data)) {
return SimpleFormResponse.closed();
}
int buttonId;
try {
buttonId = Integer.parseInt(data);
} catch (Exception exception) {
return SimpleFormResponse.invalid();
}
if (buttonId >= buttons.size()) {
return SimpleFormResponse.invalid();
}
return SimpleFormResponse.of(buttonId, buttons.get(buttonId));
}
public static final class Builder extends Form.Builder<Builder, SimpleForm> {
private final List<ButtonComponent> buttons = new ArrayList<>();
private String content;
public Builder content(String content) {
this.content = translate(content);
return this;
}
public Builder button(String text, FormImage.Type type, String data) {
buttons.add(ButtonComponent.of(translate(text), type, data));
return this;
}
public Builder button(String text, FormImage image) {
buttons.add(ButtonComponent.of(translate(text), image));
return this;
}
public Builder button(String text) {
buttons.add(ButtonComponent.of(translate(text)));
return this;
}
@Override
public SimpleForm build() {
SimpleForm form = of(title, content, buttons);
if (biResponseHandler != null) {
form.setResponseHandler(response -> biResponseHandler.accept(form, response));
return form;
}
form.setResponseHandler(responseHandler);
return form;
}
}
}

View file

@ -23,35 +23,28 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.common.window.button;
package org.geysermc.common.form.component;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.RequiredArgsConstructor;
import org.geysermc.common.form.util.FormImage;
public class FormButton {
@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public final class ButtonComponent {
private final String text;
private final FormImage image;
@Getter
@Setter
private String text;
@Getter
private FormImage image;
public FormButton(String text) {
this.text = text;
public static ButtonComponent of(String text, FormImage image) {
return new ButtonComponent(text, image);
}
public FormButton(String text, FormImage image) {
this.text = text;
if (image.getData() != null && !image.getData().isEmpty()) {
this.image = image;
}
public static ButtonComponent of(String text, FormImage.Type type, String data) {
return of(text, FormImage.of(type, data));
}
public void setImage(FormImage image) {
if (image.getData() != null && !image.getData().isEmpty()) {
this.image = image;
}
public static ButtonComponent of(String text) {
return of(text, null);
}
}

View file

@ -0,0 +1,77 @@
/*
* 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.common.form.component;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Objects;
@Getter
public abstract class Component {
private final Type type;
private final String text;
Component(Type type, String text) {
Objects.requireNonNull(type, "Type cannot be null");
Objects.requireNonNull(text, "Text cannot be null");
this.type = type;
this.text = text;
}
@Getter
@RequiredArgsConstructor
public enum Type {
@SerializedName("dropdown")
DROPDOWN(DropdownComponent.class),
@SerializedName("input")
INPUT(InputComponent.class),
@SerializedName("label")
LABEL(LabelComponent.class),
@SerializedName("slider")
SLIDER(SliderComponent.class),
@SerializedName("step_slider")
STEP_SLIDER(StepSliderComponent.class),
@SerializedName("toggle")
TOGGLE(ToggleComponent.class);
private static final Type[] VALUES = values();
private final String name = name().toLowerCase();
private final Class<? extends Component> componentClass;
public static Type getByName(String name) {
for (Type type : VALUES) {
if (type.name.equals(name)) {
return type;
}
}
return null;
}
}
}

View file

@ -0,0 +1,102 @@
/*
* 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.common.form.component;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
@Getter
public class DropdownComponent extends Component {
private final List<String> options;
@SerializedName("default")
private final int defaultOption;
private DropdownComponent(String text, List<String> options, int defaultOption) {
super(Type.DROPDOWN, text);
this.options = Collections.unmodifiableList(options);
this.defaultOption = defaultOption;
}
public static DropdownComponent of(String text, List<String> options, int defaultOption) {
if (defaultOption == -1 || defaultOption >= options.size()) {
defaultOption = 0;
}
return new DropdownComponent(text, options, defaultOption);
}
public static Builder builder() {
return new Builder();
}
public static Builder builder(String text) {
return builder().text(text);
}
public static class Builder {
private final List<String> options = new ArrayList<>();
private String text;
private int defaultOption = 0;
public Builder text(String text) {
this.text = text;
return this;
}
public Builder option(String option, boolean isDefault) {
options.add(option);
if (isDefault) {
defaultOption = options.size() - 1;
}
return this;
}
public Builder option(String option) {
return option(option, false);
}
public Builder defaultOption(int defaultOption) {
this.defaultOption = defaultOption;
return this;
}
public DropdownComponent build() {
return of(text, options, defaultOption);
}
public DropdownComponent translateAndBuild(Function<String, String> translator) {
for (int i = 0; i < options.size(); i++) {
options.set(i, translator.apply(options.get(i)));
}
return of(translator.apply(text), options, defaultOption);
}
}
}

View file

@ -23,30 +23,32 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.common.window.component;
package org.geysermc.common.form.component;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
public class InputComponent extends FormComponent {
@Getter
public class InputComponent extends Component {
private final String placeholder;
@SerializedName("default")
private final String defaultText;
@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;
private InputComponent(String text, String placeholder, String defaultText) {
super(Type.INPUT, text);
this.placeholder = placeholder;
this.defaultText = defaultText;
}
public static InputComponent of(String text, String placeholder, String defaultText) {
return new InputComponent(text, placeholder, defaultText);
}
public static InputComponent of(String text, String placeholder) {
return new InputComponent(text, placeholder, "");
}
public static InputComponent of(String text) {
return new InputComponent(text, "", "");
}
}

View file

@ -23,20 +23,17 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.common.window.component;
package org.geysermc.common.form.component;
import lombok.Getter;
import lombok.Setter;
public class LabelComponent extends FormComponent {
@Getter
public class LabelComponent extends Component {
private LabelComponent(String text) {
super(Type.LABEL, text);
}
@Getter
@Setter
private String text;
public LabelComponent(String text) {
super("label");
this.text = text;
public static LabelComponent of(String text) {
return new LabelComponent(text);
}
}

View file

@ -0,0 +1,73 @@
/*
* 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.common.form.component;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
@Getter
public final class SliderComponent extends Component {
private final float min;
private final float max;
private final int step;
@SerializedName("default")
private final float defaultValue;
private SliderComponent(String text, float min, float max, int step, float defaultValue) {
super(Type.SLIDER, text);
this.min = min;
this.max = max;
this.step = step;
this.defaultValue = defaultValue;
}
public static SliderComponent of(String text, float min, float max, int step, float defaultValue) {
min = Math.max(min, 0f);
max = Math.max(max, min);
if (step < 1) {
step = 1;
}
if (defaultValue == -1f) {
defaultValue = (int) Math.floor(min + max / 2D);
}
return new SliderComponent(text, min, max, step, defaultValue);
}
public static SliderComponent of(String text, float min, float max, int step) {
return of(text, min, max, step, -1);
}
public static SliderComponent of(String text, float min, float max, float defaultValue) {
return of(text, min, max, -1, defaultValue);
}
public static SliderComponent of(String text, float min, float max) {
return of(text, min, max, -1, -1);
}
}

View file

@ -0,0 +1,116 @@
/*
* 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.common.form.component;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
@Getter
public final class StepSliderComponent extends Component {
private final List<String> steps;
@SerializedName("default")
private final int defaultStep;
private StepSliderComponent(String text, List<String> steps, int defaultStep) {
super(Type.STEP_SLIDER, text);
this.steps = Collections.unmodifiableList(steps);
this.defaultStep = defaultStep;
}
public static StepSliderComponent of(String text, List<String> steps, int defaultStep) {
if (text == null) {
text = "";
}
if (defaultStep >= steps.size() || defaultStep == -1) {
defaultStep = 0;
}
return new StepSliderComponent(text, steps, defaultStep);
}
public static StepSliderComponent of(String text, int defaultStep, String... steps) {
return of(text, Arrays.asList(steps), defaultStep);
}
public static StepSliderComponent of(String text, String... steps) {
return of(text, 0, steps);
}
public static Builder builder() {
return new Builder();
}
public static Builder builder(String text) {
return builder().text(text);
}
public static final class Builder {
private final List<String> steps = new ArrayList<>();
private String text;
private int defaultStep;
public Builder text(String text) {
this.text = text;
return this;
}
public Builder step(String step, boolean defaultStep) {
steps.add(step);
if (defaultStep) {
this.defaultStep = steps.size() - 1;
}
return this;
}
public Builder step(String step) {
return step(step, false);
}
public Builder defaultStep(int defaultStep) {
this.defaultStep = defaultStep;
return this;
}
public StepSliderComponent build() {
return of(text, steps, defaultStep);
}
public StepSliderComponent translateAndBuild(Function<String, String> translator) {
for (int i = 0; i < steps.size(); i++) {
steps.set(i, translator.apply(steps.get(i)));
}
return of(translator.apply(text), steps, defaultStep);
}
}
}

View file

@ -23,29 +23,26 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.common.window.component;
package org.geysermc.common.form.component;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
public class ToggleComponent extends FormComponent {
@Getter
public class ToggleComponent extends Component {
@SerializedName("default")
private final boolean defaultValue;
@Getter
@Setter
private String text;
@Getter
@Setter
private boolean defaultValue;
public ToggleComponent(String text) {
this(text, false);
}
public ToggleComponent(String text, boolean defaultValue) {
super("toggle");
this.text = text;
private ToggleComponent(String text, boolean defaultValue) {
super(Type.TOGGLE, text);
this.defaultValue = defaultValue;
}
public static ToggleComponent of(String text, boolean defaultValue) {
return new ToggleComponent(text, defaultValue);
}
public static ToggleComponent of(String text) {
return of(text, false);
}
}

View file

@ -0,0 +1,193 @@
/*
* 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.common.form.response;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonPrimitive;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import org.geysermc.common.form.CustomForm;
import org.geysermc.common.form.component.Component;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
@ToString
public class CustomFormResponse implements FormResponse {
private static final Gson GSON = new Gson();
private static final CustomFormResponse CLOSED =
new CustomFormResponse(true, false, null, null);
private static final CustomFormResponse INVALID =
new CustomFormResponse(false, true, null, null);
private final boolean closed;
private final boolean invalid;
private final JsonArray responses;
private final List<Component.Type> componentTypes;
private int index = -1;
public static CustomFormResponse closed() {
return CLOSED;
}
public static CustomFormResponse invalid() {
return INVALID;
}
public static CustomFormResponse of(CustomForm form, String responseData) {
JsonArray responses = GSON.fromJson(responseData, JsonArray.class);
List<Component.Type> types = new ArrayList<>();
for (Component component : form.getContent()) {
types.add(component.getType());
}
return of(types, responses);
}
public static CustomFormResponse of(List<Component.Type> componentTypes,
JsonArray responses) {
if (componentTypes.size() != responses.size()) {
return invalid();
}
return new CustomFormResponse(false, false, responses,
Collections.unmodifiableList(componentTypes));
}
@SuppressWarnings("unchecked")
public <T> T next(boolean includeLabels) {
if (!hasNext()) {
return null;
}
while (++index < responses.size()) {
Component.Type type = componentTypes.get(index);
if (type == Component.Type.LABEL && !includeLabels) {
continue;
}
return (T) getDataFromType(type, index);
}
return null; // we don't have anything to check anymore
}
public <T> T next() {
return next(false);
}
public void skip(int amount) {
index += amount;
}
public void skip() {
skip(1);
}
public void index(int index) {
this.index = index;
}
public boolean hasNext() {
return responses.size() > index + 1;
}
public JsonPrimitive get(int index) {
try {
return responses.get(index).getAsJsonPrimitive();
} catch (IllegalStateException exception) {
wrongType(index, "a primitive");
return null;
}
}
public int getDropdown(int index) {
JsonPrimitive primitive = get(index);
if (!primitive.isNumber()) {
wrongType(index, "dropdown");
}
return primitive.getAsInt();
}
public String getInput(int index) {
JsonPrimitive primitive = get(index);
if (!primitive.isString()) {
wrongType(index, "input");
}
return primitive.getAsString();
}
public float getSlider(int index) {
JsonPrimitive primitive = get(index);
if (!primitive.isNumber()) {
wrongType(index, "slider");
}
return primitive.getAsFloat();
}
public int getStepSlide(int index) {
JsonPrimitive primitive = get(index);
if (!primitive.isNumber()) {
wrongType(index, "step slider");
}
return primitive.getAsInt();
}
public boolean getToggle(int index) {
JsonPrimitive primitive = get(index);
if (!primitive.isBoolean()) {
wrongType(index, "toggle");
}
return primitive.getAsBoolean();
}
private Object getDataFromType(Component.Type type, int index) {
switch (type) {
case DROPDOWN:
return getDropdown(index);
case INPUT:
return getInput(index);
case SLIDER:
return getSlider(index);
case STEP_SLIDER:
return getStepSlide(index);
case TOGGLE:
return getToggle(index);
default:
return null; // label e.g. is always null
}
}
private void wrongType(int index, String expected) {
throw new IllegalStateException(String.format(
"Expected %s on %s, got %s",
expected, index, responses.get(index).toString()));
}
}

View file

@ -23,7 +23,13 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.common.window.response;
package org.geysermc.common.form.response;
public interface FormResponse {
boolean isClosed();
boolean isInvalid();
default boolean isCorrect() {
return !isClosed() && !isInvalid();
}
}

View file

@ -23,37 +23,38 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.common.window;
package org.geysermc.common.form.response;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.common.window.response.FormResponse;
import lombok.RequiredArgsConstructor;
public abstract class FormWindow {
@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public final class ModalFormResponse implements FormResponse {
private static final ModalFormResponse CLOSED =
new ModalFormResponse(true, false, -1, null);
private static final ModalFormResponse INVALID =
new ModalFormResponse(false, true, -1, null);
private final boolean closed;
private final boolean invalid;
@Getter
private final String type;
private final int clickedButtonId;
private final String clickedButtonText;
@Getter
protected FormResponse response;
@Getter
@Setter
protected boolean closed;
public FormWindow(String type) {
this.type = type;
public static ModalFormResponse closed() {
return CLOSED;
}
// Lombok won't work here, so we need to make our own method
public void setResponse(FormResponse response) {
this.response = response;
public static ModalFormResponse invalid() {
return INVALID;
}
@JsonIgnore
public abstract String getJSONData();
public abstract void setResponse(String response);
public static ModalFormResponse of(int clickedButtonId, String clickedButtonText) {
return new ModalFormResponse(false, false, clickedButtonId, clickedButtonText);
}
public boolean getResult() {
return clickedButtonId == 0;
}
}

View file

@ -23,47 +23,33 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.common.window.component;
package org.geysermc.common.form.response;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.RequiredArgsConstructor;
import org.geysermc.common.form.component.ButtonComponent;
import java.util.ArrayList;
import java.util.List;
@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public final class SimpleFormResponse implements FormResponse {
private static final SimpleFormResponse CLOSED = new SimpleFormResponse(true, false, -1, null);
private static final SimpleFormResponse INVALID = new SimpleFormResponse(false, true, -1, null);
private final boolean closed;
private final boolean invalid;
public class StepSliderComponent extends FormComponent {
private final int clickedButtonId;
private final ButtonComponent clickedButton;
@Getter
@Setter
private String text;
@Getter
private List<String> steps;
@Getter
@Setter
private int defaultStepIndex;
public StepSliderComponent(String text) {
this(text, new ArrayList<String>());
public static SimpleFormResponse closed() {
return CLOSED;
}
public StepSliderComponent(String text, List<String> steps) {
this(text, steps, 0);
public static SimpleFormResponse invalid() {
return INVALID;
}
public StepSliderComponent(String text, List<String> 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;
public static SimpleFormResponse of(int clickedButtonId, ButtonComponent clickedButton) {
return new SimpleFormResponse(false, false, clickedButtonId, clickedButton);
}
}

View file

@ -0,0 +1,126 @@
/*
* 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.common.form.util;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import org.geysermc.common.form.CustomForm;
import org.geysermc.common.form.Form;
import org.geysermc.common.form.ModalForm;
import org.geysermc.common.form.SimpleForm;
import org.geysermc.common.form.component.ButtonComponent;
import org.geysermc.common.form.component.Component;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
public class FormAdaptor implements JsonDeserializer<Form>, JsonSerializer<Form> {
private static final Type LIST_BUTTON_TYPE =
new TypeToken<List<ButtonComponent>>() {}.getType();
@Override
public Form deserialize(JsonElement jsonElement, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException {
if (!jsonElement.isJsonObject()) {
throw new JsonParseException("Form has to be a JsonObject");
}
JsonObject json = jsonElement.getAsJsonObject();
if (typeOfT == SimpleForm.class) {
String title = json.get("title").getAsString();
String content = json.get("content").getAsString();
List<ButtonComponent> buttons = context
.deserialize(json.get("buttons"), LIST_BUTTON_TYPE);
return SimpleForm.of(title, content, buttons);
}
if (typeOfT == ModalForm.class) {
String title = json.get("title").getAsString();
String content = json.get("content").getAsString();
String button1 = json.get("button1").getAsString();
String button2 = json.get("button2").getAsString();
return ModalForm.of(title, content, button1, button2);
}
if (typeOfT == CustomForm.class) {
String title = json.get("title").getAsString();
FormImage icon = context.deserialize(json.get("icon"), FormImage.class);
List<Component> content = new ArrayList<>();
JsonArray contentArray = json.getAsJsonArray("content");
for (JsonElement contentElement : contentArray) {
String typeName = contentElement.getAsJsonObject().get("type").getAsString();
Component.Type type = Component.Type.getByName(typeName);
if (type == null) {
throw new JsonParseException("Failed to find Component type " + typeName);
}
content.add(context.deserialize(contentElement, type.getComponentClass()));
}
return CustomForm.of(title, icon, content);
}
return null;
}
@Override
public JsonElement serialize(Form src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();
result.add("type", context.serialize(src.getType()));
if (typeOfSrc == SimpleForm.class) {
SimpleForm form = (SimpleForm) src;
result.addProperty("title", form.getTitle());
result.addProperty("content", form.getContent());
result.add("buttons", context.serialize(form.getButtons(), LIST_BUTTON_TYPE));
return result;
}
if (typeOfSrc == ModalForm.class) {
ModalForm form = (ModalForm) src;
result.addProperty("title", form.getTitle());
result.addProperty("content", form.getContent());
result.addProperty("button1", form.getButton1());
result.addProperty("button2", form.getButton2());
return result;
}
if (typeOfSrc == CustomForm.class) {
CustomForm form = (CustomForm) src;
result.addProperty("title", form.getTitle());
result.add("icon", context.serialize(form.getIcon()));
result.add("content", context.serialize(form.getContent()));
return result;
}
return null;
}
}

View file

@ -23,36 +23,32 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.common.window.button;
package org.geysermc.common.form.util;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class FormImage {
private final String type;
private final String data;
@Getter
@Setter
private String type;
@Getter
@Setter
private String data;
public FormImage(FormImageType type, String data) {
this.type = type.getName();
this.data = data;
public static FormImage of(String type, String data) {
return new FormImage(type, data);
}
public enum FormImageType {
public static FormImage of(Type type, String data) {
return of(type.getName(), data);
}
@RequiredArgsConstructor
public enum Type {
PATH("path"),
URL("url");
@Getter
private String name;
FormImageType(String name) {
this.name = name;
}
@Getter private final String name;
@Override
public String toString() {

View file

@ -1,71 +0,0 @@
/*
* 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.common.window;
import lombok.Getter;
import org.geysermc.common.window.CustomFormWindow;
import org.geysermc.common.window.button.FormImage;
import org.geysermc.common.window.component.FormComponent;
import org.geysermc.common.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;
}
}

View file

@ -1,165 +0,0 @@
/*
* 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.common.window;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.common.window.button.FormImage;
import org.geysermc.common.window.component.*;
import org.geysermc.common.window.response.CustomFormResponse;
import org.geysermc.common.window.response.FormResponseData;
import java.io.IOException;
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<FormComponent> content;
public CustomFormWindow(String title) {
this(title, new ArrayList<>());
}
public CustomFormWindow(String title, List<FormComponent> content) {
this(title, content, (FormImage) null);
}
public CustomFormWindow(String title, List<FormComponent> content, String icon) {
this(title, content, new FormImage(FormImage.FormImageType.URL, icon));
}
public CustomFormWindow(String title, List<FormComponent> 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 = "";
try {
toModify = new ObjectMapper().writeValueAsString(this);
} catch (JsonProcessingException e) { }
//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") || data.isEmpty()) {
closed = true;
return;
}
int i = 0;
Map<Integer, FormResponseData> dropdownResponses = new HashMap<Integer, FormResponseData>();
Map<Integer, String> inputResponses = new HashMap<Integer, String>();
Map<Integer, Float> sliderResponses = new HashMap<Integer, Float>();
Map<Integer, FormResponseData> stepSliderResponses = new HashMap<Integer, FormResponseData>();
Map<Integer, Boolean> toggleResponses = new HashMap<Integer, Boolean>();
Map<Integer, Object> responses = new HashMap<Integer, Object>();
Map<Integer, String> labelResponses = new HashMap<Integer, String>();
List<String> componentResponses = new ArrayList<>();
try {
componentResponses = new ObjectMapper().readValue(data, new TypeReference<List<String>>(){});
} catch (IOException e) { }
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);
}
}

View file

@ -1,82 +0,0 @@
/*
* 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.common.window;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.common.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() {
try {
return new ObjectMapper().writeValueAsString(this);
} catch (JsonProcessingException e) {
return "";
}
}
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);
}
}
}

View file

@ -1,94 +0,0 @@
/*
* 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.common.window;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.common.window.button.FormButton;
import org.geysermc.common.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<FormButton> buttons;
public SimpleFormWindow(String title, String content) {
this(title, content, new ArrayList<FormButton>());
}
public SimpleFormWindow(String title, String content, List<FormButton> buttons) {
super("form");
this.title = title;
this.content = content;
this.buttons = buttons;
}
@Override
public String getJSONData() {
try {
return new ObjectMapper().writeValueAsString(this);
} catch (JsonProcessingException e) {
return "";
}
}
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));
}
}

View file

@ -1,56 +0,0 @@
/*
* 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.common.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<String> 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;
}
}

View file

@ -1,38 +0,0 @@
/*
* 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.common.window.component;
import lombok.Getter;
public abstract class FormComponent {
@Getter
private final String type;
public FormComponent(String type) {
this.type = type;
}
}

View file

@ -1,65 +0,0 @@
/*
* 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.common.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 = Math.max(min, 0f);
this.max = max > this.min ? max : this.min;
if (step != -1f && step > 0)
this.step = step;
if (defaultValue != -1f)
this.defaultValue = defaultValue;
}
}

View file

@ -1,46 +0,0 @@
/*
* 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.common.window.response;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.geysermc.common.window.response.FormResponse;
import org.geysermc.common.window.response.FormResponseData;
import java.util.Map;
@Getter
@AllArgsConstructor
public class CustomFormResponse implements FormResponse {
private Map<Integer, Object> responses;
private Map<Integer, FormResponseData> dropdownResponses;
private Map<Integer, String> inputResponses;
private Map<Integer, Float> sliderResponses;
private Map<Integer, FormResponseData> stepSliderResponses;
private Map<Integer, Boolean> toggleResponses;
private Map<Integer, String> labelResponses;
}

View file

@ -1,37 +0,0 @@
/*
* 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.common.window.response;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public class FormResponseData {
private int elementID;
private String elementContent;
}

View file

@ -1,38 +0,0 @@
/*
* 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.common.window.response;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.geysermc.common.window.response.FormResponse;
@Getter
@AllArgsConstructor
public class ModalFormResponse implements FormResponse {
private int clickedButtonId;
private String clickedButtonText;
}

View file

@ -1,39 +0,0 @@
/*
* 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.common.window.response;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.geysermc.common.window.button.FormButton;
import org.geysermc.common.window.response.FormResponse;
@Getter
@AllArgsConstructor
public class SimpleFormResponse implements FormResponse {
private int clickedButtonId;
private FormButton clickedButton;
}