MinionTriggerBlock & More GUI

This commit is contained in:
skippyall
2025-12-09 20:00:57 +01:00
parent b413592abf
commit c5b3c883ca
25 changed files with 282 additions and 181 deletions
+3 -1
View File
@@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '1.10-SNAPSHOT'
id 'net.fabricmc.fabric-loom-remap' version '1.14-SNAPSHOT'
id 'maven-publish'
}
@@ -40,6 +40,8 @@ repositories {
}
dependencies {
implementation 'org.jetbrains:annotations:15.0'
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
+1 -1
View File
@@ -1 +1 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
@@ -0,0 +1,11 @@
package io.github.skippyall.minions;
import net.fabricmc.fabric.api.attachment.v1.AttachmentRegistry;
import net.fabricmc.fabric.api.attachment.v1.AttachmentType;
import net.minecraft.util.Identifier;
import java.util.UUID;
public record PlayerClipboardAttachment(UUID selectedMinion, String selectedInstruction) {
public static final AttachmentType<PlayerClipboardAttachment> TYPE = AttachmentRegistry.create(Identifier.of(Minions.MOD_ID, "clipboard"));
}
@@ -3,32 +3,58 @@ package io.github.skippyall.minions.block;
import com.mojang.serialization.MapCodec;
import eu.pb4.polymer.core.api.block.PolymerBlock;
import io.github.skippyall.minions.MinionRegistration;
import io.github.skippyall.minions.PlayerClipboardAttachment;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.BlockWithEntity;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.util.ActionResult;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.block.WireOrientation;
import org.jetbrains.annotations.Nullable;
import xyz.nucleoid.packettweaker.PacketContext;
import java.util.Optional;
public class MinionTriggerBlock extends BlockWithEntity implements PolymerBlock {
public static final MapCodec<MinionTriggerBlock> CODEC = createCodec(MinionTriggerBlock::new);
public static final BooleanProperty POWERED = BooleanProperty.of("powered");
public static final BooleanProperty RUNNING = BooleanProperty.of("running");
public MinionTriggerBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(POWERED, false));
setDefaultState(getDefaultState().with(POWERED, false).with(RUNNING, false));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(POWERED);
builder.add(POWERED, RUNNING);
}
@Override
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
PlayerClipboardAttachment clipboard = player.getAttached(PlayerClipboardAttachment.TYPE);
if(clipboard != null) {
Optional<MinionTriggerBlockEntity> be = world.getBlockEntity(pos, MinionRegistration.MINION_TRIGGER_BE_TYPE);
if(be.isPresent()) {
be.get().setInstruction(clipboard.selectedMinion(), clipboard.selectedInstruction());
player.playSoundToPlayer(SoundEvents.BLOCK_NOTE_BLOCK_CHIME.value(), SoundCategory.BLOCKS, 1, 1);
return ActionResult.SUCCESS;
}
}
return ActionResult.PASS;
}
@Override
@@ -64,4 +90,13 @@ public class MinionTriggerBlock extends BlockWithEntity implements PolymerBlock
public BlockState getPolymerBlockState(BlockState state, PacketContext context) {
return state.get(POWERED) ? Blocks.REDSTONE_BLOCK.getDefaultState() : Blocks.GOLD_BLOCK.getDefaultState();
}
@Override
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
if(type == MinionRegistration.MINION_TRIGGER_BE_TYPE) {
return MinionTriggerBlockEntity::tick;
} else {
return null;
}
}
}
@@ -10,62 +10,80 @@ import net.minecraft.storage.ReadView;
import net.minecraft.storage.WriteView;
import net.minecraft.util.Uuids;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.Optional;
import java.util.UUID;
public class MinionTriggerBlockEntity extends BlockEntity {
private UUID minionUuid;
private String instructionName = "";
private boolean first = true;
private boolean runningCache = false;
public MinionTriggerBlockEntity(BlockPos pos, BlockState state) {
super(MinionRegistration.MINION_TRIGGER_BE_TYPE, pos, state);
}
public void updatePower() {
boolean powered = getCachedState().get(MinionTriggerBlock.POWERED);
ConfiguredInstruction<MinionRuntime> instruction = getInstruction();
public void setInstruction(UUID minionUuid, String instructionName) {
this.minionUuid = minionUuid;
this.instructionName = instructionName;
markDirty();
}
if(instruction != null) {
if(powered) {
instruction.run(getMinion().getInstructionManager());
} else {
instruction.stop(getMinion().getInstructionManager());
public static void tick(World world, BlockPos pos, BlockState state, BlockEntity blockEntity) {
if(!(blockEntity instanceof MinionTriggerBlockEntity triggerBlockEntity)) {
return;
}
if(triggerBlockEntity.first) {
triggerBlockEntity.first = false;
world.updateComparators(pos, MinionRegistration.MINION_TRIGGER_BLOCK);
triggerBlockEntity.runningCache = triggerBlockEntity.getInstruction().map(ConfiguredInstruction::isRunning).orElse(false);
} else {
boolean isRunning = triggerBlockEntity.getInstruction().map(ConfiguredInstruction::isRunning).orElse(false);
if (isRunning != triggerBlockEntity.runningCache) {
world.updateComparators(pos, MinionRegistration.MINION_TRIGGER_BLOCK);
triggerBlockEntity.runningCache = isRunning;
}
}
}
public void updatePower() {
boolean powered = getCachedState().get(MinionTriggerBlock.POWERED);
getMinion().ifPresent(minion -> {
getInstruction().ifPresent(instruction -> {
if(powered) {
instruction.run(minion.getInstructionManager());
} else {
instruction.stop(minion.getInstructionManager());
}
});
});
}
public int getComparatorOutput() {
ConfiguredInstruction<MinionRuntime> instruction = getInstruction();
if(instruction != null && instruction.isRunning()) {
Optional<ConfiguredInstruction<MinionRuntime>> instruction = getInstruction();
if(instruction.isPresent() && instruction.get().isRunning()) {
return 15;
}
return 0;
}
public MinionFakePlayer getMinion() {
public Optional<MinionFakePlayer> getMinion() {
if(minionUuid != null && world != null && world.getPlayerByUuid(minionUuid) instanceof MinionFakePlayer minion) {
return minion;
return Optional.of(minion);
}
return null;
return Optional.empty();
}
public ConfiguredInstruction<MinionRuntime> getInstruction() {
MinionFakePlayer minion = getMinion();
if(minion == null) {
return null;
}
return minion.getInstructionManager().getInstruction(instructionName);
public Optional<ConfiguredInstruction<MinionRuntime>> getInstruction(MinionFakePlayer minion) {
return Optional.ofNullable(minion.getInstructionManager().getInstruction(instructionName));
}
@Override
public void onBlockReplaced(BlockPos pos, BlockState oldState) {
super.onBlockReplaced(pos, oldState);
}
@Override
public void markRemoved() {
super.markRemoved();
public Optional<ConfiguredInstruction<MinionRuntime>> getInstruction() {
return getMinion().flatMap(this::getInstruction);
}
@Override
@@ -1,40 +0,0 @@
package io.github.skippyall.minions.gui;
public class CommandsGui {
/*public static void openServerModuleCommandGui(ServerPlayerEntity player, MinionFakePlayer minion) {
Collection<ModuleItem> modules = minion.getModuleInventory().getModules();
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
gui.setTitle(Text.translatable("minions.gui.module_commands.title"));
for (ModuleItem module : modules) {
gui.addSlot(new GuiElementBuilder()
.setItem(module.asItem())
.setCallback(() -> openServerCommandGui(player, minion, module))
);
}
gui.open();
}
public static void openServerCommandGui(ServerPlayerEntity player, MinionFakePlayer minion, ModuleItem module) {
List<Command> commands = module.getCommands();
SimpleGui commandGui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
commandGui.setTitle(Text.translatable("minions.gui.commands.title", module.asItem().getName()));
for(int j = 0; j < commands.size(); j++) {
Command command = commands.get(j);
commandGui.setSlot(j, new GuiElementBuilder()
.setItem(command.getItemRepresentation())
.setName(command.getName())
.addLoreLine(command.getDescription())
.setCallback(() -> command.execute(player, minion))
);
}
commandGui.open();
}*/
}
@@ -1,11 +1,8 @@
package io.github.skippyall.minions.gui;
import com.mojang.authlib.properties.PropertyMap;
import com.mojang.datafixers.util.Either;
import eu.pb4.sgui.api.elements.GuiElementBuilder;
import io.github.skippyall.minions.util.ModelIdUtil;
import net.minecraft.block.SkullBlock;
import net.minecraft.block.entity.SkullBlockEntity;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.LoreComponent;
import net.minecraft.component.type.ProfileComponent;
@@ -30,6 +27,10 @@ public interface GuiDisplay {
this(ModelIdUtil.getItemModelId(model), translationKeyBase, withLore);
}
public ModelBased(Item model, String translationKeyBase) {
this(ModelIdUtil.getItemModelId(model), translationKeyBase, false);
}
@Override
public ItemStack createItemStack() {
ItemStack stack = new ItemStack(Items.BARRIER);
@@ -3,7 +3,10 @@ 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.PlayerClipboardAttachment;
import io.github.skippyall.minions.gui.input.ChoiceInput;
import io.github.skippyall.minions.gui.input.Result;
import io.github.skippyall.minions.gui.input.TextInput;
import io.github.skippyall.minions.minion.MinionRuntime;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.module.MinionModule;
@@ -17,7 +20,10 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.NoSuchElementException;
@@ -28,12 +34,12 @@ public class InstructionGui {
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_3X3, player, false);
gui.setSlot(3, new GuiElementBuilder()
.setItem(Items.BOOK)
.setName(Text.literal("Instruction List"))
.setName(Text.translatable("minions.gui.instruction.list"))
.setCallback(() -> instructionList(minion, player))
);
gui.setSlot(5, new GuiElementBuilder()
.setItem(Items.WRITABLE_BOOK)
.setName(Text.literal("New Instruction"))
.setName(Text.translatable("minions.gui.instruction.create"))
.setCallback(() -> createNewInstruction(minion, player))
);
@@ -55,13 +61,22 @@ public class InstructionGui {
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 -> {
inputInstructionName(minion, player, "Instruction").thenAccept(name -> {
ConfiguredInstruction<MinionRuntime> configuredInstruction = minion.getInstructionManager().createInstruction(name, instructionType);
configureInstructionMenu(name, configuredInstruction, minion, player);
})
);
}
public static CompletableFuture<String> inputInstructionName(MinionFakePlayer minion, ServerPlayerEntity player, String defaultValue) {
return TextInput.inputSync(player, Text.translatable("minions.gui.instruction.enter_name"), defaultValue, name -> {
if(minion.getInstructionManager().hasInstruction(name)) {
return new Result.Error<>(Text.translatable("minions.gui.instruction.name_already_used"));
}
return new Result.Success<>(name);
});
}
public static boolean checkInstructionExists(String name, ConfiguredInstruction<?> instruction, MinionFakePlayer minion, ServerPlayerEntity player) {
boolean stillExists = minion.getInstructionManager().getInstruction(name) == instruction;
if(!stillExists) {
@@ -77,16 +92,44 @@ public class InstructionGui {
}
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
gui.setTitle(Text.literal(name));
gui.setSlot(12, createInstructionElement(instruction.getInstruction()));
gui.setSlot(7, new GuiElementBuilder(Items.ANVIL)
.setName(Text.translatable("minions.gui.instruction.configure.rename"))
.setCallback(() -> inputInstructionName(minion, player, name).thenAccept(newName -> {
minion.getInstructionManager().setInstructionName(name, newName);
configureInstructionMenu(newName, instruction, minion, player);
}))
);
int slot = 13;
gui.setSlot(8, new GuiElementBuilder(Items.LAVA_BUCKET)
.setName(Text.translatable("minions.gui.instruction.configure.delete"))
.setCallback(() -> ChoiceInput.confirm(player, Text.translatable("minions.gui.instruction.configure.delete.confirm", name))
.thenAccept(v -> {
minion.getInstructionManager().removeInstruction(name);
instructionList(minion, player);
}))
);
gui.setSlot(13, createInstructionElement(instruction.getInstruction()));
int slot = 14;
for(Parameter<?> parameter : instruction.getInstruction().getParameters()) {
gui.setSlot(slot, createArgumentElement(instruction.getArguments().getArgument(parameter))
.setCallback(() -> configureArgumentMenu(name, instruction, parameter, minion, player))
);
slot++;
}
gui.setSlot(25, new GuiElementBuilder(Items.FEATHER)
.setName(Text.translatable("minions.gui.instruction.configure.copy"))
.addLoreLine(Text.translatable("minions.gui.instruction.configure.copy.description"))
.setCallback(() -> {
player.setAttached(PlayerClipboardAttachment.TYPE, new PlayerClipboardAttachment(minion.getUuid(), name));
player.playSoundToPlayer(SoundEvents.BLOCK_NOTE_BLOCK_CHIME.value(), SoundCategory.BLOCKS, 1, 1);
})
);
updateRunSlot(instruction, minion, gui);
gui.open();
@@ -95,7 +138,7 @@ public class InstructionGui {
private static void updateRunSlot(ConfiguredInstruction<MinionRuntime> instruction, MinionFakePlayer minion, SimpleGui gui) {
if(!instruction.isRunning()) {
gui.setSlot(26, new GuiElementBuilder(Items.ARROW)
.setName(Text.literal("Run"))
.setName(Text.translatable("minions.gui.instruction.run"))
.setCallback(() -> {
instruction.run(minion.getInstructionManager());
updateRunSlot(instruction, minion, gui);
@@ -103,7 +146,7 @@ public class InstructionGui {
);
} else {
gui.setSlot(26, new GuiElementBuilder(Items.BARRIER)
.setName(Text.literal("Stop"))
.setName(Text.translatable("minions.gui.instruction.stop"))
.setCallback(() -> {
instruction.stop(minion.getInstructionManager());
updateRunSlot(instruction, minion, gui);
@@ -117,11 +160,11 @@ public class InstructionGui {
return;
}
A argument = instruction.getArguments().getArgument(parameter);
@Nullable 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.ARGUMENT_TYPES.getId(argument.getType()).getPath())))
.setName(Text.translatable("minions.gui.instruction.argument.configure.type", Text.translatable(TranslationUtil.getTranslationKey(argument != null ? argument.getType() : null, MinionRegistries.ARGUMENT_TYPES, "minions.gui.instruction.argument.configure.type.unset"))))
.setCallback(() -> selectArgumentType(player)
.thenApply(type -> type.openConfiguration(player, parameter.type(), null)
.thenAccept(newArgument -> {
@@ -21,7 +21,7 @@ public class MinionGui {
gui.setSlot(1, new GuiElementBuilder()
.setItem(Items.COMMAND_BLOCK)
.setName(Text.translatable("minions.gui.main.commands"))
.setName(Text.translatable("minions.gui.main.instructions"))
.setCallback((i, clickType, slotActionType) -> {
InstructionGui.openInstructionMainMenu(minion, player);
})
@@ -50,14 +50,6 @@ public class MinionGui {
gui.open();
}
public static void openCommandsGui(ServerPlayerEntity player, MinionFakePlayer minion) {
//CommandsGui.openServerModuleCommandGui(player, minion);
}
public static void openProgrammingInventory(ServerPlayerEntity player, MinionFakePlayer minion) {
}
public static void openMinionInventory(ServerPlayerEntity player, MinionFakePlayer minion) {
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X5, player, false);
gui.setTitle(Text.translatable("minions.gui.inventory.title", minion.getName()));
@@ -3,7 +3,7 @@ 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.gui.input.TextInput;
import io.github.skippyall.minions.minion.MinionData;
import io.github.skippyall.minions.minion.MinionItem;
import io.github.skippyall.minions.minion.MinionProfileUtils;
@@ -0,0 +1,74 @@
package io.github.skippyall.minions.gui.input;
import eu.pb4.sgui.api.elements.GuiElementBuilder;
import eu.pb4.sgui.api.gui.SimpleGui;
import io.github.skippyall.minions.gui.Displayable;
import io.github.skippyall.minions.gui.GuiDisplay;
import net.minecraft.item.Items;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Function;
public class ChoiceInput {
public static <T> BiFunction<ServerPlayerEntity, T, CompletableFuture<T>> createDialogOpener(ScreenHandlerType<?> screen, Text title, Function<T, GuiDisplay> displayFunction, T[] values, @Nullable T fallback) {
return (player, object) -> {
CompletableFuture<T> future = new CompletableFuture<>();
SimpleGui gui = new SimpleGui(screen, player, false) {
@Override
public void onClose() {
if(fallback == null) {
future.cancel(false);
} else {
future.complete(fallback);
}
}
};
gui.setTitle(title);
for(T value : values) {
gui.addSlot(displayFunction.apply(value).createElement()
.setCallback(() -> future.complete(value))
);
}
gui.open();
return future;
};
}
public static <T extends Displayable> BiFunction<ServerPlayerEntity, T, CompletableFuture<T>> createDialogOpener(T[] values) {
return createDialogOpener(ScreenHandlerType.GENERIC_9X3, Text.empty(), Displayable::getDisplay, values, null);
}
public static CompletableFuture<Void> confirm(ServerPlayerEntity player, Text title) {
CompletableFuture<Void> future = new CompletableFuture<>();
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_3X3, player, false) {
@Override
public void onClose() {
future.cancel(false);
}
};
gui.setTitle(title);
gui.setSlot(3, new GuiElementBuilder(Items.REDSTONE_BLOCK)
.setName(Text.translatable("minions.gui.abort"))
.setCallback(() -> future.cancel(false))
);
gui.setSlot(5, new GuiElementBuilder(Items.EMERALD_BLOCK)
.setName(Text.translatable("minions.gui.confirm"))
.setCallback(() -> future.complete(null))
);
gui.open();
return future;
}
}
@@ -1,4 +1,4 @@
package io.github.skippyall.minions.input;
package io.github.skippyall.minions.gui.input;
import org.jetbrains.annotations.NotNull;
@@ -87,7 +87,7 @@ public interface Result<T, E> {
@Override
public @NotNull T getOrThrow() {
throw new RuntimeException("Result was an error: " + message.toString());
throw new RuntimeException("Result was an error: " + message);
}
@Override
@@ -106,7 +106,7 @@ public interface Result<T, E> {
}
@Override
public void ifError(Consumer<Error<T, E>> handler) {
public void ifError(@NotNull Consumer<Error<T, E>> handler) {
handler.accept(this);
}
}
@@ -1,4 +1,4 @@
package io.github.skippyall.minions.input;
package io.github.skippyall.minions.gui.input;
import eu.pb4.sgui.api.elements.GuiElementBuilder;
import eu.pb4.sgui.api.gui.AnvilInputGui;
@@ -9,7 +9,6 @@ import net.minecraft.text.Text;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.function.Predicate;
public class TextInput<T> extends AnvilInputGui {
private final GuiElementBuilder valid = new GuiElementBuilder()
@@ -1,37 +0,0 @@
package io.github.skippyall.minions.input;
import eu.pb4.sgui.api.gui.SimpleGui;
import io.github.skippyall.minions.gui.Displayable;
import io.github.skippyall.minions.gui.GuiDisplay;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.server.network.ServerPlayerEntity;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Function;
public class ChoiceInput {
public static <T> BiFunction<ServerPlayerEntity, T, CompletableFuture<T>> createDialogOpener(Function<T, GuiDisplay> displayFunction, T[] values) {
return (player, object) -> {
CompletableFuture<T> future = new CompletableFuture<>();
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false) {
@Override
public void onClose() {
future.cancel(false);
}
};
for(T value : values) {
gui.addSlot(displayFunction.apply(value).createElement()
.setCallback(() -> future.complete(value))
);
}
gui.open();
return future;
};
}
public static <T extends Displayable> BiFunction<ServerPlayerEntity, T, CompletableFuture<T>> createDialogOpener(T[] values) {
return createDialogOpener(Displayable::getDisplay, values);
}
}
@@ -1,7 +1,6 @@
package io.github.skippyall.minions.minion;
import com.mojang.serialization.Codec;
import io.github.skippyall.minions.Minions;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.PersistentState;
import net.minecraft.world.PersistentStateType;
@@ -1,20 +1,13 @@
package io.github.skippyall.minions.minion;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.ProfileLookupCallback;
import com.mojang.authlib.properties.PropertyMap;
import com.mojang.authlib.yggdrasil.ProfileResult;
import com.mojang.brigadier.StringReader;
import io.github.skippyall.minions.input.Result;
import net.minecraft.block.entity.SkullBlockEntity;
import net.minecraft.server.MinecraftServer;
import io.github.skippyall.minions.gui.input.Result;
import net.minecraft.text.Text;
import net.minecraft.util.StringHelper;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;
import static io.github.skippyall.minions.Minions.LOGGER;
@@ -40,7 +40,11 @@ public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
}
public ConfiguredInstruction<MinionRuntime> createInstruction(String name, InstructionType<MinionRuntime> instructionType) {
ConfiguredInstruction<MinionRuntime> instruction = new ConfiguredInstruction<>(instructionType, name);
if(configuredInstructions.containsKey(name)) {
return null;
}
ConfiguredInstruction<MinionRuntime> instruction = new ConfiguredInstruction<>(instructionType);
configuredInstructions.put(name, instruction);
return instruction;
}
@@ -59,6 +63,12 @@ public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
return configuredInstructions.containsKey(name);
}
public void setInstructionName(String oldName, String newName) {
if(!configuredInstructions.containsKey(newName)) {
configuredInstructions.put(newName, configuredInstructions.remove(oldName));
}
}
public void save(WriteView view) {
WriteView.ListView list = view.getList("configuredInstructions");
for (Map.Entry<String, ConfiguredInstruction<MinionRuntime>> instruction : configuredInstructions.entrySet()) {
@@ -78,7 +88,7 @@ public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
}
try {
ConfiguredInstruction<MinionRuntime> instruction = ConfiguredInstruction.load(inner, this, name.get());
ConfiguredInstruction<MinionRuntime> instruction = ConfiguredInstruction.load(inner, this);
configuredInstructions.put(name.get(), instruction);
} catch (Exception e) {
Minions.LOGGER.error("Could not deserialize configured instruction \"{}\" of minion \"{}\":", name.get(), minion.getGameProfile().getName(), e);
@@ -2,7 +2,7 @@ package io.github.skippyall.minions.minion.skin;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
import io.github.skippyall.minions.input.TextInput;
import io.github.skippyall.minions.gui.input.TextInput;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
@@ -2,7 +2,7 @@ package io.github.skippyall.minions.minion.skin;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.PropertyMap;
import io.github.skippyall.minions.input.TextInput;
import io.github.skippyall.minions.gui.input.TextInput;
import net.minecraft.block.entity.SkullBlockEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
@@ -2,16 +2,10 @@ package io.github.skippyall.minions.minion.skin;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.PropertyMap;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.github.skippyall.minions.input.TextInput;
import io.github.skippyall.minions.minion.MinionProfileUtils;
import io.github.skippyall.minions.gui.input.TextInput;
import net.minecraft.block.entity.SkullBlockEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Uuids;
import net.minecraft.util.dynamic.Codecs;
import java.util.Optional;
import java.util.UUID;
@@ -13,18 +13,16 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
private final ValueSupplierList<R> arguments;
private final ValueConsumerList<R> valueConsumers;
private @Nullable InstructionExecution<R> execution;
private final String name;
private ConfiguredInstruction(InstructionType<R> instruction, ValueSupplierList<R> arguments, ValueConsumerList<R> valueConsumers, @Nullable InstructionExecution<R> execution, String name) {
private ConfiguredInstruction(InstructionType<R> instruction, ValueSupplierList<R> arguments, ValueConsumerList<R> valueConsumers, @Nullable InstructionExecution<R> execution) {
this.instruction = instruction;
this.arguments = arguments;
this.valueConsumers = valueConsumers;
this.execution = execution;
this.name = name;
}
public ConfiguredInstruction(InstructionType<R> instruction, String name) {
this(instruction, new ValueSupplierList<>(), new ValueConsumerList<>(), null, name);
public ConfiguredInstruction(InstructionType<R> instruction) {
this(instruction, new ValueSupplierList<>(), new ValueConsumerList<>(), null);
}
public InstructionType<R> getInstruction() {
@@ -35,10 +33,6 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
return arguments;
}
public String getName() {
return name;
}
public boolean canRun() {
return instruction != null && arguments != null && arguments.hasArgumentForAll(instruction.getParameters());
}
@@ -57,7 +51,7 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
execution = instruction.createExecution(arguments, minion);
execution.start(minion);
} catch (Exception e) {
Minions.LOGGER.error("An error occurred while executing configured Instruction {}", name, e);
Minions.LOGGER.error("An error occurred while executing configured Instruction", e);
}
}
@@ -93,7 +87,7 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
}
}
public static <R extends InstructionRuntime<R>> ConfiguredInstruction<R> load(ReadView view, R minion, String name) {
public static <R extends InstructionRuntime<R>> ConfiguredInstruction<R> load(ReadView view, R minion) {
InstructionType<R> instructionType = view.read("instruction", minion.getInstructionTypeRegistry().getCodec()).orElseThrow();
ValueSupplierList<R> arguments = view.read("arguments", minion.getArgumentListCodec()).orElseGet(ValueSupplierList::new);
@@ -105,12 +99,12 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
ReadView executionView = view.getReadView("execution");
try {
InstructionExecution<R> execution = instructionType.loadExecution(executionView, minion);
return new ConfiguredInstruction<>(instructionType, arguments, valueConsumers, execution, name);
return new ConfiguredInstruction<>(instructionType, arguments, valueConsumers, execution);
} catch (Exception e) {
Minions.LOGGER.error("Error while loading execution", e);
}
}
return new ConfiguredInstruction<>(instructionType, arguments, valueConsumers, null, name);
return new ConfiguredInstruction<>(instructionType, arguments, valueConsumers, null);
}
}
@@ -9,7 +9,6 @@ import io.github.skippyall.minions.program.instruction.execution.ActionExecution
import io.github.skippyall.minions.program.instruction.execution.TurnExecution;
import io.github.skippyall.minions.program.instruction.execution.WalkExecution;
import io.github.skippyall.minions.program.supplier.Parameter;
import io.github.skippyall.minions.util.ModelIdUtil;
import net.minecraft.item.Items;
import net.minecraft.registry.Registry;
import net.minecraft.util.Identifier;
@@ -22,7 +21,7 @@ import java.util.function.Supplier;
public class Instructions {
public static final InstructionType<MinionRuntime> WALK = register(
"walk",
base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_BOOTS), base, true),
base -> new GuiDisplay.ModelBased(Items.IRON_BOOTS, base, true),
WalkExecution::new,
List.of(WalkExecution.blocksToMoveParam)
);
@@ -36,13 +35,13 @@ public class Instructions {
public static final InstructionType<MinionRuntime> ATTACK = register(
"attack",
base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_BOOTS), base, true),
base -> new GuiDisplay.ModelBased(Items.IRON_PICKAXE, base, true),
() -> new ActionExecution(EntityPlayerActionPack.ActionType.ATTACK)
);
public static final InstructionType<MinionRuntime> USE = register(
"use",
base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.LEVER), base, true),
base -> new GuiDisplay.ModelBased(Items.LEVER, base, true),
() -> new ActionExecution(EntityPlayerActionPack.ActionType.USE)
);
@@ -3,10 +3,9 @@ package io.github.skippyall.minions.program.value;
import com.mojang.serialization.Codec;
import io.github.skippyall.minions.MinionRegistries;
import io.github.skippyall.minions.Minions;
import io.github.skippyall.minions.gui.Displayable;
import io.github.skippyall.minions.gui.GuiDisplay;
import io.github.skippyall.minions.input.ChoiceInput;
import io.github.skippyall.minions.input.TextInput;
import io.github.skippyall.minions.gui.input.ChoiceInput;
import io.github.skippyall.minions.gui.input.TextInput;
import io.github.skippyall.minions.program.instruction.execution.TurnExecution;
import net.minecraft.item.Items;
import net.minecraft.registry.Registry;
@@ -6,7 +6,6 @@ import net.minecraft.util.Identifier;
public class ModelIdUtil {
public static Identifier getItemModelId(Item item) {
Identifier identifier = Registries.ITEM.getId(item);
return identifier.withPrefixedPath("item/");
return Registries.ITEM.getId(item);
}
}
@@ -1,13 +1,16 @@
{
"minions.gui.main.commands": "Commands",
"minions.gui.main.programming": "Programming",
"minions.gui.main.instructions": "Instructions",
"minions.gui.main.modules": "Modules",
"minions.gui.main.inventory": "Inventory",
"minions.gui.main.pickup": "Pick up",
"minions.gui.inventory.title": "%s's Inventory",
"minions.gui.module_commands.title": "Commands",
"minions.gui.commands.title": "%s's Commands",
"minions.gui.modules.title": "%s's Modules",
"minions.gui.ok": "OK",
"minions.gui.confirm": "Confirm",
"minions.gui.abort": "Abort",
"minions.gui.look.skin.name": "Name",
"minions.gui.look.skin.name.title": "Enter a player name",
"minions.gui.look.skin.uuid": "UUID",
@@ -15,10 +18,23 @@
"minions.gui.look.skin.base64": "Base64",
"minions.gui.look.skin.base64.title": "Enter a skin in base64 encoding",
"minions.gui.look.rename.title": "Enter a name",
"minions.gui.instruction.list": "Instruction List",
"minions.gui.instruction.create": "New Instruction",
"minions.gui.instruction.no_instruction_set": "No instruction set",
"minions.gui.instruction.enter_name": "Enter a name",
"minions.gui.instruction.name_already_used": "Name already used",
"minions.gui.instruction.removed": "This instruction no longer exists",
"minions.gui.instruction.no_argument_set": "No argument set",
"minions.gui.instruction.configure.rename": "Rename",
"minions.gui.instruction.configure.delete": "Delete",
"minions.gui.instruction.configure.delete.confirm": "Delete %s?",
"minions.gui.instruction.configure.copy": "Copy Reference",
"minions.gui.instruction.configure.copy.description": "Click here and then use a Minion Trigger Block to bind it",
"minions.gui.instruction.run": "Run",
"minions.gui.instruction.stop": "Stop",
"minions.gui.instruction.argument.configure.type": "Type: %s",
"minions.gui.instruction.argument.configure.type.unset": "Unset",
"minions.command.input.int.fail": "Not an integer",
"minions.command.input.float.fail": "Not a number",