Commiting before Dingenskirchen

This commit is contained in:
skippyall
2025-10-08 00:04:21 +02:00
parent 640e6f801a
commit da4351cff2
23 changed files with 335 additions and 111 deletions
@@ -1,6 +1,8 @@
package io.github.skippyall.minions; package io.github.skippyall.minions;
import com.mojang.serialization.Lifecycle; 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.minion.skin.SkinProvider;
import io.github.skippyall.minions.program.argument.GenericArgumentType; import io.github.skippyall.minions.program.argument.GenericArgumentType;
import io.github.skippyall.minions.program.instruction.InstructionType; import io.github.skippyall.minions.program.instruction.InstructionType;
@@ -12,7 +14,7 @@ import net.minecraft.util.Identifier;
public class MinionRegistries { public class MinionRegistries {
public static final Registry<ValueType<?>> VALUE_TYPES = registry("value_type"); public static final Registry<ValueType<?>> VALUE_TYPES = registry("value_type");
public static final Registry<GenericArgumentType> GENERIC_ARGUMENT_TYPE_REGISTRY = registry("generic_argument_type"); public static final Registry<GenericArgumentType<MinionRuntime>> GENERIC_ARGUMENT_TYPE_REGISTRY = registry("generic_argument_type");
public static final Registry<InstructionType<?>> INSTRUCTION_TYPES = registry("instruction_type"); public static final Registry<InstructionType<?>> INSTRUCTION_TYPES = registry("instruction_type");
public static final Registry<SkinProvider> SKIN_PROVIDERS = registry("skin_providers"); public static final Registry<SkinProvider> SKIN_PROVIDERS = registry("skin_providers");
@@ -112,7 +112,7 @@ public class InstructionGui {
} }
} }
public static <T, A extends Argument<T, ? extends SpecificArgumentType<T, A>>> void configureArgumentMenu(String name, ConfiguredInstruction<?> instruction, Parameter<T> parameter, MinionFakePlayer minion, ServerPlayerEntity player) { public static <T, A extends Argument<T, ? extends SpecificArgumentType<T, A, MinionFakePlayer>, MinionFakePlayer>> void configureArgumentMenu(String name, ConfiguredInstruction<?> instruction, Parameter<T> parameter, MinionFakePlayer minion, ServerPlayerEntity player) {
if(!checkInstructionExists(name, instruction, minion, player)) { if(!checkInstructionExists(name, instruction, minion, player)) {
return; return;
} }
@@ -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<MinionRuntime> {
@Override
public Registry<GenericArgumentType<MinionRuntime>> getGenericArgumentTypeRegistry() {
return MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY;
}
}
@@ -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<R extends InstructionRuntime<R>> {
Registry<GenericArgumentType<R>> getGenericArgumentTypeRegistry();
default Codec<GenericArgumentType<R>> getGenericArgumentTypeCodec() {
return getGenericArgumentTypeRegistry().getCodec();
}
default Codec<SpecificArgumentType<?,?,R>> getSpecificArgumentTypeCodec() {
return Arguments.createSpecificTypeCodec(getGenericArgumentTypeCodec());
}
default Codec<Argument<?,?,R>> getArgumentCodec() {
return Arguments.createArgumentCodec(getGenericArgumentTypeCodec());
}
default Codec<ArgumentList<R>> getArgumentListCodec() {
return ArgumentList.getCodec(getGenericArgumentTypeCodec());
}
}
@@ -1,7 +1,7 @@
package io.github.skippyall.minions.program.argument; package io.github.skippyall.minions.program.argument;
import io.github.skippyall.minions.gui.GuiDisplay; 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 io.github.skippyall.minions.program.value.ValueType;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -12,8 +12,8 @@ import org.jetbrains.annotations.Nullable;
* @param <T> The type of the <code>Argument</code>'s value * @param <T> The type of the <code>Argument</code>'s value
* @param <S> The <code>SpecificArgumentType</code> * @param <S> The <code>SpecificArgumentType</code>
*/ */
public interface Argument<T, S extends SpecificArgumentType<T, ? extends Argument<T, S>>> { public interface Argument<T, S extends SpecificArgumentType<T, ? extends Argument<T, S, R>, R>, R extends InstructionRuntime<R>> {
T resolve(MinionFakePlayer minion); T resolve(R minion);
default ValueType<T> getValueType() { default ValueType<T> getValueType() {
return getType().getValueType(); return getType().getValueType();
@@ -23,7 +23,7 @@ public interface Argument<T, S extends SpecificArgumentType<T, ? extends Argumen
S getType(); S getType();
default <U, A extends Argument<U, ? extends SpecificArgumentType<U,A>>> @Nullable A cast(ValueType<U> type) { default <U, A extends Argument<U, ? extends SpecificArgumentType<U,A,R>, R>> @Nullable A cast(ValueType<U> type) {
if(getValueType() == type) { if(getValueType() == type) {
//noinspection unchecked //noinspection unchecked
return (A) this; return (A) this;
@@ -1,37 +1,36 @@
package io.github.skippyall.minions.program.argument; package io.github.skippyall.minions.program.argument;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.program.InstructionRuntime;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class ArgumentList { public class ArgumentList<R extends InstructionRuntime<R>> {
public static final Codec<ArgumentList> CODEC = Codec.unboundedMap(Codec.STRING, Arguments.ARGUMENT_CODEC) private final Map<String, Argument<?, ?, R>> arguments;
.xmap(ArgumentList::new, list -> list.arguments);
private final Map<String, Argument<?, ?>> arguments;
public ArgumentList() { public ArgumentList() {
arguments = new HashMap<>(); arguments = new HashMap<>();
} }
public ArgumentList(Map<String, Argument<?,?>> arguments) { public ArgumentList(Map<String, Argument<?,?, R>> arguments) {
this.arguments = new HashMap<>(arguments); this.arguments = new HashMap<>(arguments);
} }
public <T> T getValue(Parameter<T> parameter, MinionFakePlayer minion) { public <T> T getValue(Parameter<T> parameter, R runtime) {
Argument<T,?> argument = getArgument(parameter); Argument<T,?,R> argument = getArgument(parameter);
return argument != null ? argument.resolve(minion) : null; return argument != null ? argument.resolve(runtime) : null;
} }
public <T, A extends Argument<T, ? extends SpecificArgumentType<T,A>>> A getArgument(Parameter<T> parameter) { public <T, A extends Argument<T, ? extends SpecificArgumentType<T,A,R>,R>> A getArgument(Parameter<T> parameter) {
Argument<?, ?> argument = arguments.get(parameter.name()); Argument<?, ?,R> argument = arguments.get(parameter.name());
return argument == null ? null : argument.cast(parameter.type()); return argument == null ? null : argument.cast(parameter.type());
} }
public <T> void setArgument(Parameter<T> parameter, Argument<T,?> argument) { public <T> void setArgument(Parameter<T> parameter, Argument<T,?,R> argument) {
arguments.put(parameter.name(), argument); arguments.put(parameter.name(), argument);
} }
@@ -47,4 +46,9 @@ public class ArgumentList {
} }
return true; return true;
} }
public static <R extends InstructionRuntime<R>> Codec<ArgumentList<R>> getCodec(Codec<GenericArgumentType<R>> genericCodec) {
return Codec.unboundedMap(Codec.STRING, Arguments.createArgumentCodec(genericCodec))
.xmap(ArgumentList::new, list -> list.arguments);
}
} }
@@ -3,34 +3,48 @@ package io.github.skippyall.minions.program.argument;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import io.github.skippyall.minions.MinionRegistries; import io.github.skippyall.minions.MinionRegistries;
import io.github.skippyall.minions.Minions; 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.registry.Registry;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
public class Arguments { public class Arguments {
public static final Codec<SpecificArgumentType<?,?>> SPECIFIC_ARGUMENT_TYPE_CODEC = MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY.getCodec().dispatch( public static final Codec<SpecificArgumentType<?,?, MinionFakePlayer>> SPECIFIC_ARGUMENT_TYPE_CODEC = createSpecificTypeCodec(MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY.getCodec());
"type", public static final Codec<Argument<?,?,MinionFakePlayer>> ARGUMENT_CODEC = createArgumentCodecFromSpecific(SPECIFIC_ARGUMENT_TYPE_CODEC);
SpecificArgumentType::getGenericArgumentType,
generic ->
MinionRegistries.VALUE_TYPES.getCodec().xmap(
generic::createTypeSpecific,
SpecificArgumentType::getValueType
).fieldOf("valueType")
);
public static final Codec<Argument<?,?>> ARGUMENT_CODEC = SPECIFIC_ARGUMENT_TYPE_CODEC.dispatch(Argument::getType, specific -> specific.getArgumentCodec().fieldOf("data")); public static final GenericArgumentType<MinionFakePlayer> 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 <R> Codec<SpecificArgumentType<?,?,R>> createSpecificTypeCodec(Codec<GenericArgumentType<R>> genericCodec) {
return genericCodec.dispatch(
"type",
SpecificArgumentType::getGenericArgumentType,
generic ->
MinionRegistries.VALUE_TYPES.getCodec().xmap(
generic::createTypeSpecific,
SpecificArgumentType::getValueType
).fieldOf("valueType")
);
}
/*public static <V> SpecificArgumentType<V, ? extends Argument<V, ?>> getArgumentType(Identifier id, ValueType<V> valueType) { public static <R extends InstructionRuntime<R>> Codec<Argument<?, ?, R>> createArgumentCodecFromSpecific(Codec<SpecificArgumentType<?,?,R>> specificTypeCodec) {
GenericArgumentType generic = MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY.get(id); return specificTypeCodec.dispatch(Argument::getType, specific -> specific.getArgumentCodec().fieldOf("data"));
}
public static <R extends InstructionRuntime<R>> Codec<Argument<?,?,R>> createArgumentCodec(Codec<GenericArgumentType<R>> genericTypeCodec) {
return createArgumentCodecFromSpecific(createSpecificTypeCodec(genericTypeCodec));
}
public static <V> SpecificArgumentType<V, ? extends Argument<V, ?, MinionFakePlayer>, MinionFakePlayer> getArgumentType(Identifier id, ValueType<V> valueType) {
GenericArgumentType<MinionFakePlayer> generic = MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY.get(id);
if(generic != null) { if(generic != null) {
return generic.createTypeSpecific(valueType); return generic.createTypeSpecific(valueType);
} }
return null; return null;
}*/ }
public static GenericArgumentType register(Identifier id, GenericArgumentType argumentType) { public static GenericArgumentType<MinionFakePlayer> register(Identifier id, GenericArgumentType<MinionFakePlayer> argumentType) {
return Registry.register(MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY, id, argumentType); return Registry.register(MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY, id, argumentType);
} }
} }
@@ -1,7 +1,16 @@
package io.github.skippyall.minions.program.argument; package io.github.skippyall.minions.program.argument;
import io.github.skippyall.minions.program.InstructionRuntime;
import io.github.skippyall.minions.program.value.ValueType; import io.github.skippyall.minions.program.value.ValueType;
public interface GenericArgumentType { public interface GenericArgumentType<R extends InstructionRuntime<R>> {
<V> SpecificArgumentType<V, ? extends Argument<V,?>> createTypeSpecific(ValueType<V> valueType); default <V> SpecificArgumentType<V, ? extends Argument<V, ?, R>, R> createTypeSpecific(ValueType<V> valueType) {
return createTypeSpecific(valueType, this);
}
<V> SpecificArgumentType<V, ? extends Argument<V, ?, R>, R> createTypeSpecific(ValueType<V> valueType, GenericArgumentType<R> me);
default boolean canCreate(ValueType<?> valueType) {
return true;
}
} }
@@ -1,6 +1,7 @@
package io.github.skippyall.minions.program.argument; package io.github.skippyall.minions.program.argument;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import io.github.skippyall.minions.program.InstructionRuntime;
import io.github.skippyall.minions.program.value.ValueType; import io.github.skippyall.minions.program.value.ValueType;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -13,15 +14,15 @@ import java.util.concurrent.CompletableFuture;
* @param <V> The value type of the <code>Argument</code>s to create * @param <V> The value type of the <code>Argument</code>s to create
* @param <A> The type of the <code>Argument</code>s themselves * @param <A> The type of the <code>Argument</code>s themselves
*/ */
public abstract class SpecificArgumentType<V, A extends Argument<V, ? extends SpecificArgumentType<V, A>>> { public abstract class SpecificArgumentType<V, A extends Argument<V, ? extends SpecificArgumentType<V, A, R>, R>, R extends InstructionRuntime<R>> {
protected final ValueType<V> valueType; public final ValueType<V> valueType;
public final GenericArgumentType<R> genericType;
public SpecificArgumentType(ValueType<V> valueType) { public SpecificArgumentType(ValueType<V> valueType, GenericArgumentType<R> genericType) {
this.valueType = valueType; this.valueType = valueType;
this.genericType = genericType;
} }
public abstract GenericArgumentType getGenericArgumentType();
public abstract Codec<A> getArgumentCodec(); public abstract Codec<A> getArgumentCodec();
public abstract CompletableFuture<A> openArgumentDialog(ServerPlayerEntity player, @Nullable A previousArgument); public abstract CompletableFuture<A> openArgumentDialog(ServerPlayerEntity player, @Nullable A previousArgument);
@@ -29,4 +30,8 @@ public abstract class SpecificArgumentType<V, A extends Argument<V, ? extends Sp
public ValueType<V> getValueType() { public ValueType<V> getValueType() {
return valueType; return valueType;
} }
public GenericArgumentType<R> getGenericArgumentType() {
return genericType;
}
} }
@@ -2,15 +2,16 @@ package io.github.skippyall.minions.program.argument;
import io.github.skippyall.minions.gui.GuiDisplay; import io.github.skippyall.minions.gui.GuiDisplay;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.program.InstructionRuntime;
/** /**
* An argument that always resolves to a fixed value * An argument that always resolves to a fixed value
*/ */
public class ValueArgument<T> implements Argument<T, ValueArgumentType<T>> { public class ValueArgument<T, R extends InstructionRuntime<R>> implements Argument<T, ValueArgumentType<T, R>, R> {
private final ValueArgumentType<T> type; private final ValueArgumentType<T,R> type;
private final T value; private final T value;
public ValueArgument(ValueArgumentType<T> valueType, T value) { public ValueArgument(ValueArgumentType<T,R> valueType, T value) {
this.type = valueType; this.type = valueType;
this.value = value; this.value = value;
} }
@@ -20,7 +21,7 @@ public class ValueArgument<T> implements Argument<T, ValueArgumentType<T>> {
} }
@Override @Override
public T resolve(MinionFakePlayer minion) { public T resolve(R runtime) {
return value; return value;
} }
@@ -30,7 +31,7 @@ public class ValueArgument<T> implements Argument<T, ValueArgumentType<T>> {
} }
@Override @Override
public ValueArgumentType<T> getType() { public ValueArgumentType<T,R> getType() {
return type; return type;
} }
} }
@@ -1,29 +1,25 @@
package io.github.skippyall.minions.program.argument; package io.github.skippyall.minions.program.argument;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import io.github.skippyall.minions.program.InstructionRuntime;
import io.github.skippyall.minions.program.value.ValueType; import io.github.skippyall.minions.program.value.ValueType;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class ValueArgumentType<V> extends SpecificArgumentType<V, ValueArgument<V>> { public class ValueArgumentType<V, R extends InstructionRuntime<R>> extends SpecificArgumentType<V, ValueArgument<V,R>, R> {
public ValueArgumentType(ValueType<V> valueType) { public ValueArgumentType(ValueType<V> valueType, GenericArgumentType<R> genericType) {
super(valueType); super(valueType, genericType);
} }
@Override @Override
public GenericArgumentType getGenericArgumentType() { public Codec<ValueArgument<V,R>> getArgumentCodec() {
return Arguments.VALUE_ARGUMENT;
}
@Override
public Codec<ValueArgument<V>> getArgumentCodec() {
return valueType.codec().xmap(value -> new ValueArgument<>(this, value), ValueArgument::getValue); return valueType.codec().xmap(value -> new ValueArgument<>(this, value), ValueArgument::getValue);
} }
@Override @Override
public CompletableFuture<ValueArgument<V>> openArgumentDialog(ServerPlayerEntity player, @Nullable ValueArgument<V> previousArgument) { public CompletableFuture<ValueArgument<V,R>> openArgumentDialog(ServerPlayerEntity player, @Nullable ValueArgument<V,R> previousArgument) {
return valueType.openValueDialog( return valueType.openValueDialog(
player, player,
previousArgument != null ? previousArgument.getValue() : valueType.defaultValue() previousArgument != null ? previousArgument.getValue() : valueType.defaultValue()
@@ -8,28 +8,28 @@ import net.minecraft.storage.ReadView;
import net.minecraft.storage.WriteView; import net.minecraft.storage.WriteView;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class ConfiguredInstruction<R> { public class ConfiguredInstruction<Return,R> {
private final InstructionType<R> instruction; private final InstructionType<Return,R> instruction;
private final ArgumentList arguments; private final ArgumentList<R> arguments;
private @Nullable InstructionExecution<R> execution; private @Nullable InstructionExecution<Return, R> execution;
private final String name; private final String name;
private ConfiguredInstruction(InstructionType<R> instruction, ArgumentList arguments, @Nullable InstructionExecution<R> execution, String name) { private ConfiguredInstruction(InstructionType<Return,R> instruction, ArgumentList<R> arguments, @Nullable InstructionExecution<Return,R> execution, String name) {
this.instruction = instruction; this.instruction = instruction;
this.arguments = arguments; this.arguments = arguments;
this.execution = execution; this.execution = execution;
this.name = name; this.name = name;
} }
public ConfiguredInstruction(InstructionType<R> instruction, String name) { public ConfiguredInstruction(InstructionType<Return,R> instruction, String name) {
this(instruction, new ArgumentList(), null, name); this(instruction, new ArgumentList<>(), null, name);
} }
public InstructionType<R> getInstruction() { public InstructionType<Return,R> getInstruction() {
return instruction; return instruction;
} }
public ArgumentList getArguments() { public ArgumentList<R> getArguments() {
return arguments; return arguments;
} }
@@ -45,11 +45,11 @@ public class ConfiguredInstruction<R> {
return execution != null; return execution != null;
} }
public @Nullable InstructionExecution<R> getExecution() { public @Nullable InstructionExecution<Return,R> getExecution() {
return execution; return execution;
} }
public void run(MinionFakePlayer minion) { public void run(R minion) {
if(canRun() && !isRunning()) { if(canRun() && !isRunning()) {
try { try {
execution = instruction.createExecution(arguments, minion); execution = instruction.createExecution(arguments, minion);
@@ -61,7 +61,7 @@ public class ConfiguredInstruction<R> {
} }
} }
public void tick(MinionFakePlayer minion) { public void tick(R minion) {
if(isRunning()) { if(isRunning()) {
if(execution.isDone(minion)) { if(execution.isDone(minion)) {
stop(minion); stop(minion);
@@ -74,14 +74,14 @@ public class ConfiguredInstruction<R> {
} }
} }
public void stop(MinionFakePlayer minion) { public void stop(R minion) {
if(isRunning()) { if(isRunning()) {
execution.stop(minion); execution.stop(minion);
execution = null; 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("instruction", MinionRegistries.INSTRUCTION_TYPES.getCodec(), instruction);
view.put("arguments", ArgumentList.CODEC, arguments); view.put("arguments", ArgumentList.CODEC, arguments);
view.putBoolean("running", isRunning()); view.putBoolean("running", isRunning());
@@ -90,18 +90,18 @@ public class ConfiguredInstruction<R> {
} }
} }
public static <R> ConfiguredInstruction<R> load(ReadView view, MinionFakePlayer minion, String name) { public static <Return,R> ConfiguredInstruction<Return,R> load(ReadView view, R minion, String name) {
//noinspection unchecked //noinspection unchecked
InstructionType<R> instructionType = (InstructionType<R>) view.read("instruction", MinionRegistries.INSTRUCTION_TYPES.getCodec()).orElseThrow(); InstructionType<Return,R> instructionType = (InstructionType<Return,R>) view.read("instruction", MinionRegistries.INSTRUCTION_TYPES.getCodec()).orElseThrow();
ArgumentList arguments = view.read("arguments", ArgumentList.CODEC).orElseThrow(); ArgumentList<R> arguments = view.read("arguments", ArgumentList.get).orElseThrow();
boolean running = view.getBoolean("running", false); boolean running = view.getBoolean("running", false);
if(running) { if(running) {
ReadView executionView = view.getReadView("execution"); ReadView executionView = view.getReadView("execution");
try { try {
InstructionExecution<R> execution = instructionType.loadExecution(executionView, minion); InstructionExecution<Return,R> execution = instructionType.loadExecution(executionView, minion);
return new ConfiguredInstruction<>(instructionType, arguments, execution, name); return new ConfiguredInstruction<>(instructionType, arguments, execution, name);
} catch (Exception e) { } catch (Exception e) {
@@ -1,6 +1,5 @@
package io.github.skippyall.minions.program.instruction; package io.github.skippyall.minions.program.instruction;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.program.argument.ArgumentList; import io.github.skippyall.minions.program.argument.ArgumentList;
import net.minecraft.storage.ReadView; import net.minecraft.storage.ReadView;
import net.minecraft.storage.WriteView; import net.minecraft.storage.WriteView;
@@ -9,55 +8,52 @@ import net.minecraft.storage.WriteView;
* Responsible for executing instructions. * Responsible for executing instructions.
* When an instruction is executed: * When an instruction is executed:
* <li>A new instance is created using the factory</li> * <li>A new instance is created using the factory</li>
* <li>{@link InstructionExecution#readArguments(ArgumentList, MinionFakePlayer) readFromParameters} is called</li> * <li>{@link InstructionExecution#readArguments(ArgumentList, R) readFromParameters} is called</li>
* <li>{@link InstructionExecution#start(MinionFakePlayer) start} is called</li> * <li>{@link InstructionExecution#start(R) start} is called</li>
* @param <R> * @param <Return>
*/ */
public interface InstructionExecution<R> { public interface InstructionExecution<Return, R> {
/** /**
* Starts the execution. * Starts the execution.
* @param minion
*/ */
default void start(MinionFakePlayer minion) {} default void start(R runtime) {}
/** /**
* Continues the execution of this instruction. * Continues the execution of this instruction.
* Called every tick while executing the 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. * Called every tick to determine if the execution of this instruction should be stopped.
* @param minion The minion executing the instruction
* @return <code>true</code> if the instruction is done, <code>false</code> otherwise. * @return <code>true</code> if the instruction is done, <code>false</code> 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. * 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. * In this case, the return value is ignored.
* This should undo changes to the minion unless they are supposed to be permanent. * 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 * @return The return value of the instruction
*/ */
R stop(MinionFakePlayer minion); Return stop(R runtime);
/** /**
* Initializes the execution with its arguments. * Initializes the execution with its arguments.
* @param arguments The arguments to initialize the execution * @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<R> arguments, R runtime);
/** /**
* Saves the execution, e.g. when the server is closed. * 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. * Loads the execution, e.g. when the server is started.
*/ */
void load(ReadView view, MinionFakePlayer minion); void load(ReadView view, R runtime);
} }
@@ -2,33 +2,36 @@ package io.github.skippyall.minions.program.instruction;
import io.github.skippyall.minions.gui.GuiDisplay; import io.github.skippyall.minions.gui.GuiDisplay;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; 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.Parameter;
import io.github.skippyall.minions.program.argument.ArgumentList; import io.github.skippyall.minions.program.argument.ArgumentList;
import io.github.skippyall.minions.program.value.ValueType; 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 net.minecraft.storage.ReadView;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
public final class InstructionType<R> { public class InstructionType<Return, R extends InstructionRuntime<R>> {
private final GuiDisplay display; private final GuiDisplay display;
private final Collection<Parameter<?>> parameters; private final Collection<Parameter<?>> parameters;
private final ValueType<R> returnType; private final ValueType<Return> returnType;
private final Supplier<InstructionExecution<R>> executionFactory; private final Supplier<InstructionExecution<Return,R>> executionFactory;
private InstructionType(GuiDisplay display, Supplier<InstructionExecution<R>> executionFactory, ValueType<R> returnType, Collection<Parameter<?>> parameters) { private InstructionType(GuiDisplay display, Supplier<InstructionExecution<Return,R>> executionFactory, ValueType<Return> returnType, Collection<Parameter<?>> parameters) {
this.display = display; this.display = display;
this.parameters = parameters; this.parameters = parameters;
this.returnType = returnType; this.returnType = returnType;
this.executionFactory = executionFactory; this.executionFactory = executionFactory;
} }
public static <R> InstructionType<R> create(GuiDisplay display, Supplier<InstructionExecution<R>> executionFactory, ValueType<R> returnType, Collection<Parameter<?>> parameters) { public static <Return,R extends InstructionRuntime<R>> InstructionType<Return,R> create(GuiDisplay display, Supplier<InstructionExecution<Return,R>> executionFactory, ValueType<Return> returnType, Collection<Parameter<?>> parameters) {
return new InstructionType<>(display, executionFactory, returnType, List.copyOf(parameters)); return new InstructionType<>(display, executionFactory, returnType, List.copyOf(parameters));
} }
public static <R> InstructionType<R> create(GuiDisplay display, Supplier<InstructionExecution<R>> executionFactory, ValueType<R> returnType, Parameter<?>... parameters) { public static <Return,R extends InstructionRuntime<R>> InstructionType<Return,R> create(GuiDisplay display, Supplier<InstructionExecution<Return,R>> executionFactory, ValueType<Return> returnType, Parameter<?>... parameters) {
return new InstructionType<>(display, executionFactory, returnType, List.of(parameters)); return new InstructionType<>(display, executionFactory, returnType, List.of(parameters));
} }
@@ -36,7 +39,7 @@ public final class InstructionType<R> {
return parameters; return parameters;
} }
public ValueType<R> getReturnType() { public ValueType<Return> getReturnType() {
return returnType; return returnType;
} }
@@ -44,14 +47,14 @@ public final class InstructionType<R> {
return display; return display;
} }
public InstructionExecution<R> createExecution(ArgumentList parameters, MinionFakePlayer minion) { public InstructionExecution<Return,R> createExecution(ArgumentList<R> parameters, R minion) {
InstructionExecution<R> execution = executionFactory.get(); InstructionExecution<Return,R> execution = executionFactory.get();
execution.readArguments(parameters, minion); execution.readArguments(parameters, minion);
return execution; return execution;
} }
public InstructionExecution<R> loadExecution(ReadView view, MinionFakePlayer minion) { public InstructionExecution<Return,R> loadExecution(ReadView view, R minion) {
InstructionExecution<R> execution = executionFactory.get(); InstructionExecution<Return,R> execution = executionFactory.get();
execution.load(view, minion); execution.load(view, minion);
return execution; return execution;
} }
@@ -4,6 +4,7 @@ import io.github.skippyall.minions.MinionRegistries;
import io.github.skippyall.minions.Minions; import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.gui.GuiDisplay; import io.github.skippyall.minions.gui.GuiDisplay;
import io.github.skippyall.minions.minion.fakeplayer.EntityPlayerActionPack; 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.ActionExecution;
import io.github.skippyall.minions.program.instruction.execution.WalkExecution; import io.github.skippyall.minions.program.instruction.execution.WalkExecution;
import io.github.skippyall.minions.program.argument.Parameter; import io.github.skippyall.minions.program.argument.Parameter;
@@ -18,7 +19,7 @@ import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
public class Instructions { public class Instructions {
public static final InstructionType<Void> WALK = register( public static final InstructionType<Void, MinionFakePlayer> WALK = register(
"walk", "walk",
base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_BOOTS), base, true), base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_BOOTS), base, true),
WalkExecution::new, WalkExecution::new,
@@ -26,21 +27,21 @@ public class Instructions {
WalkExecution.blocksToMoveParam WalkExecution.blocksToMoveParam
); );
public static final InstructionType<Void> ATTACK = register( public static final InstructionType<Void, MinionFakePlayer> ATTACK = register(
"attack", "attack",
base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_BOOTS), base, true), base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_BOOTS), base, true),
() -> new ActionExecution(EntityPlayerActionPack.ActionType.ATTACK), () -> new ActionExecution(EntityPlayerActionPack.ActionType.ATTACK),
ValueTypes.VOID ValueTypes.VOID
); );
public static final InstructionType<Void> USE = register( public static final InstructionType<Void, MinionFakePlayer> USE = register(
"use", "use",
base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.LEVER), base, true), base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.LEVER), base, true),
() -> new ActionExecution(EntityPlayerActionPack.ActionType.USE), () -> new ActionExecution(EntityPlayerActionPack.ActionType.USE),
ValueTypes.VOID ValueTypes.VOID
); );
private static <R> InstructionType<R> register(String id, Function<String, GuiDisplay> displayFunction, Supplier<InstructionExecution<R>> factory, ValueType<R> returnType, Parameter<?>... parameters) { private static <R> InstructionType<R, MinionFakePlayer> register(String id, Function<String, GuiDisplay> displayFunction, Supplier<InstructionExecution<R,MinionFakePlayer>> factory, ValueType<R> returnType, Parameter<?>... parameters) {
Identifier identifier = Identifier.of(Minions.MOD_ID, id); 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)); return Registry.register(MinionRegistries.INSTRUCTION_TYPES, identifier, InstructionType.create(displayFunction.apply(identifier.toTranslationKey("instruction_type")), factory, returnType, parameters));
} }
@@ -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.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.program.instruction.InstructionExecution; import io.github.skippyall.minions.program.instruction.InstructionExecution;
public interface ContinuousInstructionExecution extends InstructionExecution<Void> { public interface ContinuousInstructionExecution extends InstructionExecution<Void,MinionFakePlayer> {
@Override @Override
default boolean isDone(MinionFakePlayer minion) { default boolean isDone(MinionFakePlayer minion) {
return false; return false;
@@ -10,7 +10,7 @@ import net.minecraft.storage.WriteView;
* The timer must be set with <code>setTimer</code> when reading from parameters. * The timer must be set with <code>setTimer</code> when reading from parameters.
* Saving and loading of the timer is automatic if the super method is called by the subclass. * Saving and loading of the timer is automatic if the super method is called by the subclass.
*/ */
public abstract class TimedInstructionExecution<T> implements InstructionExecution<T> { public abstract class TimedInstructionExecution<T> implements InstructionExecution<T,MinionFakePlayer> {
int timer; int timer;
public int getTimer() { public int getTimer() {
@@ -14,7 +14,7 @@ import net.minecraft.util.StringIdentifiable;
import java.util.UUID; import java.util.UUID;
public class TurnExecution implements InstructionExecution<Void> { public class TurnExecution implements InstructionExecution<Void,MinionFakePlayer> {
public static final Parameter<Float> ANGLE = new Parameter<>("maxAngle", ValueTypes.FLOAT); public static final Parameter<Float> ANGLE = new Parameter<>("maxAngle", ValueTypes.FLOAT);
public static final Parameter<TurnDirection> DIRECTION = new Parameter<>("direction", ValueTypes.TURN_DIRECTION); public static final Parameter<TurnDirection> DIRECTION = new Parameter<>("direction", ValueTypes.TURN_DIRECTION);
@@ -43,7 +43,7 @@ public class TurnExecution implements InstructionExecution<Void> {
} }
@Override @Override
public void readArguments(ArgumentList arguments, MinionFakePlayer minion) { public void readArguments(ArgumentList<MinionFakePlayer> arguments, MinionFakePlayer minion) {
maxAngle = arguments.getValue(ANGLE, minion); maxAngle = arguments.getValue(ANGLE, minion);
direction = arguments.getValue(DIRECTION, minion); direction = arguments.getValue(DIRECTION, minion);
} }
@@ -9,7 +9,7 @@ import net.minecraft.entity.MovementType;
import net.minecraft.storage.ReadView; import net.minecraft.storage.ReadView;
import net.minecraft.storage.WriteView; import net.minecraft.storage.WriteView;
public class WalkExecution implements InstructionExecution<Void> { public class WalkExecution implements InstructionExecution<Void,MinionFakePlayer> {
public static final Parameter<Float> blocksToMoveParam = new Parameter<>("blocksToMove", ValueTypes.FLOAT); public static final Parameter<Float> blocksToMoveParam = new Parameter<>("blocksToMove", ValueTypes.FLOAT);
private final float ACCURACY = 1F / 32F; private final float ACCURACY = 1F / 32F;
@@ -34,7 +34,7 @@ public class WalkExecution implements InstructionExecution<Void> {
} }
@Override @Override
public void readArguments(ArgumentList parameters, MinionFakePlayer minion) { public void readArguments(ArgumentList<MinionFakePlayer> parameters, MinionFakePlayer minion) {
totalBlocksToMove = parameters.getValue(blocksToMoveParam, minion); totalBlocksToMove = parameters.getValue(blocksToMoveParam, minion);
blocksMoved = 0; blocksMoved = 0;
} }
@@ -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<R extends InstructionRuntime<R>> {
default <V> SpecificValueConsumerType<V, ? extends ValueConsumer<V, ?, R>, R> createTypeSpecific(ValueType<V> valueType) {
return createTypeSpecific(valueType, this);
}
<V> SpecificValueConsumerType<V, ? extends Argument<V, ?, R>, R> createTypeSpecific(ValueType<V> valueType, GenericValueConsumerType<R> me);
default boolean canCreate(ValueType<?> valueType) {
return true;
}
}
@@ -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<R extends InstructionRuntime<R>> {
private final Map<String, ValueConsumer<?, ?, R>> arguments;
public ReturnValueList() {
arguments = new HashMap<>();
}
public ReturnValueList(Map<String, ValueConsumer<?,?, R>> arguments) {
this.arguments = new HashMap<>(arguments);
}
public <T> T getValue(Parameter<T> parameter, R runtime) {
Argument<T,?,R> argument = getArgument(parameter);
return argument != null ? argument.resolve(runtime) : null;
}
public <T, A extends Argument<T, ? extends SpecificArgumentType<T,A,R>,R>> A getArgument(Parameter<T> parameter) {
Argument<?, ?,R> argument = arguments.get(parameter.name());
return argument == null ? null : argument.cast(parameter.type());
}
public <T> void setArgument(Parameter<T> parameter, Argument<T,?,R> argument) {
arguments.put(parameter.name(), argument);
}
public boolean hasArgumentFor(Parameter<?> parameter) {
return getArgument(parameter) != null;
}
public boolean hasArgumentForAll(Collection<Parameter<?>> checkParameters) {
for(Parameter<?> parameter : checkParameters) {
if(!hasArgumentFor(parameter)) {
return false;
}
}
return true;
}
public static <R extends InstructionRuntime<R>> Codec<ReturnValueList<R>> getCodec(Codec<GenericArgumentType<R>> genericCodec) {
return Codec.unboundedMap(Codec.STRING, Arguments.createArgumentCodec(genericCodec))
.xmap(ReturnValueList::new, list -> list.arguments);
}
}
@@ -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;
/**
* <code>SpecificArgumentType</code>s create <code>Argument</code>s of the specified <code>ValueType</code>.
* They are also responsible for the serialization and user input of arguments.
* @param <V> The value type of the <code>Argument</code>s to create
* @param <A> The type of the <code>Argument</code>s themselves
*/
public abstract class SpecificValueConsumerType<V, A extends ValueConsumer<V, ? extends SpecificValueConsumerType<V, A, R>, R>, R extends InstructionRuntime<R>> {
public final ValueType<V> valueType;
public final GenericArgumentType<R> genericType;
public SpecificValueConsumerType(ValueType<V> valueType, GenericArgumentType<R> genericType) {
this.valueType = valueType;
this.genericType = genericType;
}
public abstract Codec<A> getValueConsumerCodec();
public abstract CompletableFuture<A> openValueConsumerDialog(ServerPlayerEntity player, @Nullable A previousArgument);
public ValueType<V> getValueType() {
return valueType;
}
public GenericArgumentType<R> getGenericArgumentType() {
return genericType;
}
}
@@ -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 <code>Argument</code> can be supplied to an instruction with a matching parameter.
* Its value is resolved at runtime and can vary between executions.
* <code>Argument</code>s are created exclusively by <code>SpecificArgumentType</code>s.
* @param <T> The type of the <code>Argument</code>'s value
* @param <S> The <code>SpecificArgumentType</code>
*/
public interface ValueConsumer<T, S extends SpecificValueConsumerType<T, ? extends ValueConsumer<T, S, R>, R>, R extends InstructionRuntime<R>> {
void consume(T value, R runtime);
default ValueType<T> getValueType() {
return getType().getValueType();
}
GuiDisplay getDisplay();
S getType();
default <U, A extends io.github.skippyall.minions.program.argument.Argument<U, ? extends SpecificArgumentType<U,A,R>, R>> @Nullable A cast(ValueType<U> type) {
if(getValueType() == type) {
//noinspection unchecked
return (A) this;
} else {
return null;
}
}
}