diff --git a/src/main/java/io/github/skippyall/minions/MinionRegistries.java b/src/main/java/io/github/skippyall/minions/MinionRegistries.java index 866246b..9ff4631 100644 --- a/src/main/java/io/github/skippyall/minions/MinionRegistries.java +++ b/src/main/java/io/github/skippyall/minions/MinionRegistries.java @@ -1,6 +1,8 @@ package io.github.skippyall.minions; import com.mojang.serialization.Lifecycle; +import io.github.skippyall.minions.minion.MinionRuntime; +import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.skin.SkinProvider; import io.github.skippyall.minions.program.argument.GenericArgumentType; import io.github.skippyall.minions.program.instruction.InstructionType; @@ -12,7 +14,7 @@ import net.minecraft.util.Identifier; public class MinionRegistries { public static final Registry> VALUE_TYPES = registry("value_type"); - public static final Registry GENERIC_ARGUMENT_TYPE_REGISTRY = registry("generic_argument_type"); + public static final Registry> GENERIC_ARGUMENT_TYPE_REGISTRY = registry("generic_argument_type"); public static final Registry> INSTRUCTION_TYPES = registry("instruction_type"); public static final Registry SKIN_PROVIDERS = registry("skin_providers"); diff --git a/src/main/java/io/github/skippyall/minions/gui/InstructionGui.java b/src/main/java/io/github/skippyall/minions/gui/InstructionGui.java index 6de99a2..e575427 100644 --- a/src/main/java/io/github/skippyall/minions/gui/InstructionGui.java +++ b/src/main/java/io/github/skippyall/minions/gui/InstructionGui.java @@ -112,7 +112,7 @@ public class InstructionGui { } } - public static >> void configureArgumentMenu(String name, ConfiguredInstruction instruction, Parameter parameter, MinionFakePlayer minion, ServerPlayerEntity player) { + public static , MinionFakePlayer>> void configureArgumentMenu(String name, ConfiguredInstruction instruction, Parameter parameter, MinionFakePlayer minion, ServerPlayerEntity player) { if(!checkInstructionExists(name, instruction, minion, player)) { return; } diff --git a/src/main/java/io/github/skippyall/minions/minion/MinionRuntime.java b/src/main/java/io/github/skippyall/minions/minion/MinionRuntime.java new file mode 100644 index 0000000..70999d2 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/minion/MinionRuntime.java @@ -0,0 +1,14 @@ +package io.github.skippyall.minions.minion; + +import io.github.skippyall.minions.MinionRegistries; +import io.github.skippyall.minions.program.InstructionRuntime; +import io.github.skippyall.minions.program.argument.GenericArgumentType; +import net.minecraft.registry.Registry; + +public class MinionRuntime implements InstructionRuntime { + + @Override + public Registry> getGenericArgumentTypeRegistry() { + return MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY; + } +} diff --git a/src/main/java/io/github/skippyall/minions/program/InstructionRuntime.java b/src/main/java/io/github/skippyall/minions/program/InstructionRuntime.java new file mode 100644 index 0000000..ff51bf7 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/program/InstructionRuntime.java @@ -0,0 +1,29 @@ +package io.github.skippyall.minions.program; + +import com.mojang.serialization.Codec; +import io.github.skippyall.minions.program.argument.Argument; +import io.github.skippyall.minions.program.argument.ArgumentList; +import io.github.skippyall.minions.program.argument.Arguments; +import io.github.skippyall.minions.program.argument.GenericArgumentType; +import io.github.skippyall.minions.program.argument.SpecificArgumentType; +import net.minecraft.registry.Registry; + +public interface InstructionRuntime> { + Registry> getGenericArgumentTypeRegistry(); + + default Codec> getGenericArgumentTypeCodec() { + return getGenericArgumentTypeRegistry().getCodec(); + } + + default Codec> getSpecificArgumentTypeCodec() { + return Arguments.createSpecificTypeCodec(getGenericArgumentTypeCodec()); + } + + default Codec> getArgumentCodec() { + return Arguments.createArgumentCodec(getGenericArgumentTypeCodec()); + } + + default Codec> getArgumentListCodec() { + return ArgumentList.getCodec(getGenericArgumentTypeCodec()); + } +} diff --git a/src/main/java/io/github/skippyall/minions/program/argument/Argument.java b/src/main/java/io/github/skippyall/minions/program/argument/Argument.java index 54ef08a..7adfe7a 100644 --- a/src/main/java/io/github/skippyall/minions/program/argument/Argument.java +++ b/src/main/java/io/github/skippyall/minions/program/argument/Argument.java @@ -1,7 +1,7 @@ package io.github.skippyall.minions.program.argument; import io.github.skippyall.minions.gui.GuiDisplay; -import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.program.InstructionRuntime; import io.github.skippyall.minions.program.value.ValueType; import org.jetbrains.annotations.Nullable; @@ -12,8 +12,8 @@ import org.jetbrains.annotations.Nullable; * @param The type of the Argument's value * @param The SpecificArgumentType */ -public interface Argument>> { - T resolve(MinionFakePlayer minion); +public interface Argument, R>, R extends InstructionRuntime> { + T resolve(R minion); default ValueType getValueType() { return getType().getValueType(); @@ -23,7 +23,7 @@ public interface Argument>> @Nullable A cast(ValueType type) { + default , R>> @Nullable A cast(ValueType type) { if(getValueType() == type) { //noinspection unchecked return (A) this; diff --git a/src/main/java/io/github/skippyall/minions/program/argument/ArgumentList.java b/src/main/java/io/github/skippyall/minions/program/argument/ArgumentList.java index 75d2abf..9c71411 100644 --- a/src/main/java/io/github/skippyall/minions/program/argument/ArgumentList.java +++ b/src/main/java/io/github/skippyall/minions/program/argument/ArgumentList.java @@ -1,37 +1,36 @@ package io.github.skippyall.minions.program.argument; import com.mojang.serialization.Codec; +import io.github.skippyall.minions.Minions; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.program.InstructionRuntime; import java.util.Collection; import java.util.HashMap; import java.util.Map; -public class ArgumentList { - public static final Codec CODEC = Codec.unboundedMap(Codec.STRING, Arguments.ARGUMENT_CODEC) - .xmap(ArgumentList::new, list -> list.arguments); - - private final Map> arguments; +public class ArgumentList> { + private final Map> arguments; public ArgumentList() { arguments = new HashMap<>(); } - public ArgumentList(Map> arguments) { + public ArgumentList(Map> arguments) { this.arguments = new HashMap<>(arguments); } - public T getValue(Parameter parameter, MinionFakePlayer minion) { - Argument argument = getArgument(parameter); - return argument != null ? argument.resolve(minion) : null; + public T getValue(Parameter parameter, R runtime) { + Argument argument = getArgument(parameter); + return argument != null ? argument.resolve(runtime) : null; } - public >> A getArgument(Parameter parameter) { - Argument argument = arguments.get(parameter.name()); + public ,R>> A getArgument(Parameter parameter) { + Argument argument = arguments.get(parameter.name()); return argument == null ? null : argument.cast(parameter.type()); } - public void setArgument(Parameter parameter, Argument argument) { + public void setArgument(Parameter parameter, Argument argument) { arguments.put(parameter.name(), argument); } @@ -47,4 +46,9 @@ public class ArgumentList { } return true; } + + public static > Codec> getCodec(Codec> genericCodec) { + return Codec.unboundedMap(Codec.STRING, Arguments.createArgumentCodec(genericCodec)) + .xmap(ArgumentList::new, list -> list.arguments); + } } diff --git a/src/main/java/io/github/skippyall/minions/program/argument/Arguments.java b/src/main/java/io/github/skippyall/minions/program/argument/Arguments.java index 946159b..18728af 100644 --- a/src/main/java/io/github/skippyall/minions/program/argument/Arguments.java +++ b/src/main/java/io/github/skippyall/minions/program/argument/Arguments.java @@ -3,34 +3,48 @@ package io.github.skippyall.minions.program.argument; import com.mojang.serialization.Codec; import io.github.skippyall.minions.MinionRegistries; import io.github.skippyall.minions.Minions; +import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.program.InstructionRuntime; +import io.github.skippyall.minions.program.value.ValueType; import net.minecraft.registry.Registry; import net.minecraft.util.Identifier; public class Arguments { - public static final Codec> SPECIFIC_ARGUMENT_TYPE_CODEC = MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY.getCodec().dispatch( - "type", - SpecificArgumentType::getGenericArgumentType, - generic -> - MinionRegistries.VALUE_TYPES.getCodec().xmap( - generic::createTypeSpecific, - SpecificArgumentType::getValueType - ).fieldOf("valueType") - ); + public static final Codec> SPECIFIC_ARGUMENT_TYPE_CODEC = createSpecificTypeCodec(MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY.getCodec()); + public static final Codec> ARGUMENT_CODEC = createArgumentCodecFromSpecific(SPECIFIC_ARGUMENT_TYPE_CODEC); - public static final Codec> ARGUMENT_CODEC = SPECIFIC_ARGUMENT_TYPE_CODEC.dispatch(Argument::getType, specific -> specific.getArgumentCodec().fieldOf("data")); + public static final GenericArgumentType VALUE_ARGUMENT = register(Identifier.of(Minions.MOD_ID, "value"), ValueArgumentType::new); - public static final GenericArgumentType VALUE_ARGUMENT = register(Identifier.of(Minions.MOD_ID, "value"), ValueArgumentType::new); + public static Codec> createSpecificTypeCodec(Codec> genericCodec) { + return genericCodec.dispatch( + "type", + SpecificArgumentType::getGenericArgumentType, + generic -> + MinionRegistries.VALUE_TYPES.getCodec().xmap( + generic::createTypeSpecific, + SpecificArgumentType::getValueType + ).fieldOf("valueType") + ); + } - /*public static SpecificArgumentType> getArgumentType(Identifier id, ValueType valueType) { - GenericArgumentType generic = MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY.get(id); + public static > Codec> createArgumentCodecFromSpecific(Codec> specificTypeCodec) { + return specificTypeCodec.dispatch(Argument::getType, specific -> specific.getArgumentCodec().fieldOf("data")); + } + + public static > Codec> createArgumentCodec(Codec> genericTypeCodec) { + return createArgumentCodecFromSpecific(createSpecificTypeCodec(genericTypeCodec)); + } + + public static SpecificArgumentType, MinionFakePlayer> getArgumentType(Identifier id, ValueType valueType) { + GenericArgumentType generic = MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY.get(id); if(generic != null) { return generic.createTypeSpecific(valueType); } return null; - }*/ + } - public static GenericArgumentType register(Identifier id, GenericArgumentType argumentType) { + public static GenericArgumentType register(Identifier id, GenericArgumentType argumentType) { return Registry.register(MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY, id, argumentType); } } diff --git a/src/main/java/io/github/skippyall/minions/program/argument/GenericArgumentType.java b/src/main/java/io/github/skippyall/minions/program/argument/GenericArgumentType.java index d2844c5..9f698a7 100644 --- a/src/main/java/io/github/skippyall/minions/program/argument/GenericArgumentType.java +++ b/src/main/java/io/github/skippyall/minions/program/argument/GenericArgumentType.java @@ -1,7 +1,16 @@ package io.github.skippyall.minions.program.argument; +import io.github.skippyall.minions.program.InstructionRuntime; import io.github.skippyall.minions.program.value.ValueType; -public interface GenericArgumentType { - SpecificArgumentType> createTypeSpecific(ValueType valueType); +public interface GenericArgumentType> { + default SpecificArgumentType, R> createTypeSpecific(ValueType valueType) { + return createTypeSpecific(valueType, this); + } + + SpecificArgumentType, R> createTypeSpecific(ValueType valueType, GenericArgumentType me); + + default boolean canCreate(ValueType valueType) { + return true; + } } diff --git a/src/main/java/io/github/skippyall/minions/program/argument/SpecificArgumentType.java b/src/main/java/io/github/skippyall/minions/program/argument/SpecificArgumentType.java index 4934ee0..b8ad189 100644 --- a/src/main/java/io/github/skippyall/minions/program/argument/SpecificArgumentType.java +++ b/src/main/java/io/github/skippyall/minions/program/argument/SpecificArgumentType.java @@ -1,6 +1,7 @@ package io.github.skippyall.minions.program.argument; import com.mojang.serialization.Codec; +import io.github.skippyall.minions.program.InstructionRuntime; import io.github.skippyall.minions.program.value.ValueType; import net.minecraft.server.network.ServerPlayerEntity; import org.jetbrains.annotations.Nullable; @@ -13,15 +14,15 @@ import java.util.concurrent.CompletableFuture; * @param The value type of the Arguments to create * @param The type of the Arguments themselves */ -public abstract class SpecificArgumentType>> { - protected final ValueType valueType; +public abstract class SpecificArgumentType, R>, R extends InstructionRuntime> { + public final ValueType valueType; + public final GenericArgumentType genericType; - public SpecificArgumentType(ValueType valueType) { + public SpecificArgumentType(ValueType valueType, GenericArgumentType genericType) { this.valueType = valueType; + this.genericType = genericType; } - public abstract GenericArgumentType getGenericArgumentType(); - public abstract Codec getArgumentCodec(); public abstract CompletableFuture openArgumentDialog(ServerPlayerEntity player, @Nullable A previousArgument); @@ -29,4 +30,8 @@ public abstract class SpecificArgumentType getValueType() { return valueType; } + + public GenericArgumentType getGenericArgumentType() { + return genericType; + } } diff --git a/src/main/java/io/github/skippyall/minions/program/argument/ValueArgument.java b/src/main/java/io/github/skippyall/minions/program/argument/ValueArgument.java index f3b67a5..f8cef1a 100644 --- a/src/main/java/io/github/skippyall/minions/program/argument/ValueArgument.java +++ b/src/main/java/io/github/skippyall/minions/program/argument/ValueArgument.java @@ -2,15 +2,16 @@ package io.github.skippyall.minions.program.argument; import io.github.skippyall.minions.gui.GuiDisplay; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.program.InstructionRuntime; /** * An argument that always resolves to a fixed value */ -public class ValueArgument implements Argument> { - private final ValueArgumentType type; +public class ValueArgument> implements Argument, R> { + private final ValueArgumentType type; private final T value; - public ValueArgument(ValueArgumentType valueType, T value) { + public ValueArgument(ValueArgumentType valueType, T value) { this.type = valueType; this.value = value; } @@ -20,7 +21,7 @@ public class ValueArgument implements Argument> { } @Override - public T resolve(MinionFakePlayer minion) { + public T resolve(R runtime) { return value; } @@ -30,7 +31,7 @@ public class ValueArgument implements Argument> { } @Override - public ValueArgumentType getType() { + public ValueArgumentType getType() { return type; } } diff --git a/src/main/java/io/github/skippyall/minions/program/argument/ValueArgumentType.java b/src/main/java/io/github/skippyall/minions/program/argument/ValueArgumentType.java index 7316bad..bce1169 100644 --- a/src/main/java/io/github/skippyall/minions/program/argument/ValueArgumentType.java +++ b/src/main/java/io/github/skippyall/minions/program/argument/ValueArgumentType.java @@ -1,29 +1,25 @@ package io.github.skippyall.minions.program.argument; import com.mojang.serialization.Codec; +import io.github.skippyall.minions.program.InstructionRuntime; import io.github.skippyall.minions.program.value.ValueType; import net.minecraft.server.network.ServerPlayerEntity; import org.jetbrains.annotations.Nullable; import java.util.concurrent.CompletableFuture; -public class ValueArgumentType extends SpecificArgumentType> { - public ValueArgumentType(ValueType valueType) { - super(valueType); +public class ValueArgumentType> extends SpecificArgumentType, R> { + public ValueArgumentType(ValueType valueType, GenericArgumentType genericType) { + super(valueType, genericType); } @Override - public GenericArgumentType getGenericArgumentType() { - return Arguments.VALUE_ARGUMENT; - } - - @Override - public Codec> getArgumentCodec() { + public Codec> getArgumentCodec() { return valueType.codec().xmap(value -> new ValueArgument<>(this, value), ValueArgument::getValue); } @Override - public CompletableFuture> openArgumentDialog(ServerPlayerEntity player, @Nullable ValueArgument previousArgument) { + public CompletableFuture> openArgumentDialog(ServerPlayerEntity player, @Nullable ValueArgument previousArgument) { return valueType.openValueDialog( player, previousArgument != null ? previousArgument.getValue() : valueType.defaultValue() diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java b/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java index 51efa33..f729f08 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java @@ -8,28 +8,28 @@ import net.minecraft.storage.ReadView; import net.minecraft.storage.WriteView; import org.jetbrains.annotations.Nullable; -public class ConfiguredInstruction { - private final InstructionType instruction; - private final ArgumentList arguments; - private @Nullable InstructionExecution execution; +public class ConfiguredInstruction { + private final InstructionType instruction; + private final ArgumentList arguments; + private @Nullable InstructionExecution execution; private final String name; - private ConfiguredInstruction(InstructionType instruction, ArgumentList arguments, @Nullable InstructionExecution execution, String name) { + private ConfiguredInstruction(InstructionType instruction, ArgumentList arguments, @Nullable InstructionExecution execution, String name) { this.instruction = instruction; this.arguments = arguments; this.execution = execution; this.name = name; } - public ConfiguredInstruction(InstructionType instruction, String name) { - this(instruction, new ArgumentList(), null, name); + public ConfiguredInstruction(InstructionType instruction, String name) { + this(instruction, new ArgumentList<>(), null, name); } - public InstructionType getInstruction() { + public InstructionType getInstruction() { return instruction; } - public ArgumentList getArguments() { + public ArgumentList getArguments() { return arguments; } @@ -45,11 +45,11 @@ public class ConfiguredInstruction { return execution != null; } - public @Nullable InstructionExecution getExecution() { + public @Nullable InstructionExecution getExecution() { return execution; } - public void run(MinionFakePlayer minion) { + public void run(R minion) { if(canRun() && !isRunning()) { try { execution = instruction.createExecution(arguments, minion); @@ -61,7 +61,7 @@ public class ConfiguredInstruction { } } - public void tick(MinionFakePlayer minion) { + public void tick(R minion) { if(isRunning()) { if(execution.isDone(minion)) { stop(minion); @@ -74,14 +74,14 @@ public class ConfiguredInstruction { } } - public void stop(MinionFakePlayer minion) { + public void stop(R minion) { if(isRunning()) { execution.stop(minion); execution = null; } } - public void save(WriteView view, MinionFakePlayer minion) { + public void save(WriteView view, R minion) { view.put("instruction", MinionRegistries.INSTRUCTION_TYPES.getCodec(), instruction); view.put("arguments", ArgumentList.CODEC, arguments); view.putBoolean("running", isRunning()); @@ -90,18 +90,18 @@ public class ConfiguredInstruction { } } - public static ConfiguredInstruction load(ReadView view, MinionFakePlayer minion, String name) { + public static ConfiguredInstruction load(ReadView view, R minion, String name) { //noinspection unchecked - InstructionType instructionType = (InstructionType) view.read("instruction", MinionRegistries.INSTRUCTION_TYPES.getCodec()).orElseThrow(); + InstructionType instructionType = (InstructionType) view.read("instruction", MinionRegistries.INSTRUCTION_TYPES.getCodec()).orElseThrow(); - ArgumentList arguments = view.read("arguments", ArgumentList.CODEC).orElseThrow(); + ArgumentList arguments = view.read("arguments", ArgumentList.get).orElseThrow(); boolean running = view.getBoolean("running", false); if(running) { ReadView executionView = view.getReadView("execution"); try { - InstructionExecution execution = instructionType.loadExecution(executionView, minion); + InstructionExecution execution = instructionType.loadExecution(executionView, minion); return new ConfiguredInstruction<>(instructionType, arguments, execution, name); } catch (Exception e) { diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/InstructionExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/InstructionExecution.java index ff68335..3446482 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/InstructionExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/InstructionExecution.java @@ -1,6 +1,5 @@ package io.github.skippyall.minions.program.instruction; -import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.program.argument.ArgumentList; import net.minecraft.storage.ReadView; import net.minecraft.storage.WriteView; @@ -9,55 +8,52 @@ import net.minecraft.storage.WriteView; * Responsible for executing instructions. * When an instruction is executed: *
  • A new instance is created using the factory
  • - *
  • {@link InstructionExecution#readArguments(ArgumentList, MinionFakePlayer) readFromParameters} is called
  • - *
  • {@link InstructionExecution#start(MinionFakePlayer) start} is called
  • - * @param + *
  • {@link InstructionExecution#readArguments(ArgumentList, R) readFromParameters} is called
  • + *
  • {@link InstructionExecution#start(R) start} is called
  • + * @param */ -public interface InstructionExecution { +public interface InstructionExecution { /** * Starts the execution. - * @param minion */ - default void start(MinionFakePlayer minion) {} + default void start(R runtime) {} /** * Continues the execution of this instruction. * Called every tick while executing the instruction. - * @param minion */ - default void tick(MinionFakePlayer minion) {} + default void tick(R runtime) {} /** * Called every tick to determine if the execution of this instruction should be stopped. - * @param minion The minion executing the instruction * @return true if the instruction is done, false otherwise. */ - boolean isDone(MinionFakePlayer minion); + boolean isDone(R runtime); /** * Stops this execution. Is called when isDone returns true, but it may also be called before that. * In this case, the return value is ignored. * This should undo changes to the minion unless they are supposed to be permanent. * - * @param minion The minion that was executing this instruction. + * @param runtime The runtime that was executing this instruction. * @return The return value of the instruction */ - R stop(MinionFakePlayer minion); + Return stop(R runtime); /** * Initializes the execution with its arguments. * @param arguments The arguments to initialize the execution - * @param minion The minion should be used to resolve the arguments + * @param runtime The runtime should be used to resolve the arguments */ - void readArguments(ArgumentList arguments, MinionFakePlayer minion); + void readArguments(ArgumentList arguments, R runtime); /** * Saves the execution, e.g. when the server is closed. */ - void save(WriteView view, MinionFakePlayer minion); + void save(WriteView view, R runtime); /** * Loads the execution, e.g. when the server is started. */ - void load(ReadView view, MinionFakePlayer minion); + void load(ReadView view, R runtime); } diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/InstructionType.java b/src/main/java/io/github/skippyall/minions/program/instruction/InstructionType.java index e20d6ea..d057809 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/InstructionType.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/InstructionType.java @@ -2,33 +2,36 @@ package io.github.skippyall.minions.program.instruction; import io.github.skippyall.minions.gui.GuiDisplay; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.program.InstructionRuntime; import io.github.skippyall.minions.program.argument.Parameter; import io.github.skippyall.minions.program.argument.ArgumentList; import io.github.skippyall.minions.program.value.ValueType; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.recipe.Recipe; import net.minecraft.storage.ReadView; import java.util.Collection; import java.util.List; import java.util.function.Supplier; -public final class InstructionType { +public class InstructionType> { private final GuiDisplay display; private final Collection> parameters; - private final ValueType returnType; - private final Supplier> executionFactory; + private final ValueType returnType; + private final Supplier> executionFactory; - private InstructionType(GuiDisplay display, Supplier> executionFactory, ValueType returnType, Collection> parameters) { + private InstructionType(GuiDisplay display, Supplier> executionFactory, ValueType returnType, Collection> parameters) { this.display = display; this.parameters = parameters; this.returnType = returnType; this.executionFactory = executionFactory; } - public static InstructionType create(GuiDisplay display, Supplier> executionFactory, ValueType returnType, Collection> parameters) { + public static > InstructionType create(GuiDisplay display, Supplier> executionFactory, ValueType returnType, Collection> parameters) { return new InstructionType<>(display, executionFactory, returnType, List.copyOf(parameters)); } - public static InstructionType create(GuiDisplay display, Supplier> executionFactory, ValueType returnType, Parameter... parameters) { + public static > InstructionType create(GuiDisplay display, Supplier> executionFactory, ValueType returnType, Parameter... parameters) { return new InstructionType<>(display, executionFactory, returnType, List.of(parameters)); } @@ -36,7 +39,7 @@ public final class InstructionType { return parameters; } - public ValueType getReturnType() { + public ValueType getReturnType() { return returnType; } @@ -44,14 +47,14 @@ public final class InstructionType { return display; } - public InstructionExecution createExecution(ArgumentList parameters, MinionFakePlayer minion) { - InstructionExecution execution = executionFactory.get(); + public InstructionExecution createExecution(ArgumentList parameters, R minion) { + InstructionExecution execution = executionFactory.get(); execution.readArguments(parameters, minion); return execution; } - public InstructionExecution loadExecution(ReadView view, MinionFakePlayer minion) { - InstructionExecution execution = executionFactory.get(); + public InstructionExecution loadExecution(ReadView view, R minion) { + InstructionExecution execution = executionFactory.get(); execution.load(view, minion); return execution; } diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/Instructions.java b/src/main/java/io/github/skippyall/minions/program/instruction/Instructions.java index 554d9eb..349df47 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/Instructions.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/Instructions.java @@ -4,6 +4,7 @@ import io.github.skippyall.minions.MinionRegistries; import io.github.skippyall.minions.Minions; import io.github.skippyall.minions.gui.GuiDisplay; import io.github.skippyall.minions.minion.fakeplayer.EntityPlayerActionPack; +import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.program.instruction.execution.ActionExecution; import io.github.skippyall.minions.program.instruction.execution.WalkExecution; import io.github.skippyall.minions.program.argument.Parameter; @@ -18,7 +19,7 @@ import java.util.function.Function; import java.util.function.Supplier; public class Instructions { - public static final InstructionType WALK = register( + public static final InstructionType WALK = register( "walk", base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_BOOTS), base, true), WalkExecution::new, @@ -26,21 +27,21 @@ public class Instructions { WalkExecution.blocksToMoveParam ); - public static final InstructionType ATTACK = register( + public static final InstructionType ATTACK = register( "attack", base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_BOOTS), base, true), () -> new ActionExecution(EntityPlayerActionPack.ActionType.ATTACK), ValueTypes.VOID ); - public static final InstructionType USE = register( + public static final InstructionType USE = register( "use", base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.LEVER), base, true), () -> new ActionExecution(EntityPlayerActionPack.ActionType.USE), ValueTypes.VOID ); - private static InstructionType register(String id, Function displayFunction, Supplier> factory, ValueType returnType, Parameter... parameters) { + private static InstructionType register(String id, Function displayFunction, Supplier> factory, ValueType returnType, Parameter... parameters) { Identifier identifier = Identifier.of(Minions.MOD_ID, id); return Registry.register(MinionRegistries.INSTRUCTION_TYPES, identifier, InstructionType.create(displayFunction.apply(identifier.toTranslationKey("instruction_type")), factory, returnType, parameters)); } diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/execution/ContinuousInstructionExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/execution/ContinuousInstructionExecution.java index bde65ac..b2c953c 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/execution/ContinuousInstructionExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/execution/ContinuousInstructionExecution.java @@ -3,7 +3,7 @@ package io.github.skippyall.minions.program.instruction.execution; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.program.instruction.InstructionExecution; -public interface ContinuousInstructionExecution extends InstructionExecution { +public interface ContinuousInstructionExecution extends InstructionExecution { @Override default boolean isDone(MinionFakePlayer minion) { return false; diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/execution/TimedInstructionExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/execution/TimedInstructionExecution.java index f06c450..3eb56d5 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/execution/TimedInstructionExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/execution/TimedInstructionExecution.java @@ -10,7 +10,7 @@ import net.minecraft.storage.WriteView; * The timer must be set with setTimer when reading from parameters. * Saving and loading of the timer is automatic if the super method is called by the subclass. */ -public abstract class TimedInstructionExecution implements InstructionExecution { +public abstract class TimedInstructionExecution implements InstructionExecution { int timer; public int getTimer() { diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/execution/TurnExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/execution/TurnExecution.java index fcf1f20..273563e 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/execution/TurnExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/execution/TurnExecution.java @@ -14,7 +14,7 @@ import net.minecraft.util.StringIdentifiable; import java.util.UUID; -public class TurnExecution implements InstructionExecution { +public class TurnExecution implements InstructionExecution { public static final Parameter ANGLE = new Parameter<>("maxAngle", ValueTypes.FLOAT); public static final Parameter DIRECTION = new Parameter<>("direction", ValueTypes.TURN_DIRECTION); @@ -43,7 +43,7 @@ public class TurnExecution implements InstructionExecution { } @Override - public void readArguments(ArgumentList arguments, MinionFakePlayer minion) { + public void readArguments(ArgumentList arguments, MinionFakePlayer minion) { maxAngle = arguments.getValue(ANGLE, minion); direction = arguments.getValue(DIRECTION, minion); } diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/execution/WalkExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/execution/WalkExecution.java index 1d5e9fa..a2ba949 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/execution/WalkExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/execution/WalkExecution.java @@ -9,7 +9,7 @@ import net.minecraft.entity.MovementType; import net.minecraft.storage.ReadView; import net.minecraft.storage.WriteView; -public class WalkExecution implements InstructionExecution { +public class WalkExecution implements InstructionExecution { public static final Parameter blocksToMoveParam = new Parameter<>("blocksToMove", ValueTypes.FLOAT); private final float ACCURACY = 1F / 32F; @@ -34,7 +34,7 @@ public class WalkExecution implements InstructionExecution { } @Override - public void readArguments(ArgumentList parameters, MinionFakePlayer minion) { + public void readArguments(ArgumentList parameters, MinionFakePlayer minion) { totalBlocksToMove = parameters.getValue(blocksToMoveParam, minion); blocksMoved = 0; } diff --git a/src/main/java/io/github/skippyall/minions/program/returnvalue/GenericValueConsumerType.java b/src/main/java/io/github/skippyall/minions/program/returnvalue/GenericValueConsumerType.java new file mode 100644 index 0000000..850300f --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/program/returnvalue/GenericValueConsumerType.java @@ -0,0 +1,19 @@ +package io.github.skippyall.minions.program.returnvalue; + +import io.github.skippyall.minions.program.InstructionRuntime; +import io.github.skippyall.minions.program.argument.Argument; +import io.github.skippyall.minions.program.argument.SpecificArgumentType; +import io.github.skippyall.minions.program.value.ValueType; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; + +public interface GenericValueConsumerType> { + default SpecificValueConsumerType, R> createTypeSpecific(ValueType valueType) { + return createTypeSpecific(valueType, this); + } + + SpecificValueConsumerType, R> createTypeSpecific(ValueType valueType, GenericValueConsumerType me); + + default boolean canCreate(ValueType valueType) { + return true; + } +} diff --git a/src/main/java/io/github/skippyall/minions/program/returnvalue/ReturnValueList.java b/src/main/java/io/github/skippyall/minions/program/returnvalue/ReturnValueList.java new file mode 100644 index 0000000..6db8ac7 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/program/returnvalue/ReturnValueList.java @@ -0,0 +1,57 @@ +package io.github.skippyall.minions.program.returnvalue; + +import com.mojang.serialization.Codec; +import io.github.skippyall.minions.program.InstructionRuntime; +import io.github.skippyall.minions.program.argument.Argument; +import io.github.skippyall.minions.program.argument.Arguments; +import io.github.skippyall.minions.program.argument.GenericArgumentType; +import io.github.skippyall.minions.program.argument.Parameter; +import io.github.skippyall.minions.program.argument.SpecificArgumentType; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class ReturnValueList> { + private final Map> arguments; + + public ReturnValueList() { + arguments = new HashMap<>(); + } + + public ReturnValueList(Map> arguments) { + this.arguments = new HashMap<>(arguments); + } + + public T getValue(Parameter parameter, R runtime) { + Argument argument = getArgument(parameter); + return argument != null ? argument.resolve(runtime) : null; + } + + public ,R>> A getArgument(Parameter parameter) { + Argument argument = arguments.get(parameter.name()); + return argument == null ? null : argument.cast(parameter.type()); + } + + public void setArgument(Parameter parameter, Argument argument) { + arguments.put(parameter.name(), argument); + } + + public boolean hasArgumentFor(Parameter parameter) { + return getArgument(parameter) != null; + } + + public boolean hasArgumentForAll(Collection> checkParameters) { + for(Parameter parameter : checkParameters) { + if(!hasArgumentFor(parameter)) { + return false; + } + } + return true; + } + + public static > Codec> getCodec(Codec> genericCodec) { + return Codec.unboundedMap(Codec.STRING, Arguments.createArgumentCodec(genericCodec)) + .xmap(ReturnValueList::new, list -> list.arguments); + } +} diff --git a/src/main/java/io/github/skippyall/minions/program/returnvalue/SpecificValueConsumerType.java b/src/main/java/io/github/skippyall/minions/program/returnvalue/SpecificValueConsumerType.java new file mode 100644 index 0000000..74cf27c --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/program/returnvalue/SpecificValueConsumerType.java @@ -0,0 +1,39 @@ +package io.github.skippyall.minions.program.returnvalue; + +import com.mojang.serialization.Codec; +import io.github.skippyall.minions.program.InstructionRuntime; +import io.github.skippyall.minions.program.argument.Argument; +import io.github.skippyall.minions.program.argument.GenericArgumentType; +import io.github.skippyall.minions.program.value.ValueType; +import net.minecraft.server.network.ServerPlayerEntity; +import org.jetbrains.annotations.Nullable; + +import java.util.concurrent.CompletableFuture; + +/** + * SpecificArgumentTypes create Arguments of the specified ValueType. + * They are also responsible for the serialization and user input of arguments. + * @param The value type of the Arguments to create + * @param
    The type of the Arguments themselves + */ +public abstract class SpecificValueConsumerType, R>, R extends InstructionRuntime> { + public final ValueType valueType; + public final GenericArgumentType genericType; + + public SpecificValueConsumerType(ValueType valueType, GenericArgumentType genericType) { + this.valueType = valueType; + this.genericType = genericType; + } + + public abstract Codec getValueConsumerCodec(); + + public abstract CompletableFuture openValueConsumerDialog(ServerPlayerEntity player, @Nullable A previousArgument); + + public ValueType getValueType() { + return valueType; + } + + public GenericArgumentType getGenericArgumentType() { + return genericType; + } +} diff --git a/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumer.java b/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumer.java new file mode 100644 index 0000000..66a0ac8 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumer.java @@ -0,0 +1,35 @@ +package io.github.skippyall.minions.program.returnvalue; + +import io.github.skippyall.minions.gui.GuiDisplay; +import io.github.skippyall.minions.program.InstructionRuntime; +import io.github.skippyall.minions.program.argument.SpecificArgumentType; +import io.github.skippyall.minions.program.value.ValueType; +import org.jetbrains.annotations.Nullable; + +/** + * An Argument can be supplied to an instruction with a matching parameter. + * Its value is resolved at runtime and can vary between executions. + * Arguments are created exclusively by SpecificArgumentTypes. + * @param The type of the Argument's value + * @param The SpecificArgumentType + */ +public interface ValueConsumer, R>, R extends InstructionRuntime> { + void consume(T value, R runtime); + + default ValueType getValueType() { + return getType().getValueType(); + } + + GuiDisplay getDisplay(); + + S getType(); + + default , R>> @Nullable A cast(ValueType type) { + if(getValueType() == type) { + //noinspection unchecked + return (A) this; + } else { + return null; + } + } +}