Moving and stopping

This commit is contained in:
skippyall
2025-09-13 02:02:56 +02:00
parent b6f7bfc57b
commit bcfb406547
31 changed files with 415 additions and 115 deletions
@@ -2,9 +2,9 @@ package io.github.skippyall.minions;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import io.github.skippyall.minions.minion.skin.SkinProvider; import io.github.skippyall.minions.minion.skin.SkinProvider;
import io.github.skippyall.minions.new_program.argument.GenericArgumentType; import io.github.skippyall.minions.program.argument.GenericArgumentType;
import io.github.skippyall.minions.new_program.instruction.InstructionType; import io.github.skippyall.minions.program.instruction.InstructionType;
import io.github.skippyall.minions.new_program.value.ValueType; import io.github.skippyall.minions.program.value.ValueType;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.SimpleRegistry; import net.minecraft.registry.SimpleRegistry;
@@ -1,23 +1,16 @@
package io.github.skippyall.minions; package io.github.skippyall.minions;
import eu.pb4.polymer.core.api.entity.PolymerEntityUtils;
import io.github.skippyall.minions.command.MinionsCommand; import io.github.skippyall.minions.command.MinionsCommand;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.minion.MinionData; import io.github.skippyall.minions.minion.MinionData;
import io.github.skippyall.minions.minion.MinionPersistentState; import io.github.skippyall.minions.minion.MinionPersistentState;
import io.github.skippyall.minions.minion.skin.SkinProviders; import io.github.skippyall.minions.minion.skin.SkinProviders;
import io.github.skippyall.minions.mixins.PlayerListEntryS2CPacket$EntryMixin; import io.github.skippyall.minions.module.MinionModule;
import io.github.skippyall.minions.new_module.MinionModule; import io.github.skippyall.minions.program.instruction.Instructions;
import io.github.skippyall.minions.new_module.ModuleLoader; import io.github.skippyall.minions.program.value.ValueTypes;
import io.github.skippyall.minions.new_program.instruction.Instructions;
import io.github.skippyall.minions.new_program.value.ValueTypes;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.resource.ResourceType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -50,7 +43,5 @@ public class Minions implements ModInitializer {
SkinProviders.register(); SkinProviders.register();
MinionItems.register(); MinionItems.register();
MinionCreativeTab.registerGroup(); MinionCreativeTab.registerGroup();
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(new ModuleLoader());
} }
} }
@@ -0,0 +1,226 @@
package io.github.skippyall.minions.gui;
import eu.pb4.sgui.api.elements.GuiElementBuilder;
import eu.pb4.sgui.api.gui.SimpleGui;
import io.github.skippyall.minions.MinionRegistries;
import io.github.skippyall.minions.input.TextInput;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.module.MinionModule;
import io.github.skippyall.minions.program.argument.Argument;
import io.github.skippyall.minions.program.argument.GenericArgumentType;
import io.github.skippyall.minions.program.argument.SpecificArgumentType;
import io.github.skippyall.minions.program.instruction.ConfiguredInstruction;
import io.github.skippyall.minions.program.instruction.InstructionType;
import io.github.skippyall.minions.program.argument.Parameter;
import io.github.skippyall.minions.util.TranslationUtil;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.CompletableFuture;
public class InstructionGui {
public static void openInstructionMainMenu(MinionFakePlayer minion, ServerPlayerEntity player) {
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_3X3, player, false);
gui.setSlot(3, new GuiElementBuilder()
.setItem(Items.BOOK)
.setName(Text.literal("Instruction List"))
.setCallback(() -> instructionList(minion, player))
);
gui.setSlot(5, new GuiElementBuilder()
.setItem(Items.WRITABLE_BOOK)
.setName(Text.literal("New Instruction"))
.setCallback(() -> createNewInstruction(minion, player))
);
gui.open();
}
public static void instructionList(MinionFakePlayer minion, ServerPlayerEntity player) {
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
for(String instructionName : minion.getInstructionManager().getInstructionNames()) {
ConfiguredInstruction<?> instruction = minion.getInstructionManager().getInstruction(instructionName);
gui.addSlot(instruction.getInstruction().getDisplay().createElement()
.setName(Text.literal(instructionName))
.setLore(List.of())
.setCallback(() -> configureInstructionMenu(instructionName, instruction, minion, player))
);
}
gui.open();
}
public static void createNewInstruction(MinionFakePlayer minion, ServerPlayerEntity player) {
selectInstructionModuleMenu(minion, player).thenAccept(instructionType ->
TextInput.inputString(player, Text.translatable("minions.gui.instruction.enter_name"), "Instruction").thenAccept(name -> {
ConfiguredInstruction<?> configuredInstruction = minion.getInstructionManager().createInstruction(name, instructionType);
configureInstructionMenu(name, configuredInstruction, minion, player);
})
);
}
public static boolean checkInstructionExists(String name, ConfiguredInstruction<?> instruction, MinionFakePlayer minion, ServerPlayerEntity player) {
boolean stillExists = minion.getInstructionManager().getInstruction(name) == instruction;
if(!stillExists) {
player.closeHandledScreen();
player.sendMessage(Text.translatable("minions.gui.instruction.removed"));
}
return stillExists;
}
public static void configureInstructionMenu(String name, ConfiguredInstruction<?> instruction, MinionFakePlayer minion, ServerPlayerEntity player) {
if(!checkInstructionExists(name, instruction, minion, player)) {
return;
}
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
gui.setSlot(12, createInstructionElement(instruction.getInstruction()));
int slot = 13;
for(Parameter<?> parameter : instruction.getInstruction().getParameters()) {
gui.setSlot(slot, createArgumentElement(instruction.getArguments().getArgument(parameter))
.setCallback(() -> configureArgumentMenu(name, instruction, parameter, minion, player))
);
slot++;
}
updateRunSlot(instruction, minion, gui);
gui.open();
}
private static void updateRunSlot(ConfiguredInstruction<?> instruction, MinionFakePlayer minion, SimpleGui gui) {
if(!instruction.isRunning()) {
gui.setSlot(26, new GuiElementBuilder(Items.ARROW)
.setName(Text.literal("Run"))
.setCallback(() -> {
instruction.run(minion);
updateRunSlot(instruction, minion, gui);
})
);
} else {
gui.setSlot(26, new GuiElementBuilder(Items.BARRIER)
.setName(Text.literal("Stop"))
.setCallback(() -> {
instruction.stop(minion);
updateRunSlot(instruction, minion, gui);
})
);
}
}
public static <T, A extends Argument<T, ? extends SpecificArgumentType<T, A>>> void configureArgumentMenu(String name, ConfiguredInstruction<?> instruction, Parameter<T> parameter, MinionFakePlayer minion, ServerPlayerEntity player) {
if(!checkInstructionExists(name, instruction, minion, player)) {
return;
}
A argument = instruction.getArguments().getArgument(parameter);
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_3X3, player, false);
gui.setSlot(3, new GuiElementBuilder(Items.STICK)
.setName(Text.literal("Type: " + (argument == null ? "Unset" : MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY.getId(argument.getType().getGenericArgumentType()).getPath())))
.setCallback(() -> selectArgumentType(player)
.thenApply(type -> type.<T>createTypeSpecific(parameter.type()).openArgumentDialog(player, null)
.thenAccept(newArgument -> {
instruction.getArguments().setArgument(parameter, newArgument);
configureArgumentMenu(name, instruction, parameter, minion, player);
})
)
)
);
if(argument != null) {
gui.setSlot(5, new GuiElementBuilder(Items.STRUCTURE_VOID)
.setName(Text.literal("Configure"))
.setCallback(() -> argument.getType().openArgumentDialog(player, argument)
.thenAccept(newArgument -> instruction.getArguments().setArgument(parameter, newArgument))
)
);
}
gui.open();
}
public static CompletableFuture<GenericArgumentType> selectArgumentType(ServerPlayerEntity player) {
CompletableFuture<GenericArgumentType> future = new CompletableFuture<>();
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
for(GenericArgumentType type : MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY) {
gui.addSlot(new GuiElementBuilder()
.setName(Text.translatable(TranslationUtil.getTranslationKey(type, MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY)))
.setCallback(() -> future.complete(type))
);
}
gui.open();
return future;
}
public static CompletableFuture<InstructionType<?>> selectInstructionModuleMenu(MinionFakePlayer minion, ServerPlayerEntity player) {
if(minion.getModuleInventory().getModules().isEmpty()) {
player.sendMessage(Text.literal("This minion has no modules"));
return CompletableFuture.failedFuture(new NoSuchElementException("No modules"));
}
CompletableFuture<InstructionType<?>> future = new CompletableFuture<>();
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false) {
@Override
public void onClose() {
if(!future.isDone()) {
future.cancel(false);
}
}
};
for(int i = 0; i < minion.getModuleInventory().size(); i++) {
ItemStack module = minion.getModuleInventory().getStack(i);
if(module.contains(MinionModule.COMPONENT_TYPE)) {
gui.addSlot(new GuiElementBuilder(module)
.setCallback(() -> selectInstructionMenu(module.get(MinionModule.COMPONENT_TYPE), minion, player)
.thenApply(future::complete)
)
);
}
}
gui.open();
return future;
}
public static CompletableFuture<InstructionType<?>> selectInstructionMenu(MinionModule module, MinionFakePlayer minion, ServerPlayerEntity player) {
CompletableFuture<InstructionType<?>> future = new CompletableFuture<>();
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
for(InstructionType<?> instructionType : module.instructions()) {
gui.addSlot(createInstructionElement(instructionType)
.setCallback(() -> future.complete(instructionType))
);
}
gui.open();
return future;
}
public static GuiElementBuilder createInstructionElement(InstructionType<?> instructionType) {
GuiElementBuilder instructionBuilder;
if(instructionType != null) {
instructionBuilder = instructionType.getDisplay().createElement();
} else {
instructionBuilder = new GuiElementBuilder(Items.RED_WOOL)
.setName(Text.translatable("minions.gui.instruction.no_instruction_set"));
}
return instructionBuilder;
}
public static GuiElementBuilder createArgumentElement(Argument<?,?> argument) {
GuiElementBuilder argumentBuilder;
if(argument != null) {
argumentBuilder = argument.getDisplay().createElement();
} else {
argumentBuilder = new GuiElementBuilder(Items.RED_WOOL)
.setName(Text.translatable("minions.gui.instruction.no_argument_set"));
}
return argumentBuilder;
}
}
@@ -3,6 +3,7 @@ package io.github.skippyall.minions.gui;
import eu.pb4.sgui.api.elements.GuiElementBuilder; import eu.pb4.sgui.api.elements.GuiElementBuilder;
import eu.pb4.sgui.api.gui.SimpleGui; import eu.pb4.sgui.api.gui.SimpleGui;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.module.ModuleInventory;
import net.minecraft.item.Items; import net.minecraft.item.Items;
import net.minecraft.screen.ScreenHandlerType; import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.Slot;
@@ -2,8 +2,8 @@ package io.github.skippyall.minions.minion;
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.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.new_program.instruction.ConfiguredInstruction; import io.github.skippyall.minions.program.instruction.ConfiguredInstruction;
import io.github.skippyall.minions.new_program.instruction.InstructionType; import io.github.skippyall.minions.program.instruction.InstructionType;
import net.minecraft.storage.ReadView; import net.minecraft.storage.ReadView;
import net.minecraft.storage.WriteView; import net.minecraft.storage.WriteView;
@@ -46,6 +46,10 @@ public class MinionInstructionManager {
return configuredInstructions.get(name); return configuredInstructions.get(name);
} }
public boolean hasInstruction(String name) {
return configuredInstructions.containsKey(name);
}
public void save(WriteView view) { public void save(WriteView view) {
WriteView.ListView list = view.getList("configuredInstructions"); WriteView.ListView list = view.getList("configuredInstructions");
for (Map.Entry<String, ConfiguredInstruction<?>> instruction : configuredInstructions.entrySet()) { for (Map.Entry<String, ConfiguredInstruction<?>> instruction : configuredInstructions.entrySet()) {
@@ -10,7 +10,7 @@ import io.github.skippyall.minions.minion.MinionInstructionManager;
import io.github.skippyall.minions.minion.MinionItem; import io.github.skippyall.minions.minion.MinionItem;
import io.github.skippyall.minions.minion.MinionPersistentState; import io.github.skippyall.minions.minion.MinionPersistentState;
import io.github.skippyall.minions.minion.MinionProfileUtils; import io.github.skippyall.minions.minion.MinionProfileUtils;
import io.github.skippyall.minions.gui.ModuleInventory; import io.github.skippyall.minions.module.ModuleInventory;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.EquipmentSlot;
@@ -1,15 +1,14 @@
package io.github.skippyall.minions.new_module; package io.github.skippyall.minions.module;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import eu.pb4.polymer.core.api.other.PolymerComponent; import eu.pb4.polymer.core.api.other.PolymerComponent;
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.new_program.instruction.InstructionType; import io.github.skippyall.minions.program.instruction.InstructionType;
import net.minecraft.component.ComponentType; import net.minecraft.component.ComponentType;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import java.util.List; import java.util.List;
@@ -21,9 +20,7 @@ public record MinionModule(List<InstructionType<?>> instructions) {
).apply(instance, MinionModule::new) ).apply(instance, MinionModule::new)
); );
public static final Codec<MinionModule> DATAPACK_CODEC = Codec.withAlternative(Identifier.CODEC.xmap(ModuleLoader.MODULES::get, ModuleLoader.ID_BY_MODULE::get), CODEC); public static final ComponentType<MinionModule> COMPONENT_TYPE = ComponentType.<MinionModule>builder().codec(CODEC).build();
public static final ComponentType<MinionModule> COMPONENT_TYPE = ComponentType.<MinionModule>builder().codec(DATAPACK_CODEC).build();
public static final MinionModule EMPTY = new MinionModule(List.of()); public static final MinionModule EMPTY = new MinionModule(List.of());
@@ -1,8 +1,7 @@
package io.github.skippyall.minions.gui; package io.github.skippyall.minions.module;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.new_module.MinionModule; import io.github.skippyall.minions.program.instruction.InstructionType;
import io.github.skippyall.minions.new_program.instruction.InstructionType;
import net.minecraft.inventory.Inventories; import net.minecraft.inventory.Inventories;
import net.minecraft.inventory.SimpleInventory; import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -1,4 +1,4 @@
package io.github.skippyall.minions.gui; package io.github.skippyall.minions.module;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
@@ -1,30 +0,0 @@
package io.github.skippyall.minions.new_module;
import com.mojang.serialization.JsonOps;
import io.github.skippyall.minions.Minions;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.resource.JsonDataLoader;
import net.minecraft.resource.ResourceFinder;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import java.util.HashMap;
import java.util.Map;
public class ModuleLoader implements SimpleSynchronousResourceReloadListener {
public static final HashMap<MinionModule, Identifier> ID_BY_MODULE = new HashMap<>();
public static final Map<Identifier, MinionModule> MODULES = new HashMap<>();
@Override
public Identifier getFabricId() {
return Identifier.of(Minions.MOD_ID, "module");
}
@Override
public void reload(ResourceManager manager) {
MODULES.clear();
ID_BY_MODULE.clear();
JsonDataLoader.load(manager, ResourceFinder.json("minion_module"), JsonOps.INSTANCE, MinionModule.CODEC, MODULES);
MODULES.forEach((id, module) -> ID_BY_MODULE.put(module, id));
}
}
@@ -1,8 +1,8 @@
package io.github.skippyall.minions.new_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.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.new_program.value.ValueType; import io.github.skippyall.minions.program.value.ValueType;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/** /**
@@ -1,4 +1,4 @@
package io.github.skippyall.minions.new_program.argument; package io.github.skippyall.minions.program.argument;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
@@ -1,13 +1,9 @@
package io.github.skippyall.minions.new_program.argument; package io.github.skippyall.minions.program.argument;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.Lifecycle;
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.new_program.value.ValueType;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.SimpleRegistry;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
public class Arguments { public class Arguments {
@@ -1,6 +1,6 @@
package io.github.skippyall.minions.new_program.argument; package io.github.skippyall.minions.program.argument;
import io.github.skippyall.minions.new_program.value.ValueType; import io.github.skippyall.minions.program.value.ValueType;
public interface GenericArgumentType { public interface GenericArgumentType {
<V> SpecificArgumentType<V, ? extends Argument<V,?>> createTypeSpecific(ValueType<V> valueType); <V> SpecificArgumentType<V, ? extends Argument<V,?>> createTypeSpecific(ValueType<V> valueType);
@@ -1,9 +1,9 @@
package io.github.skippyall.minions.new_program.argument; package io.github.skippyall.minions.program.argument;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.github.skippyall.minions.MinionRegistries; import io.github.skippyall.minions.MinionRegistries;
import io.github.skippyall.minions.new_program.value.ValueType; import io.github.skippyall.minions.program.value.ValueType;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public record Parameter<T>(String name, ValueType<T> type) { public record Parameter<T>(String name, ValueType<T> type) {
@@ -1,7 +1,7 @@
package io.github.skippyall.minions.new_program.argument; package io.github.skippyall.minions.program.argument;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import io.github.skippyall.minions.new_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;
@@ -1,8 +1,7 @@
package io.github.skippyall.minions.new_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.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.new_program.value.ValueType;
/** /**
* An argument that always resolves to a fixed value * An argument that always resolves to a fixed value
@@ -1,7 +1,7 @@
package io.github.skippyall.minions.new_program.argument; package io.github.skippyall.minions.program.argument;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import io.github.skippyall.minions.new_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;
@@ -0,0 +1,113 @@
package io.github.skippyall.minions.program.instruction;
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.argument.ArgumentList;
import net.minecraft.storage.ReadView;
import net.minecraft.storage.WriteView;
import org.jetbrains.annotations.Nullable;
public class ConfiguredInstruction<R> {
private final InstructionType<R> instruction;
private final ArgumentList arguments;
private @Nullable InstructionExecution<R> execution;
private final String name;
private ConfiguredInstruction(InstructionType<R> instruction, ArgumentList arguments, @Nullable InstructionExecution<R> execution, String name) {
this.instruction = instruction;
this.arguments = arguments;
this.execution = execution;
this.name = name;
}
public ConfiguredInstruction(InstructionType<R> instruction, String name) {
this(instruction, new ArgumentList(), null, name);
}
public InstructionType<R> getInstruction() {
return instruction;
}
public ArgumentList getArguments() {
return arguments;
}
public String getName() {
return name;
}
public boolean canRun() {
return instruction != null && arguments != null && arguments.hasArgumentForAll(instruction.getParameters());
}
public boolean isRunning() {
return execution != null;
}
public @Nullable InstructionExecution<R> getExecution() {
return execution;
}
public void run(MinionFakePlayer minion) {
if(canRun() && !isRunning()) {
try {
execution = instruction.createExecution(arguments, minion);
execution.start(minion);
} catch (Exception e) {
Minions.LOGGER.error("An error occurred while executing configured Instruction {} of minion {}", name, minion.getGameProfile().getName(), e);
}
}
}
public void tick(MinionFakePlayer minion) {
if(isRunning()) {
if(execution.isDone(minion)) {
stop(minion);
} else {
execution.tick(minion);
if (execution.isDone(minion)) {
stop(minion);
}
}
}
}
public void stop(MinionFakePlayer minion) {
if(isRunning()) {
execution.stop(minion);
execution = null;
}
}
public void save(WriteView view, MinionFakePlayer minion) {
view.put("instruction", MinionRegistries.INSTRUCTION_TYPES.getCodec(), instruction);
view.put("arguments", ArgumentList.CODEC, arguments);
view.putBoolean("running", isRunning());
if(isRunning()) {
execution.save(view.get("execution"), minion);
}
}
public static <R> ConfiguredInstruction<R> load(ReadView view, MinionFakePlayer minion, String name) {
//noinspection unchecked
InstructionType<R> instructionType = (InstructionType<R>) view.read("instruction", MinionRegistries.INSTRUCTION_TYPES.getCodec()).orElseThrow();
ArgumentList arguments = view.read("arguments", ArgumentList.CODEC).orElseThrow();
boolean running = view.getBoolean("running", false);
if(running) {
ReadView executionView = view.getReadView("execution");
try {
InstructionExecution<R> execution = instructionType.loadExecution(executionView, minion);
return new ConfiguredInstruction<>(instructionType, arguments, execution, name);
} catch (Exception e) {
}
}
return new ConfiguredInstruction<>(instructionType, arguments, null, name);
}
}
@@ -1,7 +1,7 @@
package io.github.skippyall.minions.new_program.instruction; package io.github.skippyall.minions.program.instruction;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.new_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;
@@ -39,7 +39,7 @@ public interface InstructionExecution<R> {
* Stops this execution. This is guaranteed to be called if {@link InstructionExecution#isDone(MinionFakePlayer) isDone} * Stops this execution. This is guaranteed to be called if {@link InstructionExecution#isDone(MinionFakePlayer) isDone}
* returns true after ticking the execution, but it may also be called before that. * returns true after ticking the execution, but it may also be called before that.
* In this case, the return value is ignored unless this is a * In this case, the return value is ignored unless this is a
* {@link io.github.skippyall.minions.new_program.instruction.execution.ContinuousInstructionExecution ContinuousInstructionExecution}.</br> * {@link io.github.skippyall.minions.program.instruction.execution.ContinuousInstructionExecution ContinuousInstructionExecution}.</br>
* 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 minion The minion that was executing this instruction.
@@ -1,10 +1,10 @@
package io.github.skippyall.minions.new_program.instruction; 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.new_program.argument.Parameter; import io.github.skippyall.minions.program.argument.Parameter;
import io.github.skippyall.minions.new_program.argument.ArgumentList; import io.github.skippyall.minions.program.argument.ArgumentList;
import io.github.skippyall.minions.new_program.value.ValueType; import io.github.skippyall.minions.program.value.ValueType;
import net.minecraft.storage.ReadView; import net.minecraft.storage.ReadView;
import java.util.Collection; import java.util.Collection;
@@ -1,12 +1,14 @@
package io.github.skippyall.minions.new_program.instruction; package io.github.skippyall.minions.program.instruction;
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.gui.GuiDisplay; import io.github.skippyall.minions.gui.GuiDisplay;
import io.github.skippyall.minions.new_program.instruction.execution.WalkExecution; import io.github.skippyall.minions.minion.fakeplayer.EntityPlayerActionPack;
import io.github.skippyall.minions.new_program.argument.Parameter; import io.github.skippyall.minions.program.instruction.execution.ActionExecution;
import io.github.skippyall.minions.new_program.value.ValueType; import io.github.skippyall.minions.program.instruction.execution.WalkExecution;
import io.github.skippyall.minions.new_program.value.ValueTypes; import io.github.skippyall.minions.program.argument.Parameter;
import io.github.skippyall.minions.program.value.ValueType;
import io.github.skippyall.minions.program.value.ValueTypes;
import io.github.skippyall.minions.util.ModelIdUtil; import io.github.skippyall.minions.util.ModelIdUtil;
import net.minecraft.item.Items; import net.minecraft.item.Items;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
@@ -26,10 +28,16 @@ public class Instructions {
public static final InstructionType<Void> ATTACK = register( public static final InstructionType<Void> ATTACK = register(
"attack", "attack",
base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_PICKAXE), base, true), base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_BOOTS), base, true),
WalkExecution::new, () -> new ActionExecution(EntityPlayerActionPack.ActionType.ATTACK),
ValueTypes.VOID, ValueTypes.VOID
WalkExecution.blocksToMoveParam );
public static final InstructionType<Void> USE = register(
"use",
base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.LEVER), base, true),
() -> new ActionExecution(EntityPlayerActionPack.ActionType.USE),
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> register(String id, Function<String, GuiDisplay> displayFunction, Supplier<InstructionExecution<R>> factory, ValueType<R> returnType, Parameter<?>... parameters) {
@@ -1,8 +1,8 @@
package io.github.skippyall.minions.new_program.instruction.execution; package io.github.skippyall.minions.program.instruction.execution;
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.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.new_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;
@@ -1,7 +1,7 @@
package io.github.skippyall.minions.new_program.instruction.execution; 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.new_program.instruction.InstructionExecution; import io.github.skippyall.minions.program.instruction.InstructionExecution;
public interface ContinuousInstructionExecution<R> extends InstructionExecution<R> { public interface ContinuousInstructionExecution<R> extends InstructionExecution<R> {
@Override @Override
@@ -1,7 +1,7 @@
package io.github.skippyall.minions.new_program.instruction.execution; 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.new_program.instruction.InstructionExecution; import io.github.skippyall.minions.program.instruction.InstructionExecution;
import net.minecraft.storage.ReadView; import net.minecraft.storage.ReadView;
import net.minecraft.storage.WriteView; import net.minecraft.storage.WriteView;
@@ -1,9 +1,9 @@
package io.github.skippyall.minions.new_program.instruction.execution; package io.github.skippyall.minions.program.instruction.execution;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.new_program.argument.ArgumentList; import io.github.skippyall.minions.program.argument.ArgumentList;
import io.github.skippyall.minions.new_program.instruction.InstructionExecution; import io.github.skippyall.minions.program.instruction.InstructionExecution;
import net.minecraft.storage.ReadView; import net.minecraft.storage.ReadView;
import net.minecraft.storage.WriteView; import net.minecraft.storage.WriteView;
import net.minecraft.util.StringIdentifiable; import net.minecraft.util.StringIdentifiable;
@@ -1,10 +1,10 @@
package io.github.skippyall.minions.new_program.instruction.execution; 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.new_program.instruction.InstructionExecution; import io.github.skippyall.minions.program.instruction.InstructionExecution;
import io.github.skippyall.minions.new_program.argument.Parameter; import io.github.skippyall.minions.program.argument.Parameter;
import io.github.skippyall.minions.new_program.argument.ArgumentList; import io.github.skippyall.minions.program.argument.ArgumentList;
import io.github.skippyall.minions.new_program.value.ValueTypes; import io.github.skippyall.minions.program.value.ValueTypes;
import net.minecraft.entity.MovementType; 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;
@@ -1,4 +1,4 @@
package io.github.skippyall.minions.new_program.value; package io.github.skippyall.minions.program.value;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import io.github.skippyall.minions.gui.GuiDisplay; import io.github.skippyall.minions.gui.GuiDisplay;
@@ -1,4 +1,4 @@
package io.github.skippyall.minions.new_program.value; package io.github.skippyall.minions.program.value;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import io.github.skippyall.minions.MinionRegistries; import io.github.skippyall.minions.MinionRegistries;
@@ -17,6 +17,8 @@
"minions.gui.look.rename.title": "Enter a name", "minions.gui.look.rename.title": "Enter a name",
"minions.gui.instruction.no_instruction_set": "No instruction set", "minions.gui.instruction.no_instruction_set": "No instruction set",
"minions.gui.instruction.enter_name": "Enter a name", "minions.gui.instruction.enter_name": "Enter a name",
"minions.gui.instruction.removed": "This instruction no longer exists",
"minions.gui.instruction.no_argument_set": "No argument set",
"minions.command.input.int.fail": "Not an integer", "minions.command.input.int.fail": "Not an integer",
"minions.command.input.float.fail": "Not a number", "minions.command.input.float.fail": "Not a number",
@@ -48,6 +50,5 @@
"minions.generic.name.invalid": "Name is invalid", "minions.generic.name.invalid": "Name is invalid",
"minions.generic.name.taken": "This name is already used", "minions.generic.name.taken": "This name is already used",
"minions.generic.mod_name": "Minions", "minions.generic.mod_name": "Minions",
"minions.generic.unknown": "Unknown", "minions.generic.unknown": "Unknown"
"minions.gui.instruction.no_argument_set": "No argument set"
} }
@@ -1,5 +0,0 @@
{
"instructions": [
"minions:walk"
]
}