Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Commit

Permalink
[0.3.2] RadioSettings, Fixed Hmc command
Browse files Browse the repository at this point in the history
  • Loading branch information
3arthqu4ke committed Mar 29, 2024
1 parent 2c5aef0 commit af4ab94
Show file tree
Hide file tree
Showing 10 changed files with 253 additions and 8 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
org.gradle.jvmargs = -Xmx2G

version = 0.3.1
version = 0.3.2
minecraft_version = 1.20.4
mapping_version = 1
neoforge_version = 1-beta
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package me.earth.pingbypass.api.command.impl.arguments;

import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import me.earth.pingbypass.api.traits.HasDescription;
import me.earth.pingbypass.api.traits.Nameable;
import me.earth.pingbypass.api.traits.Streamable;

import java.util.concurrent.CompletableFuture;

public class DescriptionArgumentTypeImpl<T extends Nameable & HasDescription> extends NameableArgumentTypeImpl<T> implements DescriptionArgumentType<T> {
public DescriptionArgumentTypeImpl(Streamable<T> nameables, String type) {
super(nameables, type);
}

@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return DescriptionArgumentType.super.listSuggestions(context, builder);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

@Getter
public class NameableArgumentTypeImpl<T extends Nameable> implements NameableArgumentType<T> {
private static final NameableArgumentTypeImpl<?> EMPTY = new NameableArgumentTypeImpl<>(Streamable.empty(), "empty");
private final Streamable<T> nameables;
private final String type;

Expand All @@ -28,4 +29,9 @@ public static <V extends Nameable> ExtendedRequiredArgumentBuilder<CommandSource
return new ExtendedRequiredArgumentBuilder<>(of(name, args), name);
}

@SuppressWarnings("unchecked")
public static <V extends Nameable> NameableArgumentType<V> empty() {
return (NameableArgumentType<V>) EMPTY;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
import com.google.gson.JsonPrimitive;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.experimental.Delegate;
import me.earth.pingbypass.api.config.ConfigParseException;
import me.earth.pingbypass.api.config.JsonDeserializationFunction;
import me.earth.pingbypass.api.config.JsonParser;
import me.earth.pingbypass.api.config.JsonSerializationFunction;
import me.earth.pingbypass.api.input.Bind;
import me.earth.pingbypass.api.registry.Registry;
import me.earth.pingbypass.api.setting.impl.types.container.Container;
import me.earth.pingbypass.api.traits.Nameable;
import me.earth.pingbypass.api.traits.NameableImpl;
Expand All @@ -19,6 +22,8 @@

@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class Parsers<T> implements JsonParser<T> {
private static final JsonParser<?> DUMMY = new Parsers<>(e -> { throw new RuntimeException("dummy"); }, v -> { throw new RuntimeException("dummy"); });

public static final JsonParser<Container<Nameable>> CONTAINER = new Parsers<>(e -> Container.fromJson(e, Parsers.NAME), Container::toJson);
public static final JsonParser<Boolean> BOOL = new Parsers<>(JsonElement::getAsBoolean, JsonPrimitive::new);
public static final JsonParser<String> STRING = new Parsers<>(JsonElement::getAsString, JsonPrimitive::new);
Expand Down Expand Up @@ -54,4 +59,27 @@ public static <T, C extends Collection<T>> JsonParser<C> collection(JsonParser<T
});
}

public static <T extends Nameable> JsonParser<T> registry(Registry<T> registry) {
return new JsonParser<>() {
@Override
@SneakyThrows
public T deserialize(JsonElement element) {
return registry
.getByName(element.getAsString())
.orElseThrow(() -> new ConfigParseException("Failed to find " + element.getAsString() + " on registry " + registry));
}

@Override
@SneakyThrows
public JsonElement serialize(T element) {
return new JsonPrimitive(element.getName());
}
};
}

@SuppressWarnings("unchecked")
public static <T> JsonParser<T> dummy() {
return (JsonParser<T>) DUMMY;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ public abstract class AbstractSettingBuilder<T, S extends Setting<T>, B extends
private String description;
private T defaultValue;
private String name;
private T value;

protected abstract S create();

Expand Down Expand Up @@ -83,7 +82,6 @@ public B withDescription(String description) {

public B withValue(T value) {
this.defaultValue = value;
this.value = value;
return getSelf();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package me.earth.pingbypass.api.setting.impl.types;

import com.mojang.brigadier.arguments.ArgumentType;
import lombok.Getter;
import me.earth.pingbypass.api.config.ConfigType;
import me.earth.pingbypass.api.config.JsonParser;
import me.earth.pingbypass.api.registry.Registry;
import me.earth.pingbypass.api.registry.impl.OrderedRegistryImpl;
import me.earth.pingbypass.api.setting.Complexity;
import me.earth.pingbypass.api.setting.impl.SettingImpl;
import me.earth.pingbypass.api.traits.CanBeVisible;
import me.earth.pingbypass.api.traits.Nameable;
import net.minecraft.network.chat.Component;

import java.util.LinkedHashSet;
import java.util.function.Function;

/**
* Similar to an {@link EnumSetting}, but allows values of any type, not only Enums and thus also supports adding values later.
*
* @param <T> the type of object handled by this setting.
*/
public class RadioSetting<T extends Nameable> extends SettingImpl<T> {
@Getter
private final Registry<T> values;
private final Class<T> type;

public RadioSetting(Function<T, Component> componentFactory, CanBeVisible visibility, Complexity complexity,
ConfigType configType, String description, T defaultValue, String name, Class<T> type, LinkedHashSet<T> values,
Function<Registry<T>, ArgumentType<T>> argumentType, Function<Registry<T>, JsonParser<T>> parser) {
this(new OrderedRegistryImpl<>(), componentFactory, visibility, complexity, configType, description, defaultValue, name, type, values, argumentType, parser);
}

private RadioSetting(Registry<T> registry, Function<T, Component> componentFactory, CanBeVisible visibility, Complexity complexity,
ConfigType configType, String description, T defaultValue, String name, Class<T> type, LinkedHashSet<T> values,
Function<Registry<T>, ArgumentType<T>> argumentType, Function<Registry<T>, JsonParser<T>> parser) {
super(componentFactory, visibility, argumentType.apply(registry), complexity, parser.apply(registry), configType, description, defaultValue, name);
this.type = type;
this.values = registry;
values.forEach(this.values::register);
}

@Override
public Class<T> getType() {
return type;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package me.earth.pingbypass.api.setting.impl.types;

import com.mojang.brigadier.arguments.ArgumentType;
import me.earth.pingbypass.api.command.impl.arguments.DescriptionArgumentTypeImpl;
import me.earth.pingbypass.api.command.impl.arguments.NameableArgumentTypeImpl;
import me.earth.pingbypass.api.config.JsonParser;
import me.earth.pingbypass.api.config.impl.Parsers;
import me.earth.pingbypass.api.registry.Registry;
import me.earth.pingbypass.api.setting.impl.AbstractSettingBuilder;
import me.earth.pingbypass.api.traits.HasDescription;
import me.earth.pingbypass.api.traits.Nameable;

import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.function.Function;

public final class RadioSettingBuilder<T extends Nameable> extends AbstractSettingBuilder<T, RadioSetting<T>, RadioSettingBuilder<T>> {
private final Class<T> type;

private Function<Registry<T>, ArgumentType<T>> argumentTypeFactory;
private Function<Registry<T>, JsonParser<T>> parserFactory;
private LinkedHashSet<T> values = new LinkedHashSet<>();

@SuppressWarnings({"rawtypes", "unchecked"})
public RadioSettingBuilder(Class<T> type) {
this.type = type;
withArgumentTypeFactory(registry -> HasDescription.class.isAssignableFrom(type)
? (ArgumentType<T>) new DescriptionArgumentTypeImpl(registry, "value")
: new NameableArgumentTypeImpl<>(registry, "value"))
.withParserFactory(Parsers::registry)
.withArgumentType(NameableArgumentTypeImpl.empty()) // just to make .verify happy
.withParser(Parsers.dummy()); // just to make .verify happy
}

public RadioSettingBuilder<T> withArgumentTypeFactory(Function<Registry<T>, ArgumentType<T>> argumentTypeFactory) {
this.argumentTypeFactory = argumentTypeFactory;
return getSelf();
}

public RadioSettingBuilder<T> withParserFactory(Function<Registry<T>, JsonParser<T>> parserFactory) {
this.parserFactory = parserFactory;
return getSelf();
}

@SafeVarargs
public final RadioSettingBuilder<T> withValues(T... values) {
this.values = new LinkedHashSet<>();
this.values.addAll(Arrays.asList(values));
if (getDefaultValue() == null) {
if (values.length > 0) {
super.withValue(values[0]);
}
} else {
this.values.add(getDefaultValue());
}

return getSelf();
}

@Override
protected RadioSetting<T> create() {
return new RadioSetting<>(getComponentFactory(), getVisibility(), getComplexity(), getConfigType(), getDescription(),
getDefaultValue(), getName(), type, values, argumentTypeFactory, parserFactory);
}

@Override
public RadioSettingBuilder<T> withValue(T value) {
values.add(value);
return super.withValue(value);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import me.earth.pingbypass.api.setting.Setting;
import me.earth.pingbypass.api.setting.SettingRegistry;
import me.earth.pingbypass.api.traits.Nameable;

public interface RegistersSettingTypes extends SettingRegistry {
default BoolBuilder boolBuilder(String name, boolean value) {
Expand Down Expand Up @@ -49,7 +50,17 @@ default <T extends Enum<T>> Setting<T> constant(String name, T value, String des
}

default <T extends Enum<T>> EnumBuilder<T> enumBuilder(String name, T value) {
return new EnumBuilder<T>(value).withName(name);
return new EnumBuilder<>(value).withName(name);
}

@SuppressWarnings("unchecked")
default <T extends Nameable> RadioSetting<T> radio(String name, Class<T> type, String description, T... values) {
return radioBuilder(name, type, description, values).registerOnBuild(this).build();
}

@SuppressWarnings("unchecked")
default <T extends Nameable> RadioSettingBuilder<T> radioBuilder(String name, Class<T> type, String description, T... values) {
return new RadioSettingBuilder<>(type).withName(name).withDescription(description).withValues(values);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package me.earth.pingbypass.api.setting.settings;

import com.google.gson.JsonPrimitive;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.earth.pingbypass.api.config.ConfigParseException;
import me.earth.pingbypass.api.setting.impl.SettingRegistryImpl;
import me.earth.pingbypass.api.setting.impl.types.RegistersSettingTypes;
import me.earth.pingbypass.api.traits.Nameable;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

public class RadioSettingTest {
@Test
public void testCreate() throws CommandSyntaxException {
var settingRegistry = new SettingRegistryRegisteringSettings();
var builder = settingRegistry.radioBuilder("Test", NameableValue.class, "TestDescription", NameableValue.VALUE_1, NameableValue.VALUE_3);
var radioSetting = builder.build();
assertEquals("Test", radioSetting.getName());
assertEquals(NameableValue.class, radioSetting.getType());
assertEquals("TestDescription", radioSetting.getDescription());
assertEquals(NameableValue.VALUE_1, radioSetting.getDefaultValue());
assertEquals(NameableValue.VALUE_1, radioSetting.getValue());
assertTrue(radioSetting.getValues().contains("1"));
assertFalse(radioSetting.getValues().contains("2"));
assertTrue(radioSetting.getValues().contains("3"));
radioSetting.fromJson(new JsonPrimitive("3"));
assertEquals(NameableValue.VALUE_3, radioSetting.getValue());
assertThrows(ConfigParseException.class, () -> radioSetting.fromJson(new JsonPrimitive("2")));
radioSetting.getValues().register(NameableValue.VALUE_2);
radioSetting.fromJson(new JsonPrimitive("2"));
assertEquals(NameableValue.VALUE_2, radioSetting.getValue());
assertEquals(NameableValue.VALUE_2, radioSetting.getArgumentType().parse(new StringReader("2")));
}

@Getter
@RequiredArgsConstructor
private enum NameableValue implements Nameable {
VALUE_1("1"),
VALUE_2("2"),
VALUE_3("3");

private final String name;
}

private static final class SettingRegistryRegisteringSettings extends SettingRegistryImpl implements RegistersSettingTypes {

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
import me.earth.pingbypass.api.command.CommandManager;
import me.earth.pingbypass.api.command.DelegatingCommandSource;
import me.earth.pingbypass.server.PingBypassServer;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.ComponentUtils;
import net.minecraft.network.chat.Component;

// TODO: I do not think this works properly!
// TODO: proper API for adding stuff to HMC!
public class HmcPbCommand extends AbstractCommand {
public HmcPbCommand(HeadlessMc ctx) {
Expand All @@ -21,11 +21,18 @@ public HmcPbCommand(HeadlessMc ctx) {
public void execute(String... args) {
// this is kinda eh
PingBypassApi.instances().filter(pb -> pb instanceof PingBypassServer).findFirst().ifPresent(server -> {
if (args.length <= 1) {
Minecraft.getInstance().gui.getChat().addMessage(Component.literal("Please specify a PingBypass command!").withStyle(ChatFormatting.RED));
return;
}
// takeout the "pingbypass" at the start of the args
String[] pbArgs = new String[args.length - 1];
System.arraycopy(args, 1, pbArgs, 0, args.length - 1);
CommandManager cm = server.getCommandManager();
try {
cm.execute(String.join(" ", args), new DelegatingCommandSource(Minecraft.getInstance(), server));
cm.execute(String.join(" ", pbArgs), new DelegatingCommandSource(Minecraft.getInstance(), server));
} catch (CommandSyntaxException e) {
Minecraft.getInstance().gui.getChat().addMessage(ComponentUtils.fromMessage(e.getRawMessage()));
Minecraft.getInstance().gui.getChat().addMessage(Component.literal(e.getMessage()).withStyle(ChatFormatting.RED));
}
});
}
Expand Down

0 comments on commit af4ab94

Please sign in to comment.