Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-26 16:12:46 +01:00
First version of the Forms rewrite
The next version will split the implementation from the api
Dieser Commit ist enthalten in:
Ursprung
f8939ca5de
Commit
c9102348de
@ -15,7 +15,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.8.2</version>
|
<version>2.8.5</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
177
common/src/main/java/org/geysermc/common/form/CustomForm.java
Normale Datei
177
common/src/main/java/org/geysermc/common/form/CustomForm.java
Normale Datei
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
137
common/src/main/java/org/geysermc/common/form/Form.java
Normale Datei
137
common/src/main/java/org/geysermc/common/form/Form.java
Normale Datei
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
103
common/src/main/java/org/geysermc/common/form/ModalForm.java
Normale Datei
103
common/src/main/java/org/geysermc/common/form/ModalForm.java
Normale Datei
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
common/src/main/java/org/geysermc/common/form/SimpleForm.java
Normale Datei
117
common/src/main/java/org/geysermc/common/form/SimpleForm.java
Normale Datei
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,35 +23,28 @@
|
|||||||
* @link https://github.com/GeyserMC/Geyser
|
* @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.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
|
public static ButtonComponent of(String text, FormImage image) {
|
||||||
@Setter
|
return new ButtonComponent(text, image);
|
||||||
private String text;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private FormImage image;
|
|
||||||
|
|
||||||
public FormButton(String text) {
|
|
||||||
this.text = text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FormButton(String text, FormImage image) {
|
public static ButtonComponent of(String text, FormImage.Type type, String data) {
|
||||||
this.text = text;
|
return of(text, FormImage.of(type, data));
|
||||||
|
|
||||||
if (image.getData() != null && !image.getData().isEmpty()) {
|
|
||||||
this.image = image;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setImage(FormImage image) {
|
public static ButtonComponent of(String text) {
|
||||||
if (image.getData() != null && !image.getData().isEmpty()) {
|
return of(text, null);
|
||||||
this.image = image;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,30 +23,32 @@
|
|||||||
* @link https://github.com/GeyserMC/Geyser
|
* @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.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
|
private InputComponent(String text, String placeholder, String defaultText) {
|
||||||
@Setter
|
super(Type.INPUT, text);
|
||||||
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.placeholder = placeholder;
|
||||||
this.defaultText = defaultText;
|
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, "", "");
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,20 +23,17 @@
|
|||||||
* @link https://github.com/GeyserMC/Geyser
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.geysermc.common.window.component;
|
package org.geysermc.common.form.component;
|
||||||
|
|
||||||
import lombok.Getter;
|
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
|
public static LabelComponent of(String text) {
|
||||||
@Setter
|
return new LabelComponent(text);
|
||||||
private String text;
|
|
||||||
|
|
||||||
public LabelComponent(String text) {
|
|
||||||
super("label");
|
|
||||||
|
|
||||||
this.text = text;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,29 +23,26 @@
|
|||||||
* @link https://github.com/GeyserMC/Geyser
|
* @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.Getter;
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
public class ToggleComponent extends FormComponent {
|
@Getter
|
||||||
|
public class ToggleComponent extends Component {
|
||||||
|
@SerializedName("default")
|
||||||
|
private final boolean defaultValue;
|
||||||
|
|
||||||
@Getter
|
private ToggleComponent(String text, boolean defaultValue) {
|
||||||
@Setter
|
super(Type.TOGGLE, text);
|
||||||
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;
|
|
||||||
this.defaultValue = defaultValue;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
@ -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()));
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,13 @@
|
|||||||
* @link https://github.com/GeyserMC/Geyser
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.geysermc.common.window.response;
|
package org.geysermc.common.form.response;
|
||||||
|
|
||||||
public interface FormResponse {
|
public interface FormResponse {
|
||||||
|
boolean isClosed();
|
||||||
|
boolean isInvalid();
|
||||||
|
|
||||||
|
default boolean isCorrect() {
|
||||||
|
return !isClosed() && !isInvalid();
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,37 +23,38 @@
|
|||||||
* @link https://github.com/GeyserMC/Geyser
|
* @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.Getter;
|
||||||
import lombok.Setter;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.geysermc.common.window.response.FormResponse;
|
|
||||||
|
|
||||||
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 int clickedButtonId;
|
||||||
private final String type;
|
private final String clickedButtonText;
|
||||||
|
|
||||||
@Getter
|
public static ModalFormResponse closed() {
|
||||||
protected FormResponse response;
|
return CLOSED;
|
||||||
|
|
||||||
@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 static ModalFormResponse invalid() {
|
||||||
public void setResponse(FormResponse response) {
|
return INVALID;
|
||||||
this.response = response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnore
|
public static ModalFormResponse of(int clickedButtonId, String clickedButtonText) {
|
||||||
public abstract String getJSONData();
|
return new ModalFormResponse(false, false, clickedButtonId, clickedButtonText);
|
||||||
|
}
|
||||||
public abstract void setResponse(String response);
|
|
||||||
|
|
||||||
|
public boolean getResult() {
|
||||||
|
return clickedButtonId == 0;
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,47 +23,33 @@
|
|||||||
* @link https://github.com/GeyserMC/Geyser
|
* @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.Getter;
|
||||||
import lombok.Setter;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.geysermc.common.form.component.ButtonComponent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
@Getter
|
||||||
import java.util.List;
|
@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
|
public static SimpleFormResponse closed() {
|
||||||
@Setter
|
return CLOSED;
|
||||||
private String text;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private List<String> steps;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private int defaultStepIndex;
|
|
||||||
|
|
||||||
public StepSliderComponent(String text) {
|
|
||||||
this(text, new ArrayList<String>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public StepSliderComponent(String text, List<String> steps) {
|
public static SimpleFormResponse invalid() {
|
||||||
this(text, steps, 0);
|
return INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StepSliderComponent(String text, List<String> steps, int defaultStepIndex) {
|
public static SimpleFormResponse of(int clickedButtonId, ButtonComponent clickedButton) {
|
||||||
super("step_slider");
|
return new SimpleFormResponse(false, false, clickedButtonId, clickedButton);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
126
common/src/main/java/org/geysermc/common/form/util/FormAdaptor.java
Normale Datei
126
common/src/main/java/org/geysermc/common/form/util/FormAdaptor.java
Normale Datei
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -23,36 +23,32 @@
|
|||||||
* @link https://github.com/GeyserMC/Geyser
|
* @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.Getter;
|
||||||
import lombok.Setter;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class FormImage {
|
public class FormImage {
|
||||||
|
private final String type;
|
||||||
|
private final String data;
|
||||||
|
|
||||||
@Getter
|
public static FormImage of(String type, String data) {
|
||||||
@Setter
|
return new FormImage(type, data);
|
||||||
private String type;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private String data;
|
|
||||||
|
|
||||||
public FormImage(FormImageType type, String data) {
|
|
||||||
this.type = type.getName();
|
|
||||||
this.data = data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum FormImageType {
|
public static FormImage of(Type type, String data) {
|
||||||
|
return of(type.getName(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum Type {
|
||||||
PATH("path"),
|
PATH("path"),
|
||||||
URL("url");
|
URL("url");
|
||||||
|
|
||||||
@Getter
|
@Getter private final String name;
|
||||||
private String name;
|
|
||||||
|
|
||||||
FormImageType(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -39,7 +39,6 @@ import org.geysermc.connector.utils.LoginEncryptionUtils;
|
|||||||
import org.geysermc.connector.utils.MathUtils;
|
import org.geysermc.connector.utils.MathUtils;
|
||||||
import org.geysermc.connector.utils.ResourcePack;
|
import org.geysermc.connector.utils.ResourcePack;
|
||||||
import org.geysermc.connector.utils.ResourcePackManifest;
|
import org.geysermc.connector.utils.ResourcePackManifest;
|
||||||
import org.geysermc.connector.utils.SettingsUtils;
|
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -139,11 +138,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(ModalFormResponsePacket packet) {
|
public boolean handle(ModalFormResponsePacket packet) {
|
||||||
if (packet.getFormId() == SettingsUtils.SETTINGS_FORM_ID) {
|
session.getFormCache().handleResponse(packet);
|
||||||
return SettingsUtils.handleSettingsForm(session, packet.getFormData());
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return LoginEncryptionUtils.authenticateFromForm(session, connector, packet.getFormId(), packet.getFormData());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean couldLoginUserByName(String bedrockUsername) {
|
private boolean couldLoginUserByName(String bedrockUsername) {
|
||||||
@ -170,7 +166,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||||||
if (!session.isLoggedIn() && !session.isLoggingIn() && session.getConnector().getAuthType() == AuthType.ONLINE) {
|
if (!session.isLoggedIn() && !session.isLoggingIn() && session.getConnector().getAuthType() == AuthType.ONLINE) {
|
||||||
// TODO it is safer to key authentication on something that won't change (UUID, not username)
|
// TODO it is safer to key authentication on something that won't change (UUID, not username)
|
||||||
if (!couldLoginUserByName(session.getAuthData().getName())) {
|
if (!couldLoginUserByName(session.getAuthData().getName())) {
|
||||||
LoginEncryptionUtils.showLoginWindow(session);
|
LoginEncryptionUtils.buildAndShowLoginWindow(session);
|
||||||
}
|
}
|
||||||
// else we were able to log the user in
|
// else we were able to log the user in
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,7 @@ import it.unimi.dsi.fastutil.objects.Object2LongMap;
|
|||||||
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.geysermc.common.window.CustomFormWindow;
|
import org.geysermc.common.form.Form;
|
||||||
import org.geysermc.common.window.FormWindow;
|
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.command.CommandSender;
|
import org.geysermc.connector.command.CommandSender;
|
||||||
import org.geysermc.connector.common.AuthType;
|
import org.geysermc.connector.common.AuthType;
|
||||||
@ -101,7 +100,7 @@ public class GeyserSession implements CommandSender {
|
|||||||
private EntityCache entityCache;
|
private EntityCache entityCache;
|
||||||
private InventoryCache inventoryCache;
|
private InventoryCache inventoryCache;
|
||||||
private WorldCache worldCache;
|
private WorldCache worldCache;
|
||||||
private WindowCache windowCache;
|
private FormCache formCache;
|
||||||
@Setter
|
@Setter
|
||||||
private TeleportCache teleportCache;
|
private TeleportCache teleportCache;
|
||||||
|
|
||||||
@ -192,9 +191,6 @@ public class GeyserSession implements CommandSender {
|
|||||||
|
|
||||||
private boolean reducedDebugInfo = false;
|
private boolean reducedDebugInfo = false;
|
||||||
|
|
||||||
@Setter
|
|
||||||
private CustomFormWindow settingsForm;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The op permission level set by the server
|
* The op permission level set by the server
|
||||||
*/
|
*/
|
||||||
@ -239,7 +235,7 @@ public class GeyserSession implements CommandSender {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the last text inputted into a sign.
|
* Stores the last text inputted into a sign.
|
||||||
*
|
* <p>
|
||||||
* Bedrock sends packets every time you update the sign, Java only wants the final packet.
|
* Bedrock sends packets every time you update the sign, Java only wants the final packet.
|
||||||
* Until we determine that the user has finished editing, we save the sign's current status.
|
* Until we determine that the user has finished editing, we save the sign's current status.
|
||||||
*/
|
*/
|
||||||
@ -256,7 +252,7 @@ public class GeyserSession implements CommandSender {
|
|||||||
this.entityCache = new EntityCache(this);
|
this.entityCache = new EntityCache(this);
|
||||||
this.inventoryCache = new InventoryCache(this);
|
this.inventoryCache = new InventoryCache(this);
|
||||||
this.worldCache = new WorldCache(this);
|
this.worldCache = new WorldCache(this);
|
||||||
this.windowCache = new WindowCache(this);
|
this.formCache = new FormCache(this);
|
||||||
|
|
||||||
this.playerEntity = new PlayerEntity(new GameProfile(UUID.randomUUID(), "unknown"), 1, 1, Vector3f.ZERO, Vector3f.ZERO, Vector3f.ZERO);
|
this.playerEntity = new PlayerEntity(new GameProfile(UUID.randomUUID(), "unknown"), 1, 1, Vector3f.ZERO, Vector3f.ZERO, Vector3f.ZERO);
|
||||||
this.inventory = new PlayerInventory();
|
this.inventory = new PlayerInventory();
|
||||||
@ -497,7 +493,7 @@ public class GeyserSession implements CommandSender {
|
|||||||
this.entityCache = null;
|
this.entityCache = null;
|
||||||
this.worldCache = null;
|
this.worldCache = null;
|
||||||
this.inventoryCache = null;
|
this.inventoryCache = null;
|
||||||
this.windowCache = null;
|
this.formCache = null;
|
||||||
|
|
||||||
closed = true;
|
closed = true;
|
||||||
}
|
}
|
||||||
@ -533,10 +529,6 @@ public class GeyserSession implements CommandSender {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendForm(FormWindow window, int id) {
|
|
||||||
windowCache.showWindow(window, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRenderDistance(int renderDistance) {
|
public void setRenderDistance(int renderDistance) {
|
||||||
renderDistance = GenericMath.ceil(++renderDistance * MathUtils.SQRT_OF_TWO); //square to circle
|
renderDistance = GenericMath.ceil(++renderDistance * MathUtils.SQRT_OF_TWO); //square to circle
|
||||||
if (renderDistance > 32) renderDistance = 32; // <3 u ViaVersion but I don't like crashing clients x)
|
if (renderDistance > 32) renderDistance = 32; // <3 u ViaVersion but I don't like crashing clients x)
|
||||||
@ -551,8 +543,12 @@ public class GeyserSession implements CommandSender {
|
|||||||
return this.upstream.getAddress();
|
return this.upstream.getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendForm(FormWindow window) {
|
public void sendForm(Form form) {
|
||||||
windowCache.showWindow(window);
|
formCache.showForm(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendForm(Form.Builder<?, ?> formBuilder) {
|
||||||
|
formCache.showForm(formBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startGame() {
|
private void startGame() {
|
||||||
|
@ -26,56 +26,54 @@
|
|||||||
package org.geysermc.connector.network.session.cache;
|
package org.geysermc.connector.network.session.cache;
|
||||||
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.ModalFormRequestPacket;
|
import com.nukkitx.protocol.bedrock.packet.ModalFormRequestPacket;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.ModalFormResponsePacket;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.Getter;
|
import org.geysermc.common.form.Form;
|
||||||
|
|
||||||
import org.geysermc.common.window.FormWindow;
|
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
|
||||||
public class WindowCache {
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
private GeyserSession session;
|
@RequiredArgsConstructor
|
||||||
|
public class FormCache {
|
||||||
|
private final AtomicInteger formId = new AtomicInteger(0);
|
||||||
|
private final Int2ObjectMap<Form> forms = new Int2ObjectOpenHashMap<>();
|
||||||
|
private final GeyserSession session;
|
||||||
|
|
||||||
@Getter
|
public int addForm(Form form) {
|
||||||
private Int2ObjectMap<FormWindow> windows = new Int2ObjectOpenHashMap<>();
|
int windowId = formId.getAndIncrement();
|
||||||
|
forms.put(windowId, form);
|
||||||
public WindowCache(GeyserSession session) {
|
return windowId;
|
||||||
this.session = session;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addWindow(FormWindow window) {
|
public int showForm(Form form) {
|
||||||
windows.put(windows.size() + 1, window);
|
int windowId = addForm(form);
|
||||||
|
|
||||||
|
ModalFormRequestPacket formRequestPacket = new ModalFormRequestPacket();
|
||||||
|
formRequestPacket.setFormId(windowId);
|
||||||
|
formRequestPacket.setFormData(form.getJsonData());
|
||||||
|
|
||||||
|
session.sendUpstreamPacket(formRequestPacket);
|
||||||
|
return windowId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addWindow(FormWindow window, int id) {
|
public void handleResponse(ModalFormResponsePacket response) {
|
||||||
windows.put(id, window);
|
Form form = forms.get(response.getFormId());
|
||||||
}
|
if (form == null) {
|
||||||
|
|
||||||
public void showWindow(FormWindow window) {
|
|
||||||
showWindow(window, windows.size() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showWindow(int id) {
|
|
||||||
if (!windows.containsKey(id))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ModalFormRequestPacket formRequestPacket = new ModalFormRequestPacket();
|
|
||||||
formRequestPacket.setFormId(id);
|
|
||||||
formRequestPacket.setFormData(windows.get(id).getJSONData());
|
|
||||||
|
|
||||||
session.sendUpstreamPacket(formRequestPacket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showWindow(FormWindow window, int id) {
|
Consumer<String> responseConsumer = form.getResponseHandler();
|
||||||
ModalFormRequestPacket formRequestPacket = new ModalFormRequestPacket();
|
if (responseConsumer != null) {
|
||||||
formRequestPacket.setFormId(id);
|
responseConsumer.accept(response.getFormData().trim());
|
||||||
formRequestPacket.setFormData(window.getJSONData());
|
}
|
||||||
|
|
||||||
session.sendUpstreamPacket(formRequestPacket);
|
removeWindow(response.getFormId());
|
||||||
|
}
|
||||||
|
|
||||||
addWindow(window, id);
|
public boolean removeWindow(int id) {
|
||||||
|
return forms.remove(id) != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,6 +27,7 @@ package org.geysermc.connector.network.translators.bedrock;
|
|||||||
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.ServerSettingsRequestPacket;
|
import com.nukkitx.protocol.bedrock.packet.ServerSettingsRequestPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.ServerSettingsResponsePacket;
|
import com.nukkitx.protocol.bedrock.packet.ServerSettingsResponsePacket;
|
||||||
|
import org.geysermc.common.form.CustomForm;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.Translator;
|
import org.geysermc.connector.network.translators.Translator;
|
||||||
@ -37,11 +38,12 @@ public class BedrockServerSettingsRequestTranslator extends PacketTranslator<Ser
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(ServerSettingsRequestPacket packet, GeyserSession session) {
|
public void translate(ServerSettingsRequestPacket packet, GeyserSession session) {
|
||||||
SettingsUtils.buildForm(session);
|
CustomForm window = SettingsUtils.buildForm(session);
|
||||||
|
int windowId = session.getFormCache().addForm(window);
|
||||||
|
|
||||||
ServerSettingsResponsePacket serverSettingsResponsePacket = new ServerSettingsResponsePacket();
|
ServerSettingsResponsePacket serverSettingsResponsePacket = new ServerSettingsResponsePacket();
|
||||||
serverSettingsResponsePacket.setFormData(session.getSettingsForm().getJSONData());
|
serverSettingsResponsePacket.setFormData(window.getJsonData());
|
||||||
serverSettingsResponsePacket.setFormId(SettingsUtils.SETTINGS_FORM_ID);
|
serverSettingsResponsePacket.setFormId(windowId);
|
||||||
session.sendUpstreamPacket(serverSettingsResponsePacket);
|
session.sendUpstreamPacket(serverSettingsResponsePacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,20 +25,26 @@
|
|||||||
|
|
||||||
package org.geysermc.connector.network.translators.java;
|
package org.geysermc.connector.network.translators.java;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.packet.ingame.client.ClientPluginMessagePacket;
|
||||||
|
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerPluginMessagePacket;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import org.geysermc.common.form.Form;
|
||||||
|
import org.geysermc.common.form.ModalForm;
|
||||||
|
import org.geysermc.common.form.util.FormAdaptor;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
|
import org.geysermc.connector.common.AuthType;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.Translator;
|
import org.geysermc.connector.network.translators.Translator;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.ClientPluginMessagePacket;
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerPluginMessagePacket;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
@Translator(packet = ServerPluginMessagePacket.class)
|
@Translator(packet = ServerPluginMessagePacket.class)
|
||||||
public class JavaPluginMessageTranslator extends PacketTranslator<ServerPluginMessagePacket> {
|
public class JavaPluginMessageTranslator extends PacketTranslator<ServerPluginMessagePacket> {
|
||||||
|
private static final byte[] brandData;
|
||||||
private static byte[] brandData;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
byte[] data = GeyserConnector.NAME.getBytes(StandardCharsets.UTF_8);
|
byte[] data = GeyserConnector.NAME.getBytes(StandardCharsets.UTF_8);
|
||||||
@ -48,21 +54,11 @@ public class JavaPluginMessageTranslator extends PacketTranslator<ServerPluginMe
|
|||||||
System.arraycopy(data, 0, brandData, varInt.length, data.length);
|
System.arraycopy(data, 0, brandData, varInt.length, data.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void translate(ServerPluginMessagePacket packet, GeyserSession session) {
|
|
||||||
if (packet.getChannel().equals("minecraft:brand")) {
|
|
||||||
session.sendDownstreamPacket(
|
|
||||||
new ClientPluginMessagePacket(packet.getChannel(), brandData)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] writeVarInt(int value) {
|
private static byte[] writeVarInt(int value) {
|
||||||
byte[] data = new byte[getVarIntLength(value)];
|
byte[] data = new byte[getVarIntLength(value)];
|
||||||
int index = 0;
|
int index = 0;
|
||||||
do {
|
do {
|
||||||
byte temp = (byte)(value & 0b01111111);
|
byte temp = (byte) (value & 0b01111111);
|
||||||
value >>>= 7;
|
value >>>= 7;
|
||||||
if (value != 0) {
|
if (value != 0) {
|
||||||
temp |= 0b10000000;
|
temp |= 0b10000000;
|
||||||
@ -85,4 +81,48 @@ public class JavaPluginMessageTranslator extends PacketTranslator<ServerPluginMe
|
|||||||
}
|
}
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void translate(ServerPluginMessagePacket packet, GeyserSession session) {
|
||||||
|
String channel = packet.getChannel();
|
||||||
|
|
||||||
|
if (channel.equals("minecraft:brand")) {
|
||||||
|
session.sendDownstreamPacket(
|
||||||
|
new ClientPluginMessagePacket(channel, brandData)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Floodgate plugin messages
|
||||||
|
if (session.getConnector().getAuthType() != AuthType.FLOODGATE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel.equals("floodgate:form")) {
|
||||||
|
byte[] data = packet.getData();
|
||||||
|
|
||||||
|
// receive: first byte is form type, second and third are the id, remaining is the form data
|
||||||
|
// respond: first and second byte id, remaining is form response data
|
||||||
|
|
||||||
|
Form.Type type = Form.Type.getByOrdinal(data[0]);
|
||||||
|
if (type == null) {
|
||||||
|
throw new NullPointerException(
|
||||||
|
"Got type " + data[0] + " which isn't a valid form type!");
|
||||||
|
}
|
||||||
|
|
||||||
|
String dataString = new String(data, 3, data.length - 3, Charsets.UTF_8);
|
||||||
|
|
||||||
|
Form form = new GsonBuilder().registerTypeAdapter(ModalForm.class, new FormAdaptor()).create().fromJson(dataString, type.getTypeClass());
|
||||||
|
form.setResponseHandler(response -> {
|
||||||
|
byte[] raw = response.getBytes(StandardCharsets.UTF_8);
|
||||||
|
byte[] finalData = new byte[raw.length + 2];
|
||||||
|
|
||||||
|
finalData[0] = data[1];
|
||||||
|
finalData[1] = data[2];
|
||||||
|
System.arraycopy(raw, 0, finalData, 2, raw.length);
|
||||||
|
|
||||||
|
session.sendDownstreamPacket(new ClientPluginMessagePacket(channel, finalData));
|
||||||
|
});
|
||||||
|
session.sendForm(form);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,20 +34,16 @@ import com.nukkitx.network.util.Preconditions;
|
|||||||
import com.nukkitx.protocol.bedrock.packet.LoginPacket;
|
import com.nukkitx.protocol.bedrock.packet.LoginPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.ServerToClientHandshakePacket;
|
import com.nukkitx.protocol.bedrock.packet.ServerToClientHandshakePacket;
|
||||||
import com.nukkitx.protocol.bedrock.util.EncryptionUtils;
|
import com.nukkitx.protocol.bedrock.util.EncryptionUtils;
|
||||||
import org.geysermc.common.window.CustomFormBuilder;
|
import org.geysermc.common.form.CustomForm;
|
||||||
import org.geysermc.common.window.CustomFormWindow;
|
import org.geysermc.common.form.ModalForm;
|
||||||
import org.geysermc.common.window.FormWindow;
|
import org.geysermc.common.form.SimpleForm;
|
||||||
import org.geysermc.common.window.SimpleFormWindow;
|
import org.geysermc.common.form.response.CustomFormResponse;
|
||||||
import org.geysermc.common.window.button.FormButton;
|
import org.geysermc.common.form.response.ModalFormResponse;
|
||||||
import org.geysermc.common.window.component.InputComponent;
|
import org.geysermc.common.form.response.SimpleFormResponse;
|
||||||
import org.geysermc.common.window.component.LabelComponent;
|
|
||||||
import org.geysermc.common.window.response.CustomFormResponse;
|
|
||||||
import org.geysermc.common.window.response.SimpleFormResponse;
|
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.session.auth.AuthData;
|
import org.geysermc.connector.network.session.auth.AuthData;
|
||||||
import org.geysermc.connector.network.session.auth.BedrockClientData;
|
import org.geysermc.connector.network.session.auth.BedrockClientData;
|
||||||
import org.geysermc.connector.network.session.cache.WindowCache;
|
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -159,69 +155,49 @@ public class LoginEncryptionUtils {
|
|||||||
session.sendUpstreamPacketImmediately(packet);
|
session.sendUpstreamPacketImmediately(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int AUTH_FORM_ID = 1336;
|
public static void buildAndShowLoginWindow(GeyserSession session) {
|
||||||
private static int AUTH_DETAILS_FORM_ID = 1337;
|
|
||||||
|
|
||||||
public static void showLoginWindow(GeyserSession session) {
|
|
||||||
String userLanguage = session.getClientData().getLanguageCode();
|
String userLanguage = session.getClientData().getLanguageCode();
|
||||||
SimpleFormWindow window = new SimpleFormWindow(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.notice.title", userLanguage), LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.notice.desc", userLanguage));
|
|
||||||
window.getButtons().add(new FormButton(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.notice.btn_login", userLanguage)));
|
|
||||||
window.getButtons().add(new FormButton(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.notice.btn_disconnect", userLanguage)));
|
|
||||||
|
|
||||||
session.sendForm(window, AUTH_FORM_ID);
|
session.sendForm(
|
||||||
|
SimpleForm.builder()
|
||||||
|
.translator(LanguageUtils::getPlayerLocaleString, userLanguage)
|
||||||
|
.title("geyser.auth.login.form.notice.title")
|
||||||
|
.content("geyser.auth.login.form.notice.desc")
|
||||||
|
.button("geyser.auth.login.form.notice.btn_login") // id = 0
|
||||||
|
.button("geyser.auth.login.form.notice.btn_disconnect")
|
||||||
|
.responseHandler((form, responseData) -> {
|
||||||
|
SimpleFormResponse response = form.parseResponse(responseData.trim());
|
||||||
|
if (!response.isCorrect()) {
|
||||||
|
buildAndShowLoginWindow(session);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showLoginDetailsWindow(GeyserSession session) {
|
|
||||||
String userLanguage = session.getClientData().getLanguageCode();
|
|
||||||
CustomFormWindow window = new CustomFormBuilder(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.details.title", userLanguage))
|
|
||||||
.addComponent(new LabelComponent(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.details.desc", userLanguage)))
|
|
||||||
.addComponent(new InputComponent(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.details.email", userLanguage), "account@geysermc.org", ""))
|
|
||||||
.addComponent(new InputComponent(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.details.pass", userLanguage), "123456", ""))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
session.sendForm(window, AUTH_DETAILS_FORM_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean authenticateFromForm(GeyserSession session, GeyserConnector connector, int formId, String formData) {
|
|
||||||
WindowCache windowCache = session.getWindowCache();
|
|
||||||
if (!windowCache.getWindows().containsKey(formId))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(formId == AUTH_FORM_ID || formId == AUTH_DETAILS_FORM_ID) {
|
|
||||||
FormWindow window = windowCache.getWindows().remove(formId);
|
|
||||||
window.setResponse(formData.trim());
|
|
||||||
|
|
||||||
if (!session.isLoggedIn()) {
|
|
||||||
if (formId == AUTH_DETAILS_FORM_ID && window instanceof CustomFormWindow) {
|
|
||||||
CustomFormWindow customFormWindow = (CustomFormWindow) window;
|
|
||||||
|
|
||||||
CustomFormResponse response = (CustomFormResponse) customFormWindow.getResponse();
|
|
||||||
if (response != null) {
|
|
||||||
String email = response.getInputResponses().get(1);
|
|
||||||
String password = response.getInputResponses().get(2);
|
|
||||||
|
|
||||||
session.authenticate(email, password);
|
|
||||||
} else {
|
|
||||||
showLoginDetailsWindow(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear windows so authentication data isn't accidentally cached
|
|
||||||
windowCache.getWindows().clear();
|
|
||||||
} else if (formId == AUTH_FORM_ID && window instanceof SimpleFormWindow) {
|
|
||||||
SimpleFormResponse response = (SimpleFormResponse) window.getResponse();
|
|
||||||
if (response != null) {
|
|
||||||
if (response.getClickedButtonId() == 0) {
|
if (response.getClickedButtonId() == 0) {
|
||||||
showLoginDetailsWindow(session);
|
buildAndShowLoginDetailsWindow(session);
|
||||||
} else if(response.getClickedButtonId() == 1) {
|
return;
|
||||||
session.disconnect(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.disconnect", session.getClientData().getLanguageCode()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showLoginWindow(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session.disconnect(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.disconnect", session.getClientData().getLanguageCode()));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void buildAndShowLoginDetailsWindow(GeyserSession session) {
|
||||||
|
String userLanguage = session.getClientData().getLanguageCode();
|
||||||
|
session.sendForm(
|
||||||
|
CustomForm.builder()
|
||||||
|
.translator(LanguageUtils::getPlayerLocaleString, userLanguage)
|
||||||
|
.title("geyser.auth.login.form.details.title")
|
||||||
|
.label("geyser.auth.login.form.details.desc")
|
||||||
|
.input("geyser.auth.login.form.details.email", "account@geysermc.org", "")
|
||||||
|
.input("geyser.auth.login.form.details.pass", "123456", "")
|
||||||
|
.responseHandler((form, responseData) -> {
|
||||||
|
CustomFormResponse response = form.parseResponse(responseData.trim());
|
||||||
|
if (!response.isCorrect()) {
|
||||||
|
buildAndShowLoginDetailsWindow(session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
session.authenticate(response.next(), response.next());
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,62 +27,53 @@ package org.geysermc.connector.utils;
|
|||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||||
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
|
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
|
||||||
import org.geysermc.common.window.CustomFormBuilder;
|
import org.geysermc.common.form.CustomForm;
|
||||||
import org.geysermc.common.window.CustomFormWindow;
|
import org.geysermc.common.form.component.DropdownComponent;
|
||||||
import org.geysermc.common.window.button.FormImage;
|
import org.geysermc.common.form.response.CustomFormResponse;
|
||||||
import org.geysermc.common.window.component.DropdownComponent;
|
|
||||||
import org.geysermc.common.window.component.InputComponent;
|
|
||||||
import org.geysermc.common.window.component.LabelComponent;
|
|
||||||
import org.geysermc.common.window.component.ToggleComponent;
|
|
||||||
import org.geysermc.common.window.response.CustomFormResponse;
|
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.world.WorldManager;
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class SettingsUtils {
|
public class SettingsUtils {
|
||||||
|
|
||||||
// Used in UpstreamPacketHandler.java
|
|
||||||
public static final int SETTINGS_FORM_ID = 1338;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a settings form for the given session and store it for later
|
* Build a settings form for the given session and store it for later
|
||||||
*
|
*
|
||||||
* @param session The session to build the form for
|
* @param session The session to build the form for
|
||||||
*/
|
*/
|
||||||
public static void buildForm(GeyserSession session) {
|
public static CustomForm buildForm(GeyserSession session) {
|
||||||
// Cache the language for cleaner access
|
// Cache the language for cleaner access
|
||||||
String language = session.getClientData().getLanguageCode();
|
String language = session.getClientData().getLanguageCode();
|
||||||
|
|
||||||
CustomFormBuilder builder = new CustomFormBuilder(LanguageUtils.getPlayerLocaleString("geyser.settings.title.main", language));
|
CustomForm.Builder builder = CustomForm.builder()
|
||||||
builder.setIcon(new FormImage(FormImage.FormImageType.PATH, "textures/ui/settings_glyph_color_2x.png"));
|
.translator(LanguageUtils::getPlayerLocaleString, language)
|
||||||
|
.title("geyser.settings.title.main")
|
||||||
builder.addComponent(new LabelComponent(LanguageUtils.getPlayerLocaleString("geyser.settings.title.client", language)));
|
.iconPath("textures/ui/settings_glyph_color_2x.png")
|
||||||
builder.addComponent(new ToggleComponent(LanguageUtils.getPlayerLocaleString("geyser.settings.option.coordinates", language, session.getWorldCache().isShowCoordinates())));
|
.label("geyser.settings.title.client")
|
||||||
|
.toggle("geyser.settings.option.coordinates");
|
||||||
|
|
||||||
|
|
||||||
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
||||||
builder.addComponent(new LabelComponent(LanguageUtils.getPlayerLocaleString("geyser.settings.title.server", language)));
|
builder.label("geyser.settings.title.server");
|
||||||
|
|
||||||
DropdownComponent gamemodeDropdown = new DropdownComponent();
|
DropdownComponent.Builder gamemodeDropdown = DropdownComponent.builder("%createWorldScreen.gameMode.personal");
|
||||||
gamemodeDropdown.setText("%createWorldScreen.gameMode.personal");
|
|
||||||
gamemodeDropdown.setOptions(new ArrayList<>());
|
|
||||||
for (GameMode gamemode : GameMode.values()) {
|
for (GameMode gamemode : GameMode.values()) {
|
||||||
gamemodeDropdown.addOption(LocaleUtils.getLocaleString("selectWorld.gameMode." + gamemode.name().toLowerCase(), language), session.getGameMode() == gamemode);
|
gamemodeDropdown.option("selectWorld.gameMode." + gamemode.name().toLowerCase(), session.getGameMode() == gamemode);
|
||||||
}
|
}
|
||||||
builder.addComponent(gamemodeDropdown);
|
builder.dropdown(gamemodeDropdown);
|
||||||
|
|
||||||
DropdownComponent difficultyDropdown = new DropdownComponent();
|
DropdownComponent.Builder difficultyDropdown = DropdownComponent.builder("%options.difficulty");
|
||||||
difficultyDropdown.setText("%options.difficulty");
|
|
||||||
difficultyDropdown.setOptions(new ArrayList<>());
|
|
||||||
for (Difficulty difficulty : Difficulty.values()) {
|
for (Difficulty difficulty : Difficulty.values()) {
|
||||||
difficultyDropdown.addOption("%options.difficulty." + difficulty.name().toLowerCase(), session.getWorldCache().getDifficulty() == difficulty);
|
difficultyDropdown.option("%options.difficulty." + difficulty.name().toLowerCase(), session.getWorldCache().getDifficulty() == difficulty);
|
||||||
}
|
}
|
||||||
builder.addComponent(difficultyDropdown);
|
builder.dropdown(difficultyDropdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.gamerules")) {
|
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.gamerules")) {
|
||||||
builder.addComponent(new LabelComponent(LanguageUtils.getPlayerLocaleString("geyser.settings.title.game_rules", language)));
|
builder.label("geyser.settings.title.game_rules")
|
||||||
|
.translator(LocaleUtils::getLocaleString); // we need translate gamerules next
|
||||||
|
|
||||||
|
WorldManager worldManager = GeyserConnector.getInstance().getWorldManager();
|
||||||
for (GameRule gamerule : GameRule.values()) {
|
for (GameRule gamerule : GameRule.values()) {
|
||||||
if (gamerule.equals(GameRule.UNKNOWN)) {
|
if (gamerule.equals(GameRule.UNKNOWN)) {
|
||||||
continue;
|
continue;
|
||||||
@ -90,74 +81,54 @@ public class SettingsUtils {
|
|||||||
|
|
||||||
// Add the relevant form item based on the gamerule type
|
// Add the relevant form item based on the gamerule type
|
||||||
if (Boolean.class.equals(gamerule.getType())) {
|
if (Boolean.class.equals(gamerule.getType())) {
|
||||||
builder.addComponent(new ToggleComponent(LocaleUtils.getLocaleString("gamerule." + gamerule.getJavaID(), language), GeyserConnector.getInstance().getWorldManager().getGameRuleBool(session, gamerule)));
|
builder.toggle("gamerule." + gamerule.getJavaID(), worldManager.getGameRuleBool(session, gamerule));
|
||||||
} else if (Integer.class.equals(gamerule.getType())) {
|
} else if (Integer.class.equals(gamerule.getType())) {
|
||||||
builder.addComponent(new InputComponent(LocaleUtils.getLocaleString("gamerule." + gamerule.getJavaID(), language), "", String.valueOf(GeyserConnector.getInstance().getWorldManager().getGameRuleInt(session, gamerule))));
|
builder.input("gamerule." + gamerule.getJavaID(), "", String.valueOf(worldManager.getGameRuleInt(session, gamerule)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
session.setSettingsForm(builder.build());
|
builder.responseHandler((form, responseData) -> {
|
||||||
|
CustomFormResponse response = form.parseResponseAs(responseData);
|
||||||
|
if (response.isClosed() || response.isInvalid()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
session.getWorldCache().setShowCoordinates(response.next());
|
||||||
* Handle the settings form response
|
|
||||||
*
|
|
||||||
* @param session The session that sent the response
|
|
||||||
* @param response The response string to parse
|
|
||||||
* @return True if the form was parsed correctly, false if not
|
|
||||||
*/
|
|
||||||
public static boolean handleSettingsForm(GeyserSession session, String response) {
|
|
||||||
CustomFormWindow settingsForm = session.getSettingsForm();
|
|
||||||
settingsForm.setResponse(response);
|
|
||||||
|
|
||||||
CustomFormResponse settingsResponse = (CustomFormResponse) settingsForm.getResponse();
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
offset++; // Client settings title
|
|
||||||
|
|
||||||
session.getWorldCache().setShowCoordinates(settingsResponse.getToggleResponses().get(offset));
|
|
||||||
offset++;
|
|
||||||
|
|
||||||
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
||||||
offset++; // Server settings title
|
GameMode gameMode = GameMode.values()[(int) response.next()];
|
||||||
|
|
||||||
GameMode gameMode = GameMode.values()[settingsResponse.getDropdownResponses().get(offset).getElementID()];
|
|
||||||
if (gameMode != null && gameMode != session.getGameMode()) {
|
if (gameMode != null && gameMode != session.getGameMode()) {
|
||||||
session.getConnector().getWorldManager().setPlayerGameMode(session, gameMode);
|
session.getConnector().getWorldManager().setPlayerGameMode(session, gameMode);
|
||||||
}
|
}
|
||||||
offset++;
|
|
||||||
|
|
||||||
Difficulty difficulty = Difficulty.values()[settingsResponse.getDropdownResponses().get(offset).getElementID()];
|
Difficulty difficulty = Difficulty.values()[(int) response.next()];
|
||||||
if (difficulty != null && difficulty != session.getWorldCache().getDifficulty()) {
|
if (difficulty != null && difficulty != session.getWorldCache().getDifficulty()) {
|
||||||
session.getConnector().getWorldManager().setDifficulty(session, difficulty);
|
session.getConnector().getWorldManager().setDifficulty(session, difficulty);
|
||||||
}
|
}
|
||||||
offset++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.gamerules")) {
|
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.gamerules")) {
|
||||||
offset++; // Game rule title
|
|
||||||
|
|
||||||
for (GameRule gamerule : GameRule.values()) {
|
for (GameRule gamerule : GameRule.values()) {
|
||||||
if (gamerule.equals(GameRule.UNKNOWN)) {
|
if (gamerule.equals(GameRule.UNKNOWN)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Boolean.class.equals(gamerule.getType())) {
|
if (Boolean.class.equals(gamerule.getType())) {
|
||||||
Boolean value = settingsResponse.getToggleResponses().get(offset).booleanValue();
|
boolean value = response.next();
|
||||||
if (value != session.getConnector().getWorldManager().getGameRuleBool(session, gamerule)) {
|
if (value != session.getConnector().getWorldManager().getGameRuleBool(session, gamerule)) {
|
||||||
session.getConnector().getWorldManager().setGameRule(session, gamerule.getJavaID(), value);
|
session.getConnector().getWorldManager().setGameRule(session, gamerule.getJavaID(), value);
|
||||||
}
|
}
|
||||||
} else if (Integer.class.equals(gamerule.getType())) {
|
} else if (Integer.class.equals(gamerule.getType())) {
|
||||||
int value = Integer.parseInt(settingsResponse.getInputResponses().get(offset));
|
int value = Integer.parseInt(response.next());
|
||||||
if (value != session.getConnector().getWorldManager().getGameRuleInt(session, gamerule)) {
|
if (value != session.getConnector().getWorldManager().getGameRuleInt(session, gamerule)) {
|
||||||
session.getConnector().getWorldManager().setGameRule(session, gamerule.getJavaID(), value);
|
session.getConnector().getWorldManager().setGameRule(session, gamerule.getJavaID(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
offset++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return builder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren