diff --git a/src/main/java/io/github/skippyall/minions/MinionItems.java b/src/main/java/io/github/skippyall/minions/MinionItems.java index e9d644c..dea80b3 100644 --- a/src/main/java/io/github/skippyall/minions/MinionItems.java +++ b/src/main/java/io/github/skippyall/minions/MinionItems.java @@ -1,7 +1,12 @@ package io.github.skippyall.minions; +import eu.pb4.polymer.core.api.item.PolymerBlockItem; import eu.pb4.polymer.core.api.item.SimplePolymerItem; import io.github.skippyall.minions.minion.MinionItem; +import io.github.skippyall.minions.minion.MinionRuntime; +import io.github.skippyall.minions.module.MinionModule; +import io.github.skippyall.minions.program.instruction.InstructionType; +import io.github.skippyall.minions.program.instruction.Instructions; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.DamageResistantComponent; import net.minecraft.entity.damage.DamageType; @@ -14,16 +19,59 @@ import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.tag.TagKey; import net.minecraft.util.Identifier; +import java.util.List; import java.util.function.Function; import static io.github.skippyall.minions.Minions.MOD_ID; public class MinionItems { public static final TagKey MINION_ITEM_RESISTS = TagKey.of(RegistryKeys.DAMAGE_TYPE, Identifier.of(MOD_ID, "minion_item_resists")); - public static final MinionItem MINION_ITEM = registerItem(Identifier.of(MOD_ID, "minion"), settings -> new MinionItem(settings.component(DataComponentTypes.DAMAGE_RESISTANT, new DamageResistantComponent(MINION_ITEM_RESISTS)))); - public static final SimplePolymerItem BASIC_UPGRADE_BASE = registerItem(Identifier.of(MOD_ID, "basic_upgrade_base"), settings -> new SimplePolymerItem(settings, Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE)); - public static final SimplePolymerItem ADVANCED_UPGRADE_BASE = registerItem(Identifier.of(MOD_ID, "advanced_upgrade_base"), settings -> new SimplePolymerItem(settings, Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE)); + public static final MinionItem MINION_ITEM = registerItem( + Identifier.of(MOD_ID, "minion"), + settings -> new MinionItem(settings.component(DataComponentTypes.DAMAGE_RESISTANT, new DamageResistantComponent(MINION_ITEM_RESISTS))) + ); + public static final SimplePolymerItem BASIC_UPGRADE_BASE = registerItem( + Identifier.of(MOD_ID, "basic_upgrade_base"), + settings -> new SimplePolymerItem(settings, Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE) + ); + + public static final SimplePolymerItem ADVANCED_UPGRADE_BASE = registerItem( + Identifier.of(MOD_ID, "advanced_upgrade_base"), + settings -> new SimplePolymerItem(settings, Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE) + ); + + + public static final SimplePolymerItem MOVE_MODULE = registerModule( + Identifier.of(MOD_ID, "move_module"), + Items.IRON_BOOTS, + List.of(Instructions.WALK, Instructions.TURN) + ); + + public static final SimplePolymerItem ATTACK_MODULE = registerModule( + Identifier.of(MOD_ID, "attack_module"), + Items.IRON_PICKAXE, + List.of(Instructions.ATTACK) + ); + + public static final SimplePolymerItem INTERACT_MODULE = registerModule( + Identifier.of(MOD_ID, "interact_module"), + Items.LEVER, + List.of(Instructions.USE) + ); + + public static final SimplePolymerItem MOB_SPAWNING_MODULE = registerModule( + Identifier.of(MOD_ID, "mob_spawning_module"), + Items.SPAWNER, + List.of(), + List.of("mobSpawning") + ); + + public static final PolymerBlockItem MINION_TRIGGER_ITEM = + registerItem( + MinionRegistration.MINION_TRIGGER_ID, + settings -> new PolymerBlockItem(MinionRegistration.MINION_TRIGGER_BLOCK, settings, Items.GOLD_BLOCK) + ); public static T registerItem(Identifier identifier, Function constructor, Item.Settings settings) { T item = constructor.apply(settings.registryKey(RegistryKey.of(RegistryKeys.ITEM, identifier))); @@ -37,6 +85,23 @@ public class MinionItems { return registerItem(identifier, constructor, new Item.Settings()); } + public static SimplePolymerItem registerModule(Identifier identifier, Item vanillaItem, List> instructionTypes, List specialEffects) { + return registerItem( + identifier, + settings -> new SimplePolymerItem(settings, vanillaItem), + new Item.Settings().component(MinionModule.COMPONENT_TYPE, new MinionModule(instructionTypes, specialEffects)) + ); + } + + public static SimplePolymerItem registerModule(Identifier identifier, Item vanillaItem, List> instructionTypes) { + return registerModule( + identifier, + vanillaItem, + instructionTypes, + List.of() + ); + } + public static void register() { } } diff --git a/src/main/java/io/github/skippyall/minions/MinionRegistration.java b/src/main/java/io/github/skippyall/minions/MinionRegistration.java new file mode 100644 index 0000000..3e92b69 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/MinionRegistration.java @@ -0,0 +1,39 @@ +package io.github.skippyall.minions; + +import eu.pb4.polymer.core.api.block.PolymerBlockUtils; +import io.github.skippyall.minions.block.MinionTriggerBlock; +import io.github.skippyall.minions.block.MinionTriggerBlockEntity; +import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.registry.Registries; +import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.sound.BlockSoundGroup; +import net.minecraft.util.Identifier; + +public class MinionRegistration { + public static final Identifier MINION_TRIGGER_ID = Identifier.of(Minions.MOD_ID, "minion_trigger"); + public static final MinionTriggerBlock MINION_TRIGGER_BLOCK = Registry.register( + Registries.BLOCK, + MINION_TRIGGER_ID, + new MinionTriggerBlock(AbstractBlock.Settings.create() + .registryKey(RegistryKey.of(RegistryKeys.BLOCK, MINION_TRIGGER_ID)) + .hardness(5) + .strength(5.0F, 6.0F) + .sounds(BlockSoundGroup.IRON) + .requiresTool() + ) + ); + public static final BlockEntityType MINION_TRIGGER_BE_TYPE = + Registry.register( + Registries.BLOCK_ENTITY_TYPE, + MINION_TRIGGER_ID, + FabricBlockEntityTypeBuilder.create(MinionTriggerBlockEntity::new, MINION_TRIGGER_BLOCK).build() + ); + + public static void register() { + PolymerBlockUtils.registerBlockEntity(MINION_TRIGGER_BE_TYPE); + } +} diff --git a/src/main/java/io/github/skippyall/minions/MinionRegistries.java b/src/main/java/io/github/skippyall/minions/MinionRegistries.java index cce73d6..4976f69 100644 --- a/src/main/java/io/github/skippyall/minions/MinionRegistries.java +++ b/src/main/java/io/github/skippyall/minions/MinionRegistries.java @@ -3,8 +3,9 @@ package io.github.skippyall.minions; import com.mojang.serialization.Lifecycle; import io.github.skippyall.minions.minion.MinionRuntime; import io.github.skippyall.minions.minion.skin.SkinProvider; -import io.github.skippyall.minions.program.argument.ArgumentType; +import io.github.skippyall.minions.program.supplier.ValueSupplierType; import io.github.skippyall.minions.program.instruction.InstructionType; +import io.github.skippyall.minions.program.consumer.ValueConsumerType; import io.github.skippyall.minions.program.value.ValueType; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; @@ -13,7 +14,8 @@ import net.minecraft.util.Identifier; public class MinionRegistries { public static final Registry> VALUE_TYPES = registry("value_type"); - public static final Registry> ARGUMENT_TYPE_REGISTRY = registry("argument_type"); + public static final Registry> ARGUMENT_TYPES = registry("argument_type"); + public static final Registry> VALUE_CONSUMER_TYPES = registry("value_consumer_type"); public static final Registry> INSTRUCTION_TYPES = registry("instruction_type"); public static final Registry SKIN_PROVIDERS = registry("skin_providers"); diff --git a/src/main/java/io/github/skippyall/minions/Minions.java b/src/main/java/io/github/skippyall/minions/Minions.java index a93c073..c53187f 100644 --- a/src/main/java/io/github/skippyall/minions/Minions.java +++ b/src/main/java/io/github/skippyall/minions/Minions.java @@ -41,6 +41,8 @@ public class Minions implements ModInitializer { ValueTypes.register(); SkinProviders.register(); + + MinionRegistration.register(); MinionItems.register(); MinionCreativeTab.registerGroup(); } diff --git a/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlock.java b/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlock.java new file mode 100644 index 0000000..2493d7d --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlock.java @@ -0,0 +1,67 @@ +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 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.state.StateManager; +import net.minecraft.state.property.BooleanProperty; +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; + +public class MinionTriggerBlock extends BlockWithEntity implements PolymerBlock { + public static final MapCodec CODEC = createCodec(MinionTriggerBlock::new); + + public static final BooleanProperty POWERED = BooleanProperty.of("powered"); + + public MinionTriggerBlock(Settings settings) { + super(settings); + setDefaultState(getDefaultState().with(POWERED, false)); + } + + @Override + protected void appendProperties(StateManager.Builder builder) { + builder.add(POWERED); + } + + @Override + protected void neighborUpdate(BlockState state, World world, BlockPos pos, Block sourceBlock, @Nullable WireOrientation wireOrientation, boolean notify) { + boolean newPower = world.isReceivingRedstonePower(pos); + if(state.get(POWERED) != newPower) { + world.setBlockState(pos, state.with(POWERED, newPower)); + world.getBlockEntity(pos, MinionRegistration.MINION_TRIGGER_BE_TYPE).ifPresent(MinionTriggerBlockEntity::updatePower); + } + } + + @Override + protected boolean hasComparatorOutput(BlockState state) { + return true; + } + + @Override + protected int getComparatorOutput(BlockState state, World world, BlockPos pos) { + return world.getBlockEntity(pos, MinionRegistration.MINION_TRIGGER_BE_TYPE).map(MinionTriggerBlockEntity::getComparatorOutput).orElse(0); + } + + @Override + protected MapCodec getCodec() { + return CODEC; + } + + @Override + public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new MinionTriggerBlockEntity(pos, state); + } + + @Override + public BlockState getPolymerBlockState(BlockState state, PacketContext context) { + return state.get(POWERED) ? Blocks.REDSTONE_BLOCK.getDefaultState() : Blocks.GOLD_BLOCK.getDefaultState(); + } +} diff --git a/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlockEntity.java b/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlockEntity.java new file mode 100644 index 0000000..54bbf54 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlockEntity.java @@ -0,0 +1,84 @@ +package io.github.skippyall.minions.block; + +import io.github.skippyall.minions.MinionRegistration; +import io.github.skippyall.minions.minion.MinionRuntime; +import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.program.instruction.ConfiguredInstruction; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.storage.ReadView; +import net.minecraft.storage.WriteView; +import net.minecraft.util.Uuids; +import net.minecraft.util.math.BlockPos; + +import java.util.UUID; + +public class MinionTriggerBlockEntity extends BlockEntity { + private UUID minionUuid; + private String instructionName = ""; + + public MinionTriggerBlockEntity(BlockPos pos, BlockState state) { + super(MinionRegistration.MINION_TRIGGER_BE_TYPE, pos, state); + } + + public void updatePower() { + boolean powered = getCachedState().get(MinionTriggerBlock.POWERED); + ConfiguredInstruction instruction = getInstruction(); + + if(instruction != null) { + if(powered) { + instruction.run(getMinion().getInstructionManager()); + } else { + instruction.stop(getMinion().getInstructionManager()); + } + } + } + + public int getComparatorOutput() { + ConfiguredInstruction instruction = getInstruction(); + if(instruction != null && instruction.isRunning()) { + return 15; + } + return 0; + } + + public MinionFakePlayer getMinion() { + if(minionUuid != null && world != null && world.getPlayerByUuid(minionUuid) instanceof MinionFakePlayer minion) { + return minion; + } + return null; + } + + public ConfiguredInstruction getInstruction() { + MinionFakePlayer minion = getMinion(); + if(minion == null) { + return null; + } + + return minion.getInstructionManager().getInstruction(instructionName); + } + + @Override + public void onBlockReplaced(BlockPos pos, BlockState oldState) { + super.onBlockReplaced(pos, oldState); + } + + @Override + public void markRemoved() { + super.markRemoved(); + } + + @Override + protected void readData(ReadView view) { + minionUuid = view.read("minionUuid", Uuids.CODEC).orElse(null); + instructionName = view.getString("instructionName", ""); + } + + @Override + protected void writeData(WriteView view) { + if(minionUuid != null) { + view.put("minionUuid", Uuids.CODEC, minionUuid); + } + view.putString("instructionName", instructionName); + } +} diff --git a/src/main/java/io/github/skippyall/minions/gui/InstructionGui.java b/src/main/java/io/github/skippyall/minions/gui/InstructionGui.java index 717c194..2249295 100644 --- a/src/main/java/io/github/skippyall/minions/gui/InstructionGui.java +++ b/src/main/java/io/github/skippyall/minions/gui/InstructionGui.java @@ -7,13 +7,11 @@ import io.github.skippyall.minions.input.TextInput; import io.github.skippyall.minions.minion.MinionRuntime; 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.dingenskirchen.SpecificDingenskirchenType; +import io.github.skippyall.minions.program.supplier.ValueSupplier; +import io.github.skippyall.minions.program.supplier.ValueSupplierType; 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.program.supplier.Parameter; import io.github.skippyall.minions.util.TranslationUtil; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -45,7 +43,7 @@ public class InstructionGui { 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); + ConfiguredInstruction instruction = minion.getInstructionManager().getInstruction(instructionName); gui.addSlot(instruction.getInstruction().getDisplay().createElement() .setName(Text.literal(instructionName)) .setLore(List.of()) @@ -58,7 +56,7 @@ 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 -> { - ConfiguredInstruction configuredInstruction = minion.getInstructionManager().createInstruction(name, instructionType); + ConfiguredInstruction configuredInstruction = minion.getInstructionManager().createInstruction(name, instructionType); configureInstructionMenu(name, configuredInstruction, minion, player); }) ); @@ -73,7 +71,7 @@ public class InstructionGui { return stillExists; } - public static void configureInstructionMenu(String name, ConfiguredInstruction instruction, MinionFakePlayer minion, ServerPlayerEntity player) { + public static void configureInstructionMenu(String name, ConfiguredInstruction instruction, MinionFakePlayer minion, ServerPlayerEntity player) { if(!checkInstructionExists(name, instruction, minion, player)) { return; } @@ -94,12 +92,12 @@ public class InstructionGui { gui.open(); } - private static void updateRunSlot(ConfiguredInstruction instruction, MinionFakePlayer minion, SimpleGui gui) { + 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); + instruction.run(minion.getInstructionManager()); updateRunSlot(instruction, minion, gui); }) ); @@ -107,14 +105,14 @@ public class InstructionGui { gui.setSlot(26, new GuiElementBuilder(Items.BARRIER) .setName(Text.literal("Stop")) .setCallback(() -> { - instruction.stop(minion); + instruction.stop(minion.getInstructionManager()); updateRunSlot(instruction, minion, gui); }) ); } } - public static , MinionRuntime>> void configureArgumentMenu(String name, ConfiguredInstruction instruction, Parameter parameter, MinionFakePlayer minion, ServerPlayerEntity player) { + public static > void configureArgumentMenu(String name, ConfiguredInstruction instruction, Parameter parameter, MinionFakePlayer minion, ServerPlayerEntity player) { if(!checkInstructionExists(name, instruction, minion, player)) { return; } @@ -123,9 +121,9 @@ public class InstructionGui { 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()))) + .setName(Text.literal("Type: " + (argument == null ? "Unset" : MinionRegistries.ARGUMENT_TYPES.getId(argument.getType()).getPath()))) .setCallback(() -> selectArgumentType(player) - .thenApply(type -> type.createTypeSpecific(parameter.type()).openArgumentDialog(player, null) + .thenApply(type -> type.openConfiguration(player, parameter.type(), null) .thenAccept(newArgument -> { instruction.getArguments().setArgument(parameter, newArgument); configureArgumentMenu(name, instruction, parameter, minion, player); @@ -137,7 +135,7 @@ public class InstructionGui { if(argument != null) { gui.setSlot(5, new GuiElementBuilder(Items.STRUCTURE_VOID) .setName(Text.literal("Configure")) - .setCallback(() -> argument.getType().openArgumentDialog(player, argument) + .setCallback(() -> argument.getType().openConfiguration(player, argument.getValueType(), argument) .thenAccept(newArgument -> instruction.getArguments().setArgument(parameter, newArgument)) ) ); @@ -145,12 +143,12 @@ public class InstructionGui { gui.open(); } - public static CompletableFuture selectArgumentType(ServerPlayerEntity player) { - CompletableFuture future = new CompletableFuture<>(); + public static CompletableFuture> selectArgumentType(ServerPlayerEntity player) { + CompletableFuture> future = new CompletableFuture<>(); SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false); - for(GenericArgumentType type : MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY) { + for(ValueSupplierType type : MinionRegistries.ARGUMENT_TYPES) { gui.addSlot(new GuiElementBuilder() - .setName(Text.translatable(TranslationUtil.getTranslationKey(type, MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY))) + .setName(Text.translatable(TranslationUtil.getTranslationKey(type, MinionRegistries.ARGUMENT_TYPES))) .setCallback(() -> future.complete(type)) ); } @@ -158,13 +156,13 @@ public class InstructionGui { return future; } - public static CompletableFuture> selectInstructionModuleMenu(MinionFakePlayer minion, ServerPlayerEntity player) { + public static CompletableFuture> 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> future = new CompletableFuture<>(); + CompletableFuture> future = new CompletableFuture<>(); SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false) { @Override @@ -190,11 +188,11 @@ public class InstructionGui { return future; } - public static CompletableFuture> selectInstructionMenu(MinionModule module, MinionFakePlayer minion, ServerPlayerEntity player) { - CompletableFuture> future = new CompletableFuture<>(); + public static CompletableFuture> selectInstructionMenu(MinionModule module, MinionFakePlayer minion, ServerPlayerEntity player) { + CompletableFuture> future = new CompletableFuture<>(); SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false); - for(InstructionType instructionType : module.instructions()) { + for(InstructionType instructionType : module.instructions()) { gui.addSlot(createInstructionElement(instructionType) .setCallback(() -> future.complete(instructionType)) ); @@ -215,10 +213,10 @@ public class InstructionGui { return instructionBuilder; } - public static GuiElementBuilder createArgumentElement(Argument argument) { + public static GuiElementBuilder createArgumentElement(ValueSupplier valueSupplier) { GuiElementBuilder argumentBuilder; - if(argument != null) { - argumentBuilder = argument.getDisplay().createElement(); + if(valueSupplier != null) { + argumentBuilder = valueSupplier.getDisplay().createElement(); } else { argumentBuilder = new GuiElementBuilder(Items.RED_WOOL) .setName(Text.translatable("minions.gui.instruction.no_argument_set")); diff --git a/src/main/java/io/github/skippyall/minions/minion/MinionInstructionManager.java b/src/main/java/io/github/skippyall/minions/minion/MinionInstructionManager.java deleted file mode 100644 index fa15dc2..0000000 --- a/src/main/java/io/github/skippyall/minions/minion/MinionInstructionManager.java +++ /dev/null @@ -1,79 +0,0 @@ -package io.github.skippyall.minions.minion; - -import io.github.skippyall.minions.Minions; -import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; -import io.github.skippyall.minions.program.instruction.ConfiguredInstruction; -import io.github.skippyall.minions.program.instruction.InstructionType; -import net.minecraft.storage.ReadView; -import net.minecraft.storage.WriteView; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -public class MinionInstructionManager { - private final MinionFakePlayer minion; - private final Map> configuredInstructions = new HashMap<>(); - - public MinionInstructionManager(MinionFakePlayer minion) { - this.minion = minion; - } - - public void tick() { - for (ConfiguredInstruction instruction : configuredInstructions.values()) { - instruction.tick(minion); - } - } - - public Set getInstructionNames() { - return configuredInstructions.keySet(); - } - - public ConfiguredInstruction createInstruction(String name, InstructionType instructionType) { - ConfiguredInstruction instruction = new ConfiguredInstruction<>(instructionType, name); - configuredInstructions.put(name, instruction); - return instruction; - } - - public void removeInstruction(String name) { - ConfiguredInstruction instruction = getInstruction(name); - instruction.stop(minion); - configuredInstructions.remove(name); - } - - public ConfiguredInstruction getInstruction(String name) { - return configuredInstructions.get(name); - } - - public boolean hasInstruction(String name) { - return configuredInstructions.containsKey(name); - } - - public void save(WriteView view) { - WriteView.ListView list = view.getList("configuredInstructions"); - for (Map.Entry> instruction : configuredInstructions.entrySet()) { - WriteView inner = list.add(); - inner.putString("name", instruction.getKey()); - instruction.getValue().save(inner, minion); - } - } - - public void load(ReadView view) { - ReadView.ListReadView list = view.getListReadView("configuredInstructions"); - for (ReadView inner : list) { - Optional name = inner.getOptionalString("name"); - if(name.isEmpty()) { - Minions.LOGGER.error("Tried deserializing configured instruction without a name of minion \"{}\":", minion.getGameProfile().getName()); - continue; - } - - try { - ConfiguredInstruction instruction = ConfiguredInstruction.load(inner, minion, name.get()); - configuredInstructions.put(name.get(), instruction); - } catch (Exception e) { - Minions.LOGGER.error("Could not deserialize configured instruction \"{}\" of minion \"{}\":", name.get(), minion.getGameProfile().getName(), e); - } - } - } -} diff --git a/src/main/java/io/github/skippyall/minions/minion/MinionRuntime.java b/src/main/java/io/github/skippyall/minions/minion/MinionRuntime.java index 70999d2..a4297d9 100644 --- a/src/main/java/io/github/skippyall/minions/minion/MinionRuntime.java +++ b/src/main/java/io/github/skippyall/minions/minion/MinionRuntime.java @@ -1,14 +1,103 @@ package io.github.skippyall.minions.minion; import io.github.skippyall.minions.MinionRegistries; +import io.github.skippyall.minions.Minions; +import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.program.InstructionRuntime; -import io.github.skippyall.minions.program.argument.GenericArgumentType; +import io.github.skippyall.minions.program.supplier.ValueSupplierType; +import io.github.skippyall.minions.program.instruction.ConfiguredInstruction; +import io.github.skippyall.minions.program.instruction.InstructionType; +import io.github.skippyall.minions.program.consumer.ValueConsumerType; import net.minecraft.registry.Registry; +import net.minecraft.storage.ReadView; +import net.minecraft.storage.WriteView; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; public class MinionRuntime implements InstructionRuntime { + private final MinionFakePlayer minion; + private final Map> configuredInstructions = new HashMap<>(); + + public MinionRuntime(MinionFakePlayer minion) { + this.minion = minion; + } + + public MinionFakePlayer getMinion() { + return minion; + } + + public void tick() { + for (ConfiguredInstruction instruction : configuredInstructions.values()) { + instruction.tick(this); + } + } + + public Set getInstructionNames() { + return configuredInstructions.keySet(); + } + + public ConfiguredInstruction createInstruction(String name, InstructionType instructionType) { + ConfiguredInstruction instruction = new ConfiguredInstruction<>(instructionType, name); + configuredInstructions.put(name, instruction); + return instruction; + } + + public void removeInstruction(String name) { + ConfiguredInstruction instruction = getInstruction(name); + instruction.stop(this); + configuredInstructions.remove(name); + } + + public ConfiguredInstruction getInstruction(String name) { + return configuredInstructions.get(name); + } + + public boolean hasInstruction(String name) { + return configuredInstructions.containsKey(name); + } + + public void save(WriteView view) { + WriteView.ListView list = view.getList("configuredInstructions"); + for (Map.Entry> instruction : configuredInstructions.entrySet()) { + WriteView inner = list.add(); + inner.putString("name", instruction.getKey()); + instruction.getValue().save(inner, this); + } + } + + public void load(ReadView view) { + ReadView.ListReadView list = view.getListReadView("configuredInstructions"); + for (ReadView inner : list) { + Optional name = inner.getOptionalString("name"); + if(name.isEmpty()) { + Minions.LOGGER.error("Tried deserializing configured instruction without a name of minion \"{}\":", minion.getGameProfile().getName()); + continue; + } + + try { + ConfiguredInstruction instruction = ConfiguredInstruction.load(inner, this, name.get()); + configuredInstructions.put(name.get(), instruction); + } catch (Exception e) { + Minions.LOGGER.error("Could not deserialize configured instruction \"{}\" of minion \"{}\":", name.get(), minion.getGameProfile().getName(), e); + } + } + } @Override - public Registry> getGenericArgumentTypeRegistry() { - return MinionRegistries.GENERIC_ARGUMENT_TYPE_REGISTRY; + public Registry> getArgumentTypeRegistry() { + return MinionRegistries.ARGUMENT_TYPES; + } + + @Override + public Registry> getInstructionTypeRegistry() { + return MinionRegistries.INSTRUCTION_TYPES; + } + + @Override + public Registry> getValueConsumerTypeRegistry() { + return MinionRegistries.VALUE_CONSUMER_TYPES; } } diff --git a/src/main/java/io/github/skippyall/minions/minion/fakeplayer/MinionFakePlayer.java b/src/main/java/io/github/skippyall/minions/minion/fakeplayer/MinionFakePlayer.java index bc73118..bf2015a 100644 --- a/src/main/java/io/github/skippyall/minions/minion/fakeplayer/MinionFakePlayer.java +++ b/src/main/java/io/github/skippyall/minions/minion/fakeplayer/MinionFakePlayer.java @@ -6,7 +6,7 @@ import com.mojang.authlib.properties.PropertyMap; import io.github.skippyall.minions.MinionItems; import io.github.skippyall.minions.minion.MinionData; import io.github.skippyall.minions.gui.MinionGui; -import io.github.skippyall.minions.minion.MinionInstructionManager; +import io.github.skippyall.minions.minion.MinionRuntime; import io.github.skippyall.minions.minion.MinionItem; import io.github.skippyall.minions.minion.MinionPersistentState; import io.github.skippyall.minions.minion.MinionProfileUtils; @@ -51,11 +51,8 @@ public class MinionFakePlayer extends ServerPlayerEntity { private EntityPlayerActionPack actionPack; - private float moveForward; - private float moveSideways; - private final ModuleInventory moduleInventory = new ModuleInventory(); - private final MinionInstructionManager instructionManager = new MinionInstructionManager(this); + private final MinionRuntime instructionManager = new MinionRuntime(this); private final MinionData data; @@ -118,7 +115,7 @@ public class MinionFakePlayer extends ServerPlayerEntity { return actionPack; } - public MinionInstructionManager getInstructionManager() { + public MinionRuntime getInstructionManager() { return instructionManager; } @@ -127,11 +124,11 @@ public class MinionFakePlayer extends ServerPlayerEntity { } public boolean canSpawnMobs() { - return true; + return moduleInventory.hasAbility("mobSpawning"); } public boolean canDespawnMobs() { - return true; + return moduleInventory.hasAbility("mobSpawning"); } @Override @@ -249,44 +246,6 @@ public class MinionFakePlayer extends ServerPlayerEntity { return networkHandler.player; } - /*public void moveForward(float forward) { - this.moveForward += forward; - EntityPlayerActionPack actionPack = getMinionActionPack(); - if (moveForward != 0) { - actionPack.setForward(moveForward > 0 ? 1 : -1); - } - } - - public void moveSideways(float sideways) { - this.moveSideways += sideways; - EntityPlayerActionPack actionPack = getMinionActionPack(); - if (moveSideways != 0) { - actionPack.setStrafing(moveSideways > 0 ? 1 : -1); - } - } - - @Override - public void move(MovementType movementType, Vec3d movement) { - float newForward = (float) (moveForward - movement.z); - float newSideways = (float) (moveSideways - movement.x); - Vec3d newMovement = movement; - if ((newForward < 0 && moveForward > 0) || (newForward > 0 && moveForward < 0)) { - newMovement = new Vec3d(newMovement.x, newMovement.y, moveForward); - moveForward = 0; - getMinionActionPack().setForward(0); - }else { - moveForward = newForward; - } - if ((newSideways < 0 && moveSideways > 0) || (newSideways > 0 && moveSideways < 0)) { - newMovement = new Vec3d(newMovement.x, newMovement.y, moveSideways); - moveSideways = 0; - getMinionActionPack().setStrafing(0); - }else { - moveSideways = newSideways; - } - super.move(movementType, newMovement); - }*/ - @Override public void drop(ServerWorld world, DamageSource damageSource) { super.drop(world, damageSource); diff --git a/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java b/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java index 872015f..8557760 100644 --- a/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java +++ b/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java @@ -8,7 +8,6 @@ import com.llamalad7.mixinextras.sugar.Local; import com.mojang.authlib.GameProfile; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.fakeplayer.NetHandlerPlayServerFake; -import net.minecraft.nbt.NbtCompound; import net.minecraft.network.ClientConnection; import net.minecraft.network.packet.c2s.common.SyncedClientOptions; import net.minecraft.server.MinecraftServer; diff --git a/src/main/java/io/github/skippyall/minions/module/MinionModule.java b/src/main/java/io/github/skippyall/minions/module/MinionModule.java index 9bf4129..95b0281 100644 --- a/src/main/java/io/github/skippyall/minions/module/MinionModule.java +++ b/src/main/java/io/github/skippyall/minions/module/MinionModule.java @@ -5,6 +5,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import eu.pb4.polymer.core.api.other.PolymerComponent; import io.github.skippyall.minions.MinionRegistries; import io.github.skippyall.minions.Minions; +import io.github.skippyall.minions.minion.MinionRuntime; import io.github.skippyall.minions.program.instruction.InstructionType; import net.minecraft.component.ComponentType; import net.minecraft.registry.Registries; @@ -13,10 +14,11 @@ import net.minecraft.util.Identifier; import java.util.List; -public record MinionModule(List> instructions) { +public record MinionModule(List> instructions, List specialBehaviour) { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - MinionRegistries.INSTRUCTION_TYPES.getCodec().listOf().fieldOf("instructions").forGetter(MinionModule::instructions) + MinionRegistries.INSTRUCTION_TYPES.getCodec().listOf().fieldOf("instructions").forGetter(MinionModule::instructions), + Codec.STRING.listOf().fieldOf("specialBehaviour").forGetter(MinionModule::specialBehaviour) ).apply(instance, MinionModule::new) ); @@ -24,8 +26,13 @@ public record MinionModule(List> instructions) { public static final MinionModule EMPTY = new MinionModule(List.of()); - public MinionModule(List> instructions) { + public MinionModule(List> instructions) { + this(instructions, List.of()); + } + + public MinionModule(List> instructions, List specialBehaviour) { this.instructions = List.copyOf(instructions); + this.specialBehaviour = List.copyOf(specialBehaviour); } public static void register() { diff --git a/src/main/java/io/github/skippyall/minions/module/ModuleInventory.java b/src/main/java/io/github/skippyall/minions/module/ModuleInventory.java index 11a6d0b..b45184a 100644 --- a/src/main/java/io/github/skippyall/minions/module/ModuleInventory.java +++ b/src/main/java/io/github/skippyall/minions/module/ModuleInventory.java @@ -19,6 +19,8 @@ import java.util.Set; public class ModuleInventory extends SimpleInventory { private final Set modules = new HashSet<>(); + private final Set specialAbilities = new HashSet<>(); + public ModuleInventory() { super(27); } @@ -45,10 +47,12 @@ public class ModuleInventory extends SimpleInventory { public void updateModules() { modules.clear(); + specialAbilities.clear(); for (ItemStack heldStack : heldStacks) { MinionModule module = heldStack.get(MinionModule.COMPONENT_TYPE); if(module != null) { modules.add(module); + specialAbilities.addAll(module.specialBehaviour()); } } } @@ -62,14 +66,14 @@ public class ModuleInventory extends SimpleInventory { Inventories.writeData(view, heldStacks); } - public boolean hasModule(MinionModule module) { - return modules.contains(module); - } - public Collection getModules() { return modules; } + public boolean hasAbility(String ability) { + return specialAbilities.contains(ability); + } + public List> getAllInstructions() { ArrayList> instructionTypes = new ArrayList<>(); for(MinionModule module : modules) { diff --git a/src/main/java/io/github/skippyall/minions/module/ModuleInventoryScreenHandler.java b/src/main/java/io/github/skippyall/minions/module/ModuleInventoryScreenHandler.java index 2e325b6..79b5f1d 100644 --- a/src/main/java/io/github/skippyall/minions/module/ModuleInventoryScreenHandler.java +++ b/src/main/java/io/github/skippyall/minions/module/ModuleInventoryScreenHandler.java @@ -11,6 +11,7 @@ import net.minecraft.screen.slot.Slot; public class ModuleInventoryScreenHandler extends ScreenHandler { private final int rows = 3; private final ModuleInventory inventory; + public ModuleInventoryScreenHandler(int syncId, ModuleInventory inventory) { super(ScreenHandlerType.GENERIC_9X3, syncId); this.inventory = inventory; @@ -18,14 +19,13 @@ public class ModuleInventoryScreenHandler extends ScreenHandler { public ModuleInventoryScreenHandler(int syncId, PlayerInventory playerInventory, ModuleInventory inventory) { super(ScreenHandlerType.GENERIC_9X3, syncId); - int k; - int j; + GenericContainerScreenHandler.checkSize(inventory, 3 * 9); this.inventory = inventory; inventory.onOpen(playerInventory.player); - int i = (rows - 4) * 18; - for (j = 0; j < rows; ++j) { - for (k = 0; k < 9; ++k) { + + for (int j = 0; j < rows; ++j) { + for (int k = 0; k < 9; ++k) { this.addSlot(new Slot(inventory, k + j * 9, 8 + k * 18, 18 + j * 18) { @Override public boolean canInsert(ItemStack stack) { @@ -34,14 +34,8 @@ public class ModuleInventoryScreenHandler extends ScreenHandler { }); } } - for (j = 0; j < 3; ++j) { - for (k = 0; k < 9; ++k) { - this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 103 + j * 18 + i)); - } - } - for (j = 0; j < 9; ++j) { - this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 161 + i)); - } + + addPlayerSlots(playerInventory, 8, 85); } @Override diff --git a/src/main/java/io/github/skippyall/minions/program/InstructionRuntime.java b/src/main/java/io/github/skippyall/minions/program/InstructionRuntime.java index 71293b2..24f9a63 100644 --- a/src/main/java/io/github/skippyall/minions/program/InstructionRuntime.java +++ b/src/main/java/io/github/skippyall/minions/program/InstructionRuntime.java @@ -1,30 +1,43 @@ 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.ArgumentType; -import io.github.skippyall.minions.program.argument.Arguments; +import io.github.skippyall.minions.program.supplier.ValueSupplier; +import io.github.skippyall.minions.program.supplier.ValueSupplierList; +import io.github.skippyall.minions.program.supplier.ValueSupplierType; import io.github.skippyall.minions.program.instruction.InstructionType; -import io.github.skippyall.minions.program.returnvalue.ValueConsumerType; +import io.github.skippyall.minions.program.consumer.ValueConsumer; +import io.github.skippyall.minions.program.consumer.ValueConsumerList; +import io.github.skippyall.minions.program.consumer.ValueConsumerType; import net.minecraft.registry.Registry; public interface InstructionRuntime> { - Registry> getArgumentTypeRegistry(); + Registry> getArgumentTypeRegistry(); Registry> getInstructionTypeRegistry(); - Registry> getValueConsumerRegistry(); + Registry> getValueConsumerTypeRegistry(); - default Codec> getArgumentTypeCodec() { + default Codec> getArgumentTypeCodec() { return getArgumentTypeRegistry().getCodec(); } - default Codec> getArgumentCodec() { - return Arguments.createArgumentCodec(getArgumentTypeCodec()); + default Codec> getArgumentCodec() { + return ValueSupplier.createArgumentCodec(getArgumentTypeCodec()); } - default Codec> getArgumentListCodec() { - return ArgumentList.getCodec(getArgumentTypeCodec()); + default Codec> getArgumentListCodec() { + return ValueSupplierList.getCodec(getArgumentCodec()); + } + + default Codec> getValueConsumerTypeCodec() { + return getValueConsumerTypeRegistry().getCodec(); + } + + default Codec> getValueConsumerCodec() { + return ValueConsumer.createValueConsumerCodec(getValueConsumerTypeCodec()); + } + + default Codec> getValueConsumerListCodec() { + return ValueConsumerList.getCodec(getValueConsumerCodec()); } } diff --git a/src/main/java/io/github/skippyall/minions/program/argument/Argument.java b/src/main/java/io/github/skippyall/minions/program/argument/Argument.java deleted file mode 100644 index 0f0ee7f..0000000 --- a/src/main/java/io/github/skippyall/minions/program/argument/Argument.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.skippyall.minions.program.argument; - -import io.github.skippyall.minions.gui.GuiDisplay; -import io.github.skippyall.minions.program.InstructionRuntime; -import io.github.skippyall.minions.program.value.ValueType; -import org.jetbrains.annotations.Nullable; - -/** - * An Argument can be supplied to an instruction with a matching parameter. - * Its value is resolved at runtime and can vary between executions. - * Arguments are created exclusively by SpecificArgumentTypes. - * @param The type of the Argument's value - */ -public interface Argument> { - T resolve(R minion); - - GuiDisplay getDisplay(); - - ValueType getValueType(); - - ArgumentType getType(); - - default > @Nullable A cast(ValueType type) { - if(getValueType() == type) { - //noinspection unchecked - return (A) this; - } else { - return null; - } - } -} diff --git a/src/main/java/io/github/skippyall/minions/program/argument/ArgumentList.java b/src/main/java/io/github/skippyall/minions/program/argument/ArgumentList.java deleted file mode 100644 index 672ecb4..0000000 --- a/src/main/java/io/github/skippyall/minions/program/argument/ArgumentList.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.skippyall.minions.program.argument; - -import com.mojang.serialization.Codec; -import io.github.skippyall.minions.program.InstructionRuntime; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -public class ArgumentList> { - private final Map> arguments; - - public ArgumentList() { - arguments = new HashMap<>(); - } - - public ArgumentList(Map> arguments) { - this.arguments = new HashMap<>(arguments); - } - - public T getValue(Parameter parameter, R runtime) { - Argument argument = getArgument(parameter); - return argument != null ? argument.resolve(runtime) : null; - } - - public > A getArgument(Parameter parameter) { - Argument argument = arguments.get(parameter.name()); - return argument == null ? null : argument.cast(parameter.type()); - } - - public void setArgument(Parameter parameter, Argument argument) { - arguments.put(parameter.name(), argument); - } - - public boolean hasArgumentFor(Parameter parameter) { - return getArgument(parameter) != null; - } - - public boolean hasArgumentForAll(Collection> checkParameters) { - for(Parameter parameter : checkParameters) { - if(!hasArgumentFor(parameter)) { - return false; - } - } - return true; - } - - public static > Codec> getCodec(Codec> genericCodec) { - return Codec.unboundedMap(Codec.STRING, Arguments.createArgumentCodec(genericCodec)) - .xmap(ArgumentList::new, list -> list.arguments); - } -} diff --git a/src/main/java/io/github/skippyall/minions/program/argument/ArgumentType.java b/src/main/java/io/github/skippyall/minions/program/argument/ArgumentType.java deleted file mode 100644 index 0fbc0c8..0000000 --- a/src/main/java/io/github/skippyall/minions/program/argument/ArgumentType.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.skippyall.minions.program.argument; - -import com.mojang.serialization.Codec; -import io.github.skippyall.minions.program.InstructionRuntime; -import io.github.skippyall.minions.program.value.ValueType; -import net.minecraft.server.network.ServerPlayerEntity; -import org.jetbrains.annotations.Nullable; - -import java.util.concurrent.CompletableFuture; - -public abstract class ArgumentType> { - public abstract Codec> getCodec(ValueType type); - - public abstract CompletableFuture> openConfiguration(ServerPlayerEntity player, ValueType valueType, @Nullable Argument previous); -} diff --git a/src/main/java/io/github/skippyall/minions/program/argument/Arguments.java b/src/main/java/io/github/skippyall/minions/program/argument/Arguments.java deleted file mode 100644 index 19787d0..0000000 --- a/src/main/java/io/github/skippyall/minions/program/argument/Arguments.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.skippyall.minions.program.argument; - -import com.mojang.serialization.Codec; -import io.github.skippyall.minions.MinionRegistries; -import io.github.skippyall.minions.program.InstructionRuntime; - -public class Arguments { - public static > Codec> createArgumentCodec(Codec> codec) { - return codec.dispatch( - "type", - Argument::getType, - type -> - MinionRegistries.VALUE_TYPES.getCodec().>dispatch( - Argument::getValueType, - valueType -> type.getCodec(valueType).fieldOf("valueType") - ).fieldOf("valueType") - ); - } -} diff --git a/src/main/java/io/github/skippyall/minions/program/consumer/ValueConsumer.java b/src/main/java/io/github/skippyall/minions/program/consumer/ValueConsumer.java new file mode 100644 index 0000000..29a8e15 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/program/consumer/ValueConsumer.java @@ -0,0 +1,45 @@ +package io.github.skippyall.minions.program.consumer; + +import com.mojang.serialization.Codec; +import io.github.skippyall.minions.MinionRegistries; +import io.github.skippyall.minions.gui.GuiDisplay; +import io.github.skippyall.minions.program.InstructionRuntime; +import io.github.skippyall.minions.program.value.ValueType; +import org.jetbrains.annotations.Nullable; + +/** + * An ValueSupplier can be supplied to an instruction with a matching parameter. + * Its value is resolved at runtime and can vary between executions. + * ValueSuppliers are created exclusively by SpecificArgumentTypes. + * @param The type of the ValueSupplier's value + */ +public interface ValueConsumer> { + void consume(T value, R runtime); + + GuiDisplay getDisplay(); + + ValueType getValueType(); + + ValueConsumerType getType(); + + default > @Nullable A cast(ValueType type) { + if(getValueType() == type) { + //noinspection unchecked + return (A) this; + } else { + return null; + } + } + + static > Codec> createValueConsumerCodec(Codec> codec) { + return codec.dispatch( + "type", + ValueConsumer::getType, + type -> + MinionRegistries.VALUE_TYPES.getCodec().>dispatch( + ValueConsumer::getValueType, + valueType -> type.getCodec(valueType).fieldOf("valueType") + ).fieldOf("valueType") + ); + } +} diff --git a/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumerList.java b/src/main/java/io/github/skippyall/minions/program/consumer/ValueConsumerList.java similarity index 67% rename from src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumerList.java rename to src/main/java/io/github/skippyall/minions/program/consumer/ValueConsumerList.java index 867aa15..e39f140 100644 --- a/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumerList.java +++ b/src/main/java/io/github/skippyall/minions/program/consumer/ValueConsumerList.java @@ -1,8 +1,8 @@ -package io.github.skippyall.minions.program.returnvalue; +package io.github.skippyall.minions.program.consumer; import com.mojang.serialization.Codec; import io.github.skippyall.minions.program.InstructionRuntime; -import io.github.skippyall.minions.program.argument.Parameter; +import io.github.skippyall.minions.program.supplier.Parameter; import java.util.HashMap; import java.util.Map; @@ -27,8 +27,15 @@ public class ValueConsumerList> { valueConsumers.put(parameter.name(), consumer); } - public static > Codec> getCodec(Codec> genericCodec) { - return Codec.unboundedMap(Codec.STRING, ValueConsumers.createValueConsumersCodec(genericCodec)) + public void setValue(Parameter parameter, T value, R runtime) { + ValueConsumer consumer = getValueConsumer(parameter).cast(parameter.type()); + if (consumer != null) { + consumer.consume(value, runtime); + } + } + + public static > Codec> getCodec(Codec> valueConsumerCodec) { + return Codec.unboundedMap(Codec.STRING, valueConsumerCodec) .xmap(ValueConsumerList::new, list -> list.valueConsumers); } } diff --git a/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumerType.java b/src/main/java/io/github/skippyall/minions/program/consumer/ValueConsumerType.java similarity index 84% rename from src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumerType.java rename to src/main/java/io/github/skippyall/minions/program/consumer/ValueConsumerType.java index 0b9f9e1..ca470b7 100644 --- a/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumerType.java +++ b/src/main/java/io/github/skippyall/minions/program/consumer/ValueConsumerType.java @@ -1,8 +1,7 @@ -package io.github.skippyall.minions.program.returnvalue; +package io.github.skippyall.minions.program.consumer; 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.value.ValueType; import net.minecraft.server.network.ServerPlayerEntity; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java b/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java index bb330cc..aa56bf1 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java @@ -2,33 +2,36 @@ package io.github.skippyall.minions.program.instruction; import io.github.skippyall.minions.Minions; import io.github.skippyall.minions.program.InstructionRuntime; -import io.github.skippyall.minions.program.argument.ArgumentList; +import io.github.skippyall.minions.program.supplier.ValueSupplierList; +import io.github.skippyall.minions.program.consumer.ValueConsumerList; import net.minecraft.storage.ReadView; import net.minecraft.storage.WriteView; import org.jetbrains.annotations.Nullable; public class ConfiguredInstruction> { private final InstructionType instruction; - private final ArgumentList arguments; + private final ValueSupplierList arguments; + private final ValueConsumerList valueConsumers; private @Nullable InstructionExecution execution; private final String name; - private ConfiguredInstruction(InstructionType instruction, ArgumentList arguments, @Nullable InstructionExecution execution, String name) { + private ConfiguredInstruction(InstructionType instruction, ValueSupplierList arguments, ValueConsumerList valueConsumers, @Nullable InstructionExecution execution, String name) { this.instruction = instruction; this.arguments = arguments; + this.valueConsumers = valueConsumers; this.execution = execution; this.name = name; } public ConfiguredInstruction(InstructionType instruction, String name) { - this(instruction, new ArgumentList<>(), null, name); + this(instruction, new ValueSupplierList<>(), new ValueConsumerList<>(), null, name); } public InstructionType getInstruction() { return instruction; } - public ArgumentList getArguments() { + public ValueSupplierList getArguments() { return arguments; } @@ -75,7 +78,7 @@ public class ConfiguredInstruction> { public void stop(R minion) { if(isRunning()) { - execution.stop(minion); + execution.stop(minion, valueConsumers); execution = null; } } @@ -83,6 +86,7 @@ public class ConfiguredInstruction> { public void save(WriteView view, R minion) { view.put("instruction", minion.getInstructionTypeRegistry().getCodec(), instruction); view.put("arguments", minion.getArgumentListCodec(), arguments); + view.put("valueConsumers", minion.getValueConsumerListCodec(), valueConsumers); view.putBoolean("running", isRunning()); if(isRunning()) { execution.save(view.get("execution"), minion); @@ -92,7 +96,8 @@ public class ConfiguredInstruction> { public static > ConfiguredInstruction load(ReadView view, R minion, String name) { InstructionType instructionType = view.read("instruction", minion.getInstructionTypeRegistry().getCodec()).orElseThrow(); - ArgumentList arguments = view.read("arguments", minion.getArgumentListCodec()).orElseThrow(); + ValueSupplierList arguments = view.read("arguments", minion.getArgumentListCodec()).orElseGet(ValueSupplierList::new); + ValueConsumerList valueConsumers = view.read("valueConsumers", minion.getValueConsumerListCodec()).orElseGet(ValueConsumerList::new); boolean running = view.getBoolean("running", false); @@ -100,12 +105,12 @@ public class ConfiguredInstruction> { ReadView executionView = view.getReadView("execution"); try { InstructionExecution execution = instructionType.loadExecution(executionView, minion); - return new ConfiguredInstruction<>(instructionType, arguments, execution, name); + return new ConfiguredInstruction<>(instructionType, arguments, valueConsumers, execution, name); } catch (Exception e) { - + Minions.LOGGER.error("Error while loading execution", e); } } - return new ConfiguredInstruction<>(instructionType, arguments, null, name); + return new ConfiguredInstruction<>(instructionType, arguments, valueConsumers, null, name); } } diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/InstructionExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/InstructionExecution.java index ee84554..eb1ba34 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/InstructionExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/InstructionExecution.java @@ -1,7 +1,8 @@ package io.github.skippyall.minions.program.instruction; import io.github.skippyall.minions.program.InstructionRuntime; -import io.github.skippyall.minions.program.argument.ArgumentList; +import io.github.skippyall.minions.program.supplier.ValueSupplierList; +import io.github.skippyall.minions.program.consumer.ValueConsumerList; import net.minecraft.storage.ReadView; import net.minecraft.storage.WriteView; @@ -9,7 +10,7 @@ import net.minecraft.storage.WriteView; * Responsible for executing instructions. * When an instruction is executed: *
  • A new instance is created using the factory
  • - *
  • {@link InstructionExecution#readArguments(ArgumentList, R) readFromParameters} is called
  • + *
  • {@link InstructionExecution#readArguments(ValueSupplierList, R) readFromParameters} is called
  • *
  • {@link InstructionExecution#start(R) start} is called
  • */ public interface InstructionExecution> { @@ -32,19 +33,18 @@ public interface InstructionExecution> { /** * Stops this execution. Is called when isDone returns true, but it may also be called before that. - * In this case, the return value is ignored. * This should undo changes to the minion unless they are supposed to be permanent. * * @param runtime The runtime that was executing this instruction. */ - void stop(R runtime); + void stop(R runtime, ValueConsumerList valueConsumers); /** - * Initializes the execution with its arguments. + * Initializes the execution with its parameters. The parameters must be defined by the InstructionType * @param arguments The arguments to initialize the execution * @param runtime The runtime should be used to resolve the arguments */ - void readArguments(ArgumentList arguments, R runtime); + void readArguments(ValueSupplierList arguments, R runtime); /** * Saves the execution, e.g. when the server is closed. diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/InstructionType.java b/src/main/java/io/github/skippyall/minions/program/instruction/InstructionType.java index a6d64a3..c684524 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/InstructionType.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/InstructionType.java @@ -2,9 +2,8 @@ package io.github.skippyall.minions.program.instruction; import io.github.skippyall.minions.gui.GuiDisplay; import io.github.skippyall.minions.program.InstructionRuntime; -import io.github.skippyall.minions.program.argument.Parameter; -import io.github.skippyall.minions.program.argument.ArgumentList; -import io.github.skippyall.minions.program.value.ValueType; +import io.github.skippyall.minions.program.supplier.Parameter; +import io.github.skippyall.minions.program.supplier.ValueSupplierList; import net.minecraft.storage.ReadView; import java.util.Collection; @@ -14,31 +13,29 @@ import java.util.function.Supplier; public class InstructionType> { private final GuiDisplay display; private final Collection> parameters; + private final Collection> returnParameters; private final Supplier> executionFactory; - private InstructionType(GuiDisplay display, Supplier> executionFactory, Collection> parameters) { + public InstructionType(GuiDisplay display, Supplier> executionFactory, Collection> parameters, Collection> returnParameters) { this.display = display; - this.parameters = parameters; + this.parameters = List.copyOf(parameters); + this.returnParameters = List.copyOf(returnParameters); this.executionFactory = executionFactory; } - public static > InstructionType create(GuiDisplay display, Supplier> executionFactory, Collection> parameters) { - return new InstructionType<>(display, executionFactory, List.copyOf(parameters)); - } - - public static > InstructionType create(GuiDisplay display, Supplier> executionFactory, ValueType returnType, Parameter... parameters) { - return new InstructionType<>(display, executionFactory, List.of(parameters)); - } - public Collection> getParameters() { return parameters; } + public Collection> getReturnParameters() { + return returnParameters; + } + public GuiDisplay getDisplay() { return display; } - public InstructionExecution createExecution(ArgumentList parameters, R minion) { + public InstructionExecution createExecution(ValueSupplierList parameters, R minion) { InstructionExecution execution = executionFactory.get(); execution.readArguments(parameters, minion); return execution; diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/Instructions.java b/src/main/java/io/github/skippyall/minions/program/instruction/Instructions.java index 349df47..24d46cf 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/Instructions.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/Instructions.java @@ -3,47 +3,60 @@ package io.github.skippyall.minions.program.instruction; import io.github.skippyall.minions.MinionRegistries; import io.github.skippyall.minions.Minions; import io.github.skippyall.minions.gui.GuiDisplay; +import io.github.skippyall.minions.minion.MinionRuntime; 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.TurnExecution; import io.github.skippyall.minions.program.instruction.execution.WalkExecution; -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.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; +import java.util.Collection; +import java.util.List; import java.util.function.Function; import java.util.function.Supplier; public class Instructions { - public static final InstructionType WALK = register( + public static final InstructionType WALK = register( "walk", base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_BOOTS), base, true), WalkExecution::new, - ValueTypes.VOID, - WalkExecution.blocksToMoveParam + List.of(WalkExecution.blocksToMoveParam) ); - public static final InstructionType ATTACK = register( + public static final InstructionType TURN = register( + "turn", + base -> new GuiDisplay.ModelBased(Items.STRUCTURE_VOID, base, true), + TurnExecution::new, + List.of(TurnExecution.ANGLE, TurnExecution.DIRECTION) + ); + + public static final InstructionType ATTACK = register( "attack", base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.IRON_BOOTS), base, true), - () -> new ActionExecution(EntityPlayerActionPack.ActionType.ATTACK), - ValueTypes.VOID + () -> new ActionExecution(EntityPlayerActionPack.ActionType.ATTACK) ); - public static final InstructionType USE = register( + public static final InstructionType USE = register( "use", base -> new GuiDisplay.ModelBased(ModelIdUtil.getItemModelId(Items.LEVER), base, true), - () -> new ActionExecution(EntityPlayerActionPack.ActionType.USE), - ValueTypes.VOID + () -> new ActionExecution(EntityPlayerActionPack.ActionType.USE) ); - private static InstructionType register(String id, Function displayFunction, Supplier> factory, ValueType returnType, Parameter... parameters) { + private static InstructionType register(String id, Function displayFunction, Supplier> factory, Collection> parameters, Collection> returnParameters) { 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, new InstructionType<>(displayFunction.apply(identifier.toTranslationKey("instruction_type")), factory, parameters, returnParameters)); + } + + private static InstructionType register(String id, Function displayFunction, Supplier> factory, Collection> parameters) { + return register(id, displayFunction, factory, parameters, List.of()); + } + + private static InstructionType register(String id, Function displayFunction, Supplier> factory) { + return register(id, displayFunction, factory, List.of(), List.of()); } public static void register() { diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/execution/ActionExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/execution/ActionExecution.java index 504224a..3c100cc 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/execution/ActionExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/execution/ActionExecution.java @@ -1,12 +1,13 @@ package io.github.skippyall.minions.program.instruction.execution; +import io.github.skippyall.minions.minion.MinionRuntime; import io.github.skippyall.minions.minion.fakeplayer.EntityPlayerActionPack; -import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; -import io.github.skippyall.minions.program.argument.ArgumentList; +import io.github.skippyall.minions.program.consumer.ValueConsumerList; +import io.github.skippyall.minions.program.supplier.ValueSupplierList; import net.minecraft.storage.ReadView; import net.minecraft.storage.WriteView; -public class ActionExecution implements ContinuousInstructionExecution { +public class ActionExecution implements ContinuousInstructionExecution { private final EntityPlayerActionPack.ActionType action; public ActionExecution(EntityPlayerActionPack.ActionType action) { @@ -14,24 +15,23 @@ public class ActionExecution implements ContinuousInstructionExecution { } @Override - public void start(MinionFakePlayer minion) { - minion.getMinionActionPack().start(action, EntityPlayerActionPack.Action.continuous()); + public void start(MinionRuntime minion) { + minion.getMinion().getMinionActionPack().start(action, EntityPlayerActionPack.Action.continuous()); } @Override - public Void stop(MinionFakePlayer minion) { - minion.getMinionActionPack().stop(action); - return null; + public void stop(MinionRuntime minion, ValueConsumerList valueConsumers) { + minion.getMinion().getMinionActionPack().stop(action); } @Override - public void readArguments(ArgumentList parameters, MinionFakePlayer minion) {} + public void readArguments(ValueSupplierList parameters, MinionRuntime minion) {} @Override - public void save(WriteView view, MinionFakePlayer minion) {} + public void save(WriteView view, MinionRuntime minion) {} @Override - public void load(ReadView view, MinionFakePlayer minion) { - minion.getMinionActionPack().start(action, EntityPlayerActionPack.Action.continuous()); + public void load(ReadView view, MinionRuntime minion) { + minion.getMinion().getMinionActionPack().start(action, EntityPlayerActionPack.Action.continuous()); } } diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/execution/ContinuousInstructionExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/execution/ContinuousInstructionExecution.java index b2c953c..bd7e1b8 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/execution/ContinuousInstructionExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/execution/ContinuousInstructionExecution.java @@ -1,11 +1,11 @@ package io.github.skippyall.minions.program.instruction.execution; -import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.program.InstructionRuntime; import io.github.skippyall.minions.program.instruction.InstructionExecution; -public interface ContinuousInstructionExecution extends InstructionExecution { +public interface ContinuousInstructionExecution> extends InstructionExecution { @Override - default boolean isDone(MinionFakePlayer minion) { + default boolean isDone(R minion) { return false; } } diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/execution/TimedInstructionExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/execution/TimedInstructionExecution.java index 3eb56d5..47ec80a 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/execution/TimedInstructionExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/execution/TimedInstructionExecution.java @@ -1,6 +1,6 @@ package io.github.skippyall.minions.program.instruction.execution; -import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.program.InstructionRuntime; import io.github.skippyall.minions.program.instruction.InstructionExecution; import net.minecraft.storage.ReadView; import net.minecraft.storage.WriteView; @@ -10,7 +10,7 @@ import net.minecraft.storage.WriteView; * The timer must be set with setTimer when reading from parameters. * Saving and loading of the timer is automatic if the super method is called by the subclass. */ -public abstract class TimedInstructionExecution implements InstructionExecution { +public abstract class TimedInstructionExecution> implements InstructionExecution { int timer; public int getTimer() { @@ -22,22 +22,22 @@ public abstract class TimedInstructionExecution implements InstructionExecuti } @Override - public void tick(MinionFakePlayer minion) { + public void tick(R minion) { timer--; } @Override - public boolean isDone(MinionFakePlayer minion) { + public boolean isDone(R minion) { return timer > 0; } @Override - public void save(WriteView view, MinionFakePlayer minion) { + public void save(WriteView view, R minion) { view.putInt("timer", timer); } @Override - public void load(ReadView view, MinionFakePlayer minion) { + public void load(ReadView view, R minion) { timer = view.getInt("timer", 0); } } diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/execution/TurnExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/execution/TurnExecution.java index 273563e..24b5aed 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/execution/TurnExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/execution/TurnExecution.java @@ -3,9 +3,10 @@ package io.github.skippyall.minions.program.instruction.execution; import com.mojang.serialization.Codec; import io.github.skippyall.minions.gui.Displayable; import io.github.skippyall.minions.gui.GuiDisplay; -import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; -import io.github.skippyall.minions.program.argument.ArgumentList; -import io.github.skippyall.minions.program.argument.Parameter; +import io.github.skippyall.minions.minion.MinionRuntime; +import io.github.skippyall.minions.program.consumer.ValueConsumerList; +import io.github.skippyall.minions.program.supplier.ValueSupplierList; +import io.github.skippyall.minions.program.supplier.Parameter; import io.github.skippyall.minions.program.instruction.InstructionExecution; import io.github.skippyall.minions.program.value.ValueTypes; import net.minecraft.storage.ReadView; @@ -14,7 +15,7 @@ import net.minecraft.util.StringIdentifiable; import java.util.UUID; -public class TurnExecution implements InstructionExecution { +public class TurnExecution implements InstructionExecution { public static final Parameter ANGLE = new Parameter<>("maxAngle", ValueTypes.FLOAT); public static final Parameter DIRECTION = new Parameter<>("direction", ValueTypes.TURN_DIRECTION); @@ -25,37 +26,36 @@ public class TurnExecution implements InstructionExecution valueConsumers) { } @Override - public void readArguments(ArgumentList arguments, MinionFakePlayer minion) { + public void readArguments(ValueSupplierList arguments, MinionRuntime minion) { maxAngle = arguments.getValue(ANGLE, minion); direction = arguments.getValue(DIRECTION, minion); } @Override - public void save(WriteView view, MinionFakePlayer minion) { + public void save(WriteView view, MinionRuntime minion) { view.putFloat("maxAngle", maxAngle); view.put("direction", TurnDirection.CODEC, direction); } @Override - public void load(ReadView view, MinionFakePlayer minion) { + public void load(ReadView view, MinionRuntime minion) { maxAngle = view.getFloat("maxAngle", 0); direction = view.read("direction", TurnDirection.CODEC).orElseThrow(); } diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/execution/WalkExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/execution/WalkExecution.java index a2ba949..9be8b0f 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/execution/WalkExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/execution/WalkExecution.java @@ -1,52 +1,53 @@ package io.github.skippyall.minions.program.instruction.execution; -import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.minion.MinionRuntime; +import io.github.skippyall.minions.program.consumer.ValueConsumerList; import io.github.skippyall.minions.program.instruction.InstructionExecution; -import io.github.skippyall.minions.program.argument.Parameter; -import io.github.skippyall.minions.program.argument.ArgumentList; +import io.github.skippyall.minions.program.supplier.Parameter; +import io.github.skippyall.minions.program.supplier.ValueSupplierList; import io.github.skippyall.minions.program.value.ValueTypes; import net.minecraft.entity.MovementType; import net.minecraft.storage.ReadView; import net.minecraft.storage.WriteView; -public class WalkExecution implements InstructionExecution { +public class WalkExecution implements InstructionExecution { public static final Parameter blocksToMoveParam = new Parameter<>("blocksToMove", ValueTypes.FLOAT); - private final float ACCURACY = 1F / 32F; + private static final float ACCURACY = 1F / 32F; private float totalBlocksToMove; private float blocksMoved; @Override - public void tick(MinionFakePlayer minion) { - float speed = Math.min(minion.getMovementSpeed(), totalBlocksToMove - blocksMoved); - minion.move(MovementType.SELF, minion.getHorizontalFacing().getDoubleVector().normalize().multiply(speed)); + public void tick(MinionRuntime minion) { + float speed = Math.min(minion.getMinion().getMovementSpeed(), totalBlocksToMove - blocksMoved); + minion.getMinion().move(MovementType.SELF, minion.getMinion().getHorizontalFacing().getDoubleVector().normalize().multiply(speed)); blocksMoved += speed; } @Override - public boolean isDone(MinionFakePlayer minion) { + public boolean isDone(MinionRuntime minion) { return totalBlocksToMove - blocksMoved < ACCURACY; } @Override - public Void stop(MinionFakePlayer minion) { - return null; + public void stop(MinionRuntime minion, ValueConsumerList valueConsumers) { + } @Override - public void readArguments(ArgumentList parameters, MinionFakePlayer minion) { + public void readArguments(ValueSupplierList parameters, MinionRuntime minion) { totalBlocksToMove = parameters.getValue(blocksToMoveParam, minion); blocksMoved = 0; } @Override - public void save(WriteView view, MinionFakePlayer minion) { + public void save(WriteView view, MinionRuntime minion) { view.putFloat("totalBlocksToMove", totalBlocksToMove); view.putFloat("blocksMoved", blocksMoved); } @Override - public void load(ReadView view, MinionFakePlayer minion) { + public void load(ReadView view, MinionRuntime minion) { totalBlocksToMove = view.getFloat("totalBlocksToMove", 0F); blocksMoved = view.getFloat("blocksMoved", 0F); } diff --git a/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumer.java b/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumer.java deleted file mode 100644 index 18d9e35..0000000 --- a/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumer.java +++ /dev/null @@ -1,32 +0,0 @@ -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.ArgumentType; -import io.github.skippyall.minions.program.value.ValueType; -import org.jetbrains.annotations.Nullable; - -/** - * An Argument can be supplied to an instruction with a matching parameter. - * Its value is resolved at runtime and can vary between executions. - * Arguments are created exclusively by SpecificArgumentTypes. - * @param The type of the Argument's value - */ -public interface ValueConsumer> { - void consume(T value, R runtime); - - GuiDisplay getDisplay(); - - ValueType getValueType(); - - ValueConsumerType getType(); - - default > @Nullable A cast(ValueType type) { - if(getValueType() == type) { - //noinspection unchecked - return (A) this; - } else { - return null; - } - } -} diff --git a/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumers.java b/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumers.java deleted file mode 100644 index fb1e76d..0000000 --- a/src/main/java/io/github/skippyall/minions/program/returnvalue/ValueConsumers.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.skippyall.minions.program.returnvalue; - -import com.mojang.serialization.Codec; -import io.github.skippyall.minions.MinionRegistries; -import io.github.skippyall.minions.Minions; -import io.github.skippyall.minions.minion.MinionRuntime; -import io.github.skippyall.minions.program.InstructionRuntime; -import io.github.skippyall.minions.program.argument.Argument; -import net.minecraft.registry.Registry; -import net.minecraft.util.Identifier; - -public class ValueConsumers { - public static > Codec> createValueConsumersCodec(Codec> codec) { - return codec.dispatch( - "type", - ValueConsumer::getType, - type -> - MinionRegistries.VALUE_TYPES.getCodec().>dispatch( - ValueConsumer::getValueType, - valueType -> type.getCodec(valueType).fieldOf("valueType") - ).fieldOf("valueType") - ); - } -} diff --git a/src/main/java/io/github/skippyall/minions/program/argument/Parameter.java b/src/main/java/io/github/skippyall/minions/program/supplier/Parameter.java similarity index 94% rename from src/main/java/io/github/skippyall/minions/program/argument/Parameter.java rename to src/main/java/io/github/skippyall/minions/program/supplier/Parameter.java index 5e5eede..20abec5 100644 --- a/src/main/java/io/github/skippyall/minions/program/argument/Parameter.java +++ b/src/main/java/io/github/skippyall/minions/program/supplier/Parameter.java @@ -1,4 +1,4 @@ -package io.github.skippyall.minions.program.argument; +package io.github.skippyall.minions.program.supplier; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; diff --git a/src/main/java/io/github/skippyall/minions/program/argument/ValueArgument.java b/src/main/java/io/github/skippyall/minions/program/supplier/ValueArgument.java similarity index 82% rename from src/main/java/io/github/skippyall/minions/program/argument/ValueArgument.java rename to src/main/java/io/github/skippyall/minions/program/supplier/ValueArgument.java index b9b1814..e168ede 100644 --- a/src/main/java/io/github/skippyall/minions/program/argument/ValueArgument.java +++ b/src/main/java/io/github/skippyall/minions/program/supplier/ValueArgument.java @@ -1,14 +1,13 @@ -package io.github.skippyall.minions.program.argument; +package io.github.skippyall.minions.program.supplier; 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; /** - * An argument that always resolves to a fixed value + * An supplier that always resolves to a fixed value */ -public class ValueArgument> implements Argument { +public class ValueArgument> implements ValueSupplier { private final ValueArgumentType type; private final ValueType valueType; private final T value; diff --git a/src/main/java/io/github/skippyall/minions/program/argument/ValueArgumentType.java b/src/main/java/io/github/skippyall/minions/program/supplier/ValueArgumentType.java similarity index 77% rename from src/main/java/io/github/skippyall/minions/program/argument/ValueArgumentType.java rename to src/main/java/io/github/skippyall/minions/program/supplier/ValueArgumentType.java index f511166..148a1b9 100644 --- a/src/main/java/io/github/skippyall/minions/program/argument/ValueArgumentType.java +++ b/src/main/java/io/github/skippyall/minions/program/supplier/ValueArgumentType.java @@ -1,4 +1,4 @@ -package io.github.skippyall.minions.program.argument; +package io.github.skippyall.minions.program.supplier; import com.mojang.serialization.Codec; import io.github.skippyall.minions.program.InstructionRuntime; @@ -8,17 +8,17 @@ import org.jetbrains.annotations.Nullable; import java.util.concurrent.CompletableFuture; -public class ValueArgumentType> extends ArgumentType { +public class ValueArgumentType> extends ValueSupplierType { @Override public Codec> getCodec(ValueType valueType) { return valueType.codec().xmap(value -> new ValueArgument<>(this, valueType, value), ValueArgument::getValue); } @Override - public CompletableFuture> openConfiguration(ServerPlayerEntity player, ValueType valueType, @Nullable Argument previousArgument) { + public CompletableFuture> openConfiguration(ServerPlayerEntity player, ValueType valueType, @Nullable ValueSupplier previousValueSupplier) { return valueType.openValueDialog( player, - previousArgument instanceof ValueArgument val ? val.getValue() : valueType.defaultValue() + previousValueSupplier instanceof ValueArgument val ? val.getValue() : valueType.defaultValue() ).thenApply(value -> new ValueArgument<>(this, valueType, value)); } } diff --git a/src/main/java/io/github/skippyall/minions/program/supplier/ValueSupplier.java b/src/main/java/io/github/skippyall/minions/program/supplier/ValueSupplier.java new file mode 100644 index 0000000..32b3e24 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/program/supplier/ValueSupplier.java @@ -0,0 +1,45 @@ +package io.github.skippyall.minions.program.supplier; + +import com.mojang.serialization.Codec; +import io.github.skippyall.minions.MinionRegistries; +import io.github.skippyall.minions.gui.GuiDisplay; +import io.github.skippyall.minions.program.InstructionRuntime; +import io.github.skippyall.minions.program.value.ValueType; +import org.jetbrains.annotations.Nullable; + +/** + * An ValueSupplier can be supplied to an instruction with a matching parameter. + * Its value is resolved at runtime and can vary between executions. + * ValueSuppliers are created exclusively by SpecificArgumentTypes. + * @param The type of the ValueSupplier's value + */ +public interface ValueSupplier> { + T resolve(R minion); + + GuiDisplay getDisplay(); + + ValueType getValueType(); + + ValueSupplierType getType(); + + default > @Nullable A cast(ValueType type) { + if(getValueType() == type) { + //noinspection unchecked + return (A) this; + } else { + return null; + } + } + + static > Codec> createArgumentCodec(Codec> codec) { + return codec.dispatch( + "type", + ValueSupplier::getType, + type -> + MinionRegistries.VALUE_TYPES.getCodec().>dispatch( + ValueSupplier::getValueType, + valueType -> type.getCodec(valueType).fieldOf("valueType") + ).fieldOf("valueType") + ); + } +} diff --git a/src/main/java/io/github/skippyall/minions/program/supplier/ValueSupplierList.java b/src/main/java/io/github/skippyall/minions/program/supplier/ValueSupplierList.java new file mode 100644 index 0000000..8d778f0 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/program/supplier/ValueSupplierList.java @@ -0,0 +1,52 @@ +package io.github.skippyall.minions.program.supplier; + +import com.mojang.serialization.Codec; +import io.github.skippyall.minions.program.InstructionRuntime; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class ValueSupplierList> { + private final Map> arguments; + + public ValueSupplierList() { + arguments = new HashMap<>(); + } + + public ValueSupplierList(Map> arguments) { + this.arguments = new HashMap<>(arguments); + } + + public T getValue(Parameter parameter, R runtime) { + ValueSupplier valueSupplier = getArgument(parameter); + return valueSupplier != null ? valueSupplier.resolve(runtime) : null; + } + + public > A getArgument(Parameter parameter) { + ValueSupplier valueSupplier = arguments.get(parameter.name()); + return valueSupplier == null ? null : valueSupplier.cast(parameter.type()); + } + + public void setArgument(Parameter parameter, ValueSupplier valueSupplier) { + arguments.put(parameter.name(), valueSupplier); + } + + public boolean hasArgumentFor(Parameter parameter) { + return getArgument(parameter) != null; + } + + public boolean hasArgumentForAll(Collection> checkParameters) { + for(Parameter parameter : checkParameters) { + if(!hasArgumentFor(parameter)) { + return false; + } + } + return true; + } + + public static > Codec> getCodec(Codec> argumentCodec) { + return Codec.unboundedMap(Codec.STRING, argumentCodec) + .xmap(ValueSupplierList::new, list -> list.arguments); + } +} diff --git a/src/main/java/io/github/skippyall/minions/program/supplier/ValueSupplierType.java b/src/main/java/io/github/skippyall/minions/program/supplier/ValueSupplierType.java new file mode 100644 index 0000000..eb50215 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/program/supplier/ValueSupplierType.java @@ -0,0 +1,15 @@ +package io.github.skippyall.minions.program.supplier; + +import com.mojang.serialization.Codec; +import io.github.skippyall.minions.program.InstructionRuntime; +import io.github.skippyall.minions.program.value.ValueType; +import net.minecraft.server.network.ServerPlayerEntity; +import org.jetbrains.annotations.Nullable; + +import java.util.concurrent.CompletableFuture; + +public abstract class ValueSupplierType> { + public abstract Codec> getCodec(ValueType type); + + public abstract CompletableFuture> openConfiguration(ServerPlayerEntity player, ValueType valueType, @Nullable ValueSupplier previous); +} diff --git a/src/main/resources/data/minions/tags/block/mineable/pickaxe.json b/src/main/resources/data/minions/tags/block/mineable/pickaxe.json new file mode 100644 index 0000000..8d8bfe4 --- /dev/null +++ b/src/main/resources/data/minions/tags/block/mineable/pickaxe.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minions:minion_trigger" + ] +} \ No newline at end of file