Listen up!
This commit is contained in:
+18
-8
@@ -6,16 +6,24 @@ plugins {
|
||||
version = project.mod_version
|
||||
group = project.maven_group
|
||||
|
||||
loom {
|
||||
accessWidenerPath = file("src/main/resources/minions.accesswidener")
|
||||
}
|
||||
|
||||
base {
|
||||
archivesName = project.archives_base_name
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = file("src/main/resources/minions.accesswidener")
|
||||
splitEnvironmentSourceSets()
|
||||
|
||||
mods {
|
||||
minions {
|
||||
sourceSet sourceSets.main
|
||||
sourceSet sourceSets.client
|
||||
}
|
||||
}
|
||||
|
||||
runs.forEach {
|
||||
it.vmArg("-XX:+AllowEnhancedClassRedefinition")
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -40,8 +48,6 @@ 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"
|
||||
@@ -49,7 +55,11 @@ dependencies {
|
||||
|
||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
|
||||
modImplementation "eu.pb4:polymer-core:${project.polymer_version}"
|
||||
modImplementation "eu.pb4:polymer-virtual-entity:${project.polymer_version}"
|
||||
modImplementation "eu.pb4:polymer-resource-pack:${project.polymer_version}"
|
||||
modLocalRuntime "eu.pb4:polymer-autohost:${project.polymer_version}"
|
||||
modImplementation include("eu.pb4:sgui:${project.sgui_version}")
|
||||
modImplementation include("xyz.nucleoid:server-translations-api:${project.server_translations_version}")
|
||||
|
||||
@@ -94,14 +104,14 @@ java {
|
||||
|
||||
jar {
|
||||
from("LICENSE") {
|
||||
rename { "${it}_${project.archivesBaseName}"}
|
||||
rename { "${it}_${project.archives_base_name}"}
|
||||
}
|
||||
}
|
||||
|
||||
// configure the maven publication
|
||||
publishing {
|
||||
publications {
|
||||
minions (MavenPublication) {
|
||||
maven (MavenPublication) {
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G
|
||||
yarn_mappings=1.21.7+build.2
|
||||
|
||||
# Mod Properties
|
||||
mod_version = 0.2.1-SNAPSHOT
|
||||
mod_version = 1.0.0-SNAPSHOT-1
|
||||
maven_group = io.github.skippyall
|
||||
archives_base_name = Minions
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.github.skippyall.minions.client;
|
||||
|
||||
import eu.pb4.polymer.networking.api.client.PolymerClientNetworking;
|
||||
import io.github.skippyall.minions.MinionBlocks;
|
||||
import io.github.skippyall.minions.util.PolymerUtil;
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.BlockRenderLayerMap;
|
||||
import net.minecraft.client.render.BlockRenderLayer;
|
||||
|
||||
public class MinionsClient implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
BlockRenderLayerMap.putBlock(MinionBlocks.MINION_TRIGGER_BLOCK, BlockRenderLayer.TRANSLUCENT);
|
||||
|
||||
PolymerClientNetworking.registerCommonHandler(PolymerUtil.VersionSyncPayload.class, (client, handler, payload) -> {});
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -6,6 +6,7 @@ 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.block.piston.PistonBehavior;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
@@ -13,17 +14,17 @@ import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class MinionRegistration {
|
||||
public class MinionBlocks {
|
||||
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()
|
||||
.nonOpaque()
|
||||
.breakInstantly()
|
||||
.sounds(BlockSoundGroup.STONE)
|
||||
.pistonBehavior(PistonBehavior.DESTROY)
|
||||
)
|
||||
);
|
||||
public static final BlockEntityType<MinionTriggerBlockEntity> MINION_TRIGGER_BE_TYPE =
|
||||
@@ -2,11 +2,13 @@ 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.block.MinionTriggerBlockItem;
|
||||
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 io.github.skippyall.minions.reference.ReferenceItem;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.component.type.DamageResistantComponent;
|
||||
import net.minecraft.entity.damage.DamageType;
|
||||
@@ -45,13 +47,13 @@ public class MinionItems {
|
||||
public static final SimplePolymerItem MOVE_MODULE = registerModule(
|
||||
Identifier.of(MOD_ID, "move_module"),
|
||||
Items.IRON_BOOTS,
|
||||
List.of(Instructions.WALK, Instructions.TURN)
|
||||
List.of(Instructions.WALK, Instructions.WALK_CONTINUOUS, Instructions.TURN, Instructions.TURN_VECTOR)
|
||||
);
|
||||
|
||||
public static final SimplePolymerItem ATTACK_MODULE = registerModule(
|
||||
Identifier.of(MOD_ID, "attack_module"),
|
||||
Items.IRON_PICKAXE,
|
||||
List.of(Instructions.ATTACK)
|
||||
List.of(Instructions.ATTACK, Instructions.MINE_BLOCK)
|
||||
);
|
||||
|
||||
public static final SimplePolymerItem INTERACT_MODULE = registerModule(
|
||||
@@ -69,10 +71,12 @@ public class MinionItems {
|
||||
|
||||
public static final PolymerBlockItem MINION_TRIGGER_ITEM =
|
||||
registerItem(
|
||||
MinionRegistration.MINION_TRIGGER_ID,
|
||||
settings -> new PolymerBlockItem(MinionRegistration.MINION_TRIGGER_BLOCK, settings, Items.GOLD_BLOCK)
|
||||
MinionBlocks.MINION_TRIGGER_ID,
|
||||
settings -> new MinionTriggerBlockItem(MinionBlocks.MINION_TRIGGER_BLOCK, settings, Items.COMPARATOR)
|
||||
);
|
||||
|
||||
public static final ReferenceItem REFERENCE_ITEM = registerItem(Identifier.of(MOD_ID, "reference"), ReferenceItem::new);
|
||||
|
||||
public static <T extends Item> T registerItem(Identifier identifier, Function<Item.Settings, T> constructor, Item.Settings settings) {
|
||||
T item = constructor.apply(settings.registryKey(RegistryKey.of(RegistryKeys.ITEM, identifier)));
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package io.github.skippyall.minions;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class MinionMixinConfigPlugin implements IMixinConfigPlugin {
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRefMapperConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||
if(mixinClassName.startsWith("io.github.skippyall.mixins.compat.universal_graves.")) {
|
||||
return FabricLoader.getInstance().isModLoaded("universal-universal_graves");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,49 @@
|
||||
package io.github.skippyall.minions;
|
||||
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import io.github.skippyall.minions.docs.ReferenceEntry;
|
||||
import io.github.skippyall.minions.gui.GuiDisplay;
|
||||
import io.github.skippyall.minions.minion.MinionListener;
|
||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||
import io.github.skippyall.minions.minion.skin.SkinProvider;
|
||||
import io.github.skippyall.minions.program.instruction.ConfiguredInstructionListener;
|
||||
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 io.github.skippyall.minions.reference.Reference;
|
||||
import net.fabricmc.fabric.api.event.registry.DynamicRegistries;
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.SimpleRegistry;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class MinionRegistries {
|
||||
public static final Registry<ValueType<?>> VALUE_TYPES = registry("value_type");
|
||||
public static final Registry<ValueSupplierType<MinionRuntime>> ARGUMENT_TYPES = registry("argument_type");
|
||||
public static final Registry<ValueSupplierType<MinionRuntime>> VALUE_SUPPLIER_TYPES = registry("value_supplier_type");
|
||||
public static final Registry<ValueConsumerType<MinionRuntime>> VALUE_CONSUMER_TYPES = registry("value_consumer_type");
|
||||
public static final Registry<InstructionType<MinionRuntime>> INSTRUCTION_TYPES = registry("instruction_type");
|
||||
public static final Registry<SkinProvider> SKIN_PROVIDERS = registry("skin_providers");
|
||||
public static final Registry<SkinProvider> SKIN_PROVIDERS = registry("skin_provider");
|
||||
public static final Registry<Codec<? extends GuiDisplay>> GUI_DISPLAY_TYPE = registry("gui_display_type");
|
||||
public static final Registry<Codec<? extends ConfiguredInstructionListener>> INSTRUCTION_LISTENER_CODECS = registry("instruction_listener_codec");
|
||||
public static final Registry<Codec<? extends MinionListener>> MINION_LISTENER_CODECS = registry("minion_listener_codec");
|
||||
public static final Registry<MapCodec<? extends Reference>> REFERENCE_CODEC = registry("reference_codec");
|
||||
|
||||
public static final RegistryKey<Registry<GuiDisplay>> GUI_DISPLAY = key("gui_display");
|
||||
public static final RegistryKey<Registry<ReferenceEntry>> REFERENCE_ENTRY = key("reference_entry");
|
||||
|
||||
private static <T> Registry<T> registry(String id) {
|
||||
return new SimpleRegistry<>(RegistryKey.ofRegistry(Identifier.of(Minions.MOD_ID, id)), Lifecycle.stable());
|
||||
return FabricRegistryBuilder.<T>createSimple(key(id)).attribute(RegistryAttribute.OPTIONAL).buildAndRegister();
|
||||
}
|
||||
|
||||
private static <T> RegistryKey<Registry<T>> key(String name) {
|
||||
return RegistryKey.ofRegistry(Identifier.of(Minions.MOD_ID, name));
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
DynamicRegistries.register(GUI_DISPLAY, GuiDisplay.CODEC);
|
||||
DynamicRegistries.register(REFERENCE_ENTRY, ReferenceEntry.CODEC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package io.github.skippyall.minions;
|
||||
|
||||
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
|
||||
import io.github.skippyall.minions.command.MinionsCommand;
|
||||
import io.github.skippyall.minions.gui.GuiDisplay;
|
||||
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
||||
import io.github.skippyall.minions.minion.MinionData;
|
||||
import io.github.skippyall.minions.minion.MinionPersistentState;
|
||||
import io.github.skippyall.minions.minion.skin.SkinProviders;
|
||||
import io.github.skippyall.minions.module.MinionModule;
|
||||
import io.github.skippyall.minions.program.instruction.Instructions;
|
||||
import io.github.skippyall.minions.program.supplier.ValueSuppliers;
|
||||
import io.github.skippyall.minions.program.value.ValueTypes;
|
||||
import io.github.skippyall.minions.util.PolymerUtil;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
@@ -21,11 +25,23 @@ public class Minions implements ModInitializer {
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
MinionRegistries.register();
|
||||
|
||||
Instructions.register();
|
||||
ValueSuppliers.register();
|
||||
ValueTypes.register();
|
||||
SkinProviders.register();
|
||||
GuiDisplay.register();
|
||||
|
||||
MinionData.register();
|
||||
MinionModule.register();
|
||||
|
||||
MinionBlocks.register();
|
||||
MinionItems.register();
|
||||
MinionCreativeTab.registerGroup();
|
||||
|
||||
PolymerUtil.register();
|
||||
|
||||
ServerLifecycleEvents.SERVER_STARTED.register(server -> {
|
||||
MinionPersistentState.create(server);
|
||||
MinionPersistentState.INSTANCE.getMinionData().forEach((uuid, data) -> {
|
||||
@@ -39,11 +55,6 @@ public class Minions implements ModInitializer {
|
||||
MinionsCommand.register(commandDispatcher);
|
||||
});
|
||||
|
||||
ValueTypes.register();
|
||||
SkinProviders.register();
|
||||
|
||||
MinionRegistration.register();
|
||||
MinionItems.register();
|
||||
MinionCreativeTab.registerGroup();
|
||||
PolymerResourcePackUtils.addModAssets(Minions.MOD_ID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
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"));
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package io.github.skippyall.minions.block;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import io.github.skippyall.minions.minion.MinionListener;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class BlockEntityMinionListener implements MinionListener {
|
||||
protected RegistryKey<World> worldKey;
|
||||
protected BlockPos pos;
|
||||
|
||||
public BlockEntityMinionListener(RegistryKey<World> worldKey, BlockPos pos) {
|
||||
this.worldKey = worldKey;
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
public static final Codec<BlockEntityMinionListener> CODEC = RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
World.CODEC.fieldOf("world").forGetter(listener -> listener.worldKey),
|
||||
BlockPos.CODEC.fieldOf("pos").forGetter(listener -> listener.pos)
|
||||
).apply(instance, BlockEntityMinionListener::new));
|
||||
|
||||
|
||||
private BlockEntityState getBlockEntityState(MinecraftServer server) {
|
||||
World world = server.getWorld(worldKey);
|
||||
if(world == null || !world.isPosLoaded(pos)) {
|
||||
return BlockEntityState.UNLOADED;
|
||||
}
|
||||
|
||||
if(world.getBlockEntity(pos) instanceof MinionListeningBlockEntity) {
|
||||
return BlockEntityState.LOADED;
|
||||
} else {
|
||||
return BlockEntityState.REMOVED;
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<MinionListeningBlockEntity> getBlockEntity(MinecraftServer server) {
|
||||
World world = server.getWorld(worldKey);
|
||||
if(world != null && world.isPosLoaded(pos) && world.getBlockEntity(pos) instanceof MinionListeningBlockEntity be) {
|
||||
return Optional.of(be);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public enum BlockEntityState {
|
||||
LOADED,
|
||||
REMOVED,
|
||||
UNLOADED
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package io.github.skippyall.minions.block;
|
||||
|
||||
import io.github.skippyall.minions.minion.MinionListener;
|
||||
|
||||
public interface MinionListeningBlockEntity extends MinionListener {
|
||||
|
||||
}
|
||||
@@ -2,67 +2,118 @@ 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 eu.pb4.polymer.core.api.utils.PolymerClientDecoded;
|
||||
import eu.pb4.polymer.core.api.utils.PolymerKeepModel;
|
||||
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
|
||||
import eu.pb4.polymer.virtualentity.api.BlockWithElementHolder;
|
||||
import eu.pb4.polymer.virtualentity.api.ElementHolder;
|
||||
import eu.pb4.polymer.virtualentity.api.elements.ItemDisplayElement;
|
||||
import io.github.skippyall.minions.MinionBlocks;
|
||||
import io.github.skippyall.minions.Minions;
|
||||
import io.github.skippyall.minions.minion.MinionPersistentState;
|
||||
import io.github.skippyall.minions.reference.InstructionReference;
|
||||
import io.github.skippyall.minions.reference.Reference;
|
||||
import io.github.skippyall.minions.util.PolymerUtil;
|
||||
import net.minecraft.block.AbstractRedstoneGateBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.BlockWithEntity;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.block.SideShapeType;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.BooleanProperty;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldView;
|
||||
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 class MinionTriggerBlock extends BlockWithEntity implements PolymerBlock, PolymerKeepModel, PolymerClientDecoded, BlockWithElementHolder {
|
||||
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 static final VoxelShape SHAPE = Block.createColumnShape(16.0, 0.0, 2.0);
|
||||
|
||||
public MinionTriggerBlock(Settings settings) {
|
||||
super(settings);
|
||||
setDefaultState(getDefaultState().with(POWERED, false).with(RUNNING, false));
|
||||
setDefaultState(getDefaultState().with(POWERED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||
return SHAPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
|
||||
BlockPos blockPos = pos.down();
|
||||
return this.canPlaceAbove(world, blockPos, world.getBlockState(blockPos));
|
||||
}
|
||||
|
||||
protected boolean canPlaceAbove(WorldView world, BlockPos pos, BlockState state) {
|
||||
return state.isSideSolid(world, pos, Direction.UP, SideShapeType.RIGID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
builder.add(POWERED, RUNNING);
|
||||
builder.add(POWERED);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ActionResult onUseWithItem(ItemStack stack, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||
if(stack.get(Reference.COMPONENT_TYPE) instanceof InstructionReference instruction) {
|
||||
world.getBlockEntity(pos, MinionBlocks.MINION_TRIGGER_BE_TYPE).ifPresent(be -> {
|
||||
be.setInstruction(instruction.selectedMinion(), instruction.selectedInstruction());
|
||||
player.playSoundToPlayer(SoundEvents.BLOCK_NOTE_BLOCK_CHIME.value(), SoundCategory.BLOCKS, 1, 1);
|
||||
stack.decrement(1);
|
||||
});
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
return super.onUseWithItem(stack, state, world, pos, player, hand, hit);
|
||||
}
|
||||
|
||||
@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;
|
||||
world.getBlockEntity(pos, MinionBlocks.MINION_TRIGGER_BE_TYPE).ifPresent(be -> {
|
||||
String name = MinionPersistentState.INSTANCE.getMinionData(be.getMinionUuid()).name();
|
||||
player.sendMessage(Text.translatable("minions.reference.instruction.tooltip", name, be.getInstructionName()), true);
|
||||
});
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void neighborUpdate(BlockState state, World world, BlockPos pos, Block sourceBlock, @Nullable WireOrientation wireOrientation, boolean notify) {
|
||||
if(!canPlaceAt(state, world, pos)) {
|
||||
dropStacks(state, world, pos);
|
||||
world.removeBlock(pos, false);
|
||||
}
|
||||
|
||||
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);
|
||||
world.getBlockEntity(pos, MinionBlocks.MINION_TRIGGER_BE_TYPE).ifPresent(MinionTriggerBlockEntity::updatePower);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +124,7 @@ public class MinionTriggerBlock extends BlockWithEntity implements PolymerBlock
|
||||
|
||||
@Override
|
||||
protected int getComparatorOutput(BlockState state, World world, BlockPos pos) {
|
||||
return world.getBlockEntity(pos, MinionRegistration.MINION_TRIGGER_BE_TYPE).map(MinionTriggerBlockEntity::getComparatorOutput).orElse(0);
|
||||
return world.getBlockEntity(pos, MinionBlocks.MINION_TRIGGER_BE_TYPE).map(MinionTriggerBlockEntity::getComparatorOutput).orElse(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,15 +139,34 @@ public class MinionTriggerBlock extends BlockWithEntity implements PolymerBlock
|
||||
|
||||
@Override
|
||||
public BlockState getPolymerBlockState(BlockState state, PacketContext context) {
|
||||
return state.get(POWERED) ? Blocks.REDSTONE_BLOCK.getDefaultState() : Blocks.GOLD_BLOCK.getDefaultState();
|
||||
return PolymerUtil.isOnClient(context) ? state : Blocks.COMPARATOR.getDefaultState().with(AbstractRedstoneGateBlock.POWERED, state.get(POWERED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
|
||||
if(type == MinionRegistration.MINION_TRIGGER_BE_TYPE) {
|
||||
if(type == MinionBlocks.MINION_TRIGGER_BE_TYPE) {
|
||||
return MinionTriggerBlockEntity::tick;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ElementHolder createElementHolder(ServerWorld world, BlockPos pos, BlockState initialBlockState) {
|
||||
ElementHolder holder = new ElementHolder() {
|
||||
@Override
|
||||
public boolean startWatching(ServerPlayNetworkHandler player) {
|
||||
if(PolymerResourcePackUtils.hasMainPack(player)) {
|
||||
return super.startWatching(player);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
ItemStack stack = new ItemStack(Items.BARRIER);
|
||||
stack.set(DataComponentTypes.ITEM_MODEL, Identifier.of(Minions.MOD_ID, "minion_trigger_no_plate_" + (initialBlockState.get(MinionTriggerBlock.POWERED) ? "active" : "inactive")));
|
||||
|
||||
holder.addElement(new ItemDisplayElement(stack));
|
||||
return holder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.github.skippyall.minions.block;
|
||||
|
||||
import io.github.skippyall.minions.MinionRegistration;
|
||||
import io.github.skippyall.minions.MinionBlocks;
|
||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
||||
import io.github.skippyall.minions.program.instruction.ConfiguredInstruction;
|
||||
@@ -23,7 +23,7 @@ public class MinionTriggerBlockEntity extends BlockEntity {
|
||||
private boolean runningCache = false;
|
||||
|
||||
public MinionTriggerBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(MinionRegistration.MINION_TRIGGER_BE_TYPE, pos, state);
|
||||
super(MinionBlocks.MINION_TRIGGER_BE_TYPE, pos, state);
|
||||
}
|
||||
|
||||
public void setInstruction(UUID minionUuid, String instructionName) {
|
||||
@@ -38,12 +38,12 @@ public class MinionTriggerBlockEntity extends BlockEntity {
|
||||
}
|
||||
if(triggerBlockEntity.first) {
|
||||
triggerBlockEntity.first = false;
|
||||
world.updateComparators(pos, MinionRegistration.MINION_TRIGGER_BLOCK);
|
||||
world.updateComparators(pos, MinionBlocks.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);
|
||||
world.updateComparators(pos, MinionBlocks.MINION_TRIGGER_BLOCK);
|
||||
triggerBlockEntity.runningCache = isRunning;
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,14 @@ public class MinionTriggerBlockEntity extends BlockEntity {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public UUID getMinionUuid() {
|
||||
return minionUuid;
|
||||
}
|
||||
|
||||
public String getInstructionName() {
|
||||
return instructionName;
|
||||
}
|
||||
|
||||
public Optional<ConfiguredInstruction<MinionRuntime>> getInstruction(MinionFakePlayer minion) {
|
||||
return Optional.ofNullable(minion.getInstructionManager().getInstruction(instructionName));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package io.github.skippyall.minions.block;
|
||||
|
||||
import eu.pb4.polymer.core.api.item.PolymerBlockItem;
|
||||
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import xyz.nucleoid.packettweaker.PacketContext;
|
||||
|
||||
public class MinionTriggerBlockItem extends PolymerBlockItem {
|
||||
public MinionTriggerBlockItem(Block block, Settings settings, Item polymerItem) {
|
||||
super(block, settings, polymerItem, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Identifier getPolymerItemModel(ItemStack stack, PacketContext context) {
|
||||
if(PolymerResourcePackUtils.hasMainPack(context)) {
|
||||
return super.getPolymerItemModel(stack, context);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.github.skippyall.minions.docs;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TextCodecs;
|
||||
|
||||
public record ReferenceEntry(Text shortDescription, Text longDescription) {
|
||||
public static final Codec<ReferenceEntry> CODEC = RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
TextCodecs.CODEC.fieldOf("shortDescription").forGetter(ReferenceEntry::shortDescription),
|
||||
TextCodecs.CODEC.fieldOf("longDescription").forGetter(ReferenceEntry::longDescription)
|
||||
).apply(instance, ReferenceEntry::new));
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package io.github.skippyall.minions.gui;
|
||||
|
||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
|
||||
import io.github.skippyall.minions.gui.input.ChoiceInput;
|
||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
||||
import io.github.skippyall.minions.program.instruction.ConfiguredInstruction;
|
||||
import io.github.skippyall.minions.program.supplier.Parameter;
|
||||
import io.github.skippyall.minions.reference.ReferenceItem;
|
||||
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;
|
||||
|
||||
public class ConfigureInstructionGui extends InstructionBoundSimpleGui {
|
||||
private String name;
|
||||
|
||||
private ConfigureInstructionGui(ScreenHandlerType<?> type, ServerPlayerEntity player, MinionFakePlayer minion, ConfiguredInstruction<MinionRuntime> configuredInstruction, String name) {
|
||||
super(type, player, minion, configuredInstruction);
|
||||
this.name = name;
|
||||
init();
|
||||
}
|
||||
|
||||
public static void configureInstructionMenu(String name, ConfiguredInstruction<MinionRuntime> instruction, MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||
if(!InstructionGui.checkInstructionExists(name, instruction, minion, player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigureInstructionGui gui = new ConfigureInstructionGui(ScreenHandlerType.GENERIC_9X3, player, minion, instruction, name);
|
||||
|
||||
gui.open();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setTitle(Text.literal(name));
|
||||
|
||||
setSlot(7, new GuiElementBuilder(Items.ANVIL)
|
||||
.setName(Text.translatable("minions.gui.instruction.configure.rename"))
|
||||
.setCallback(() -> InstructionGui.inputInstructionName(minion, player, name).thenAccept(newName -> {
|
||||
minion.getInstructionManager().setInstructionName(name, newName);
|
||||
configureInstructionMenu(newName, instruction, minion, player);
|
||||
}))
|
||||
);
|
||||
|
||||
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);
|
||||
InstructionGui.instructionList(minion, player);
|
||||
}))
|
||||
);
|
||||
|
||||
updateSuppliers();
|
||||
|
||||
setSlot(13, InstructionGui.createInstructionElement(instruction.getInstruction(), player.getRegistryManager()));
|
||||
|
||||
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.getInventory().offer(ReferenceItem.createInstructionReference(minion, name), true);
|
||||
player.playSoundToPlayer(SoundEvents.BLOCK_NOTE_BLOCK_CHIME.value(), SoundCategory.BLOCKS, 1, 1);
|
||||
})
|
||||
);
|
||||
|
||||
updateRunSlot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInstructionRename(MinionFakePlayer minion, ConfiguredInstruction<?> instruction, String newName) {
|
||||
this.setTitle(Text.literal(newName));
|
||||
name = newName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun(ConfiguredInstruction<?> instruction) {
|
||||
updateRunSlot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop(ConfiguredInstruction<?> instruction) {
|
||||
updateRunSlot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSupplierChange(ConfiguredInstruction<?> instruction, Parameter<?> parameter) {
|
||||
updateSuppliers();
|
||||
}
|
||||
|
||||
private void updateRunSlot() {
|
||||
if(!instruction.isRunning()) {
|
||||
setSlot(26, new GuiElementBuilder(Items.ARROW)
|
||||
.setName(Text.translatable("minions.gui.instruction.run"))
|
||||
.setCallback(() -> instruction.run(minion.getInstructionManager()))
|
||||
);
|
||||
} else {
|
||||
setSlot(26, new GuiElementBuilder(Items.BARRIER)
|
||||
.setName(Text.translatable("minions.gui.instruction.stop"))
|
||||
.setCallback(() -> instruction.stop(minion.getInstructionManager()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSuppliers() {
|
||||
int slot = 11;
|
||||
for(Parameter<?> parameter : instruction.getInstruction().getParameters().reversed()) {
|
||||
setSlot(slot, InstructionGui.createParameterElement(parameter, player.getRegistryManager())
|
||||
.setCallback(() -> InstructionGui.configureArgumentMenu(name, instruction, parameter, minion, player))
|
||||
);
|
||||
slot--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,59 +1,151 @@
|
||||
package io.github.skippyall.minions.gui;
|
||||
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
|
||||
import io.github.skippyall.minions.util.ModelIdUtil;
|
||||
import com.mojang.serialization.Codec;
|
||||
import io.github.skippyall.minions.MinionRegistries;
|
||||
import io.github.skippyall.minions.Minions;
|
||||
import io.github.skippyall.minions.util.TranslationUtil;
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceSortedSets;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.component.type.LoreComponent;
|
||||
import net.minecraft.component.type.ProfileComponent;
|
||||
import net.minecraft.component.type.TooltipDisplayComponent;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.registry.DynamicRegistryManager;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Rarity;
|
||||
import net.minecraft.util.Uuids;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface GuiDisplay {
|
||||
default GuiElementBuilder createElement() {
|
||||
return new GuiElementBuilder(createItemStack());
|
||||
Codec<GuiDisplay> CODEC = MinionRegistries.GUI_DISPLAY_TYPE.getCodec().dispatch(GuiDisplay::getCodec, codec -> codec.fieldOf("data"));
|
||||
GuiDisplay DEFAULT_DISPLAY = new ItemBased(Items.BARRIER);
|
||||
|
||||
static GuiDisplay getGuiDisplay(Identifier id, DynamicRegistryManager manager) {
|
||||
return manager.getOptional(MinionRegistries.GUI_DISPLAY).map(registry -> registry.get(id)).orElse(DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
static <T> GuiDisplay getGuiDisplayFor(Registry<T> registry, T element, DynamicRegistryManager manager) {
|
||||
Identifier elementId = registry.getId(element);
|
||||
if(elementId == null) {
|
||||
return DEFAULT_DISPLAY;
|
||||
}
|
||||
Identifier displayId = elementId.withPrefixedPath(registry.getKey().getValue().getPath() + "/");
|
||||
|
||||
return getGuiDisplay(displayId, manager);
|
||||
}
|
||||
|
||||
static <T> ItemStack getDisplayStack(Registry<T> registry, T element, DynamicRegistryManager manager) {
|
||||
return getGuiDisplayFor(registry, element, manager).createItemStack();
|
||||
}
|
||||
|
||||
static <T> ItemStack getDisplayStackWithName(Registry<T> registry, T element, DynamicRegistryManager manager) {
|
||||
ItemStack stack = getDisplayStack(registry, element, manager);
|
||||
stack.set(DataComponentTypes.ITEM_NAME, Text.translatable(TranslationUtil.getTranslationKey(element, registry)));
|
||||
return stack;
|
||||
}
|
||||
|
||||
ItemStack createItemStack();
|
||||
|
||||
record ModelBased(Identifier model, String translationKeyBase, boolean withLore) implements GuiDisplay {
|
||||
public ModelBased(Item model, String translationKeyBase, boolean withLore) {
|
||||
this(ModelIdUtil.getItemModelId(model), translationKeyBase, withLore);
|
||||
}
|
||||
Codec<? extends GuiDisplay> getCodec();
|
||||
|
||||
public ModelBased(Item model, String translationKeyBase) {
|
||||
this(ModelIdUtil.getItemModelId(model), translationKeyBase, false);
|
||||
class ModelBased implements GuiDisplay {
|
||||
public static final Codec<ModelBased> CODEC = Identifier.CODEC.xmap(ModelBased::new, display -> display.model);
|
||||
|
||||
private final Identifier model;
|
||||
|
||||
public ModelBased(Identifier model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack createItemStack() {
|
||||
ItemStack stack = new ItemStack(Items.BARRIER);
|
||||
stack.set(DataComponentTypes.ITEM_MODEL, model);
|
||||
stack.set(DataComponentTypes.ITEM_NAME, Text.translatable(translationKeyBase + ".name"));
|
||||
if(withLore) {
|
||||
stack.set(DataComponentTypes.LORE, LoreComponent.DEFAULT.with(Text.translatable(translationKeyBase + ".description")));
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec<? extends GuiDisplay> getCodec() {
|
||||
return CODEC;
|
||||
}
|
||||
}
|
||||
|
||||
record HeadBased(UUID uuid, String translationKeyBase, boolean withLore) implements GuiDisplay {
|
||||
class ItemBased implements GuiDisplay {
|
||||
public static final Codec<ItemBased> CODEC = Registries.ITEM.getCodec().xmap(ItemBased::new, display -> display.item);
|
||||
|
||||
private final Item item;
|
||||
|
||||
public ItemBased(Item item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack createItemStack() {
|
||||
ItemStack stack = new ItemStack(item);
|
||||
stack.set(DataComponentTypes.TOOLTIP_DISPLAY, new TooltipDisplayComponent(true, ReferenceSortedSets.emptySet()));
|
||||
stack.set(DataComponentTypes.RARITY, Rarity.COMMON);
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec<? extends GuiDisplay> getCodec() {
|
||||
return CODEC;
|
||||
}
|
||||
}
|
||||
|
||||
class HeadBased implements GuiDisplay {
|
||||
public static final Codec<HeadBased> CODEC = Uuids.CODEC.xmap(HeadBased::new, display -> display.uuid);
|
||||
|
||||
private final UUID uuid;
|
||||
|
||||
public HeadBased(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack createItemStack() {
|
||||
ItemStack stack = new ItemStack(Items.PLAYER_HEAD);
|
||||
stack.set(DataComponentTypes.PROFILE, new ProfileComponent(Optional.empty(), Optional.of(uuid), new PropertyMap()));
|
||||
stack.set(DataComponentTypes.ITEM_NAME, Text.translatable(translationKeyBase + ".name"));
|
||||
if(withLore) {
|
||||
stack.set(DataComponentTypes.LORE, LoreComponent.DEFAULT.with(Text.translatable(translationKeyBase + ".description")));
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec<? extends GuiDisplay> getCodec() {
|
||||
return CODEC;
|
||||
}
|
||||
}
|
||||
|
||||
class StackBased implements GuiDisplay {
|
||||
public static final Codec<StackBased> CODEC = ItemStack.CODEC.xmap(StackBased::new, StackBased::createItemStack);
|
||||
|
||||
private final ItemStack stack;
|
||||
|
||||
public StackBased(ItemStack stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack createItemStack() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec<? extends GuiDisplay> getCodec() {
|
||||
return CODEC;
|
||||
}
|
||||
}
|
||||
|
||||
static void register() {
|
||||
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, Identifier.of(Minions.MOD_ID, "item"), ItemBased.CODEC);
|
||||
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, Identifier.of(Minions.MOD_ID, "model"), ModelBased.CODEC);
|
||||
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, Identifier.of(Minions.MOD_ID, "head"), HeadBased.CODEC);
|
||||
Registry.register(MinionRegistries.GUI_DISPLAY_TYPE, Identifier.of(Minions.MOD_ID, "stack"), StackBased.CODEC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.github.skippyall.minions.gui;
|
||||
|
||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
||||
import io.github.skippyall.minions.program.instruction.ConfiguredInstruction;
|
||||
import io.github.skippyall.minions.program.instruction.ConfiguredInstructionListener;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
public class InstructionBoundSimpleGui extends MinionBoundSimpleGui implements ConfiguredInstructionListener {
|
||||
protected final ConfiguredInstruction<MinionRuntime> instruction;
|
||||
|
||||
public InstructionBoundSimpleGui(ScreenHandlerType<?> type, ServerPlayerEntity player, MinionFakePlayer minion, ConfiguredInstruction<MinionRuntime> instruction) {
|
||||
super(type, player, minion);
|
||||
this.instruction = instruction;
|
||||
instruction.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInstructionRemove(ConfiguredInstruction<?> instruction) {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
super.onClose();
|
||||
instruction.removeListener(this);
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,6 @@ 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.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;
|
||||
@@ -18,20 +16,20 @@ 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;
|
||||
import net.minecraft.registry.DynamicRegistryManager;
|
||||
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;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class InstructionGui {
|
||||
public static void openInstructionMainMenu(MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_3X3, player, false);
|
||||
SimpleGui gui = new MinionBoundSimpleGui(ScreenHandlerType.GENERIC_3X3, player, minion);
|
||||
gui.setTitle(Text.translatable("minions.gui.instruction.title"));
|
||||
|
||||
gui.setSlot(3, new GuiElementBuilder()
|
||||
.setItem(Items.BOOK)
|
||||
.setName(Text.translatable("minions.gui.instruction.list"))
|
||||
@@ -47,30 +45,44 @@ 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<MinionRuntime> instruction = minion.getInstructionManager().getInstruction(instructionName);
|
||||
gui.addSlot(instruction.getInstruction().getDisplay().createElement()
|
||||
.setName(Text.literal(instructionName))
|
||||
.setLore(List.of())
|
||||
.setCallback(() -> configureInstructionMenu(instructionName, instruction, minion, player))
|
||||
);
|
||||
}
|
||||
SimpleGui gui = new MinionBoundSimpleGui(ScreenHandlerType.GENERIC_9X3, player, minion) {
|
||||
@Override
|
||||
public void onInstructionsUpdate(MinionFakePlayer minion) {
|
||||
resetInstructionList(this, minion, player);
|
||||
}
|
||||
};
|
||||
gui.setTitle(Text.translatable("minions.gui.instruction.title"));
|
||||
resetInstructionList(gui, minion, player);
|
||||
|
||||
gui.open();
|
||||
}
|
||||
|
||||
private static void resetInstructionList(SimpleGui gui, MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||
int i = 0;
|
||||
for (String instructionName : minion.getInstructionManager().getInstructionNames()) {
|
||||
ConfiguredInstruction<MinionRuntime> instruction = minion.getInstructionManager().getInstruction(instructionName);
|
||||
gui.setSlot(i, new GuiElementBuilder(GuiDisplay.getGuiDisplayFor(MinionRegistries.INSTRUCTION_TYPES, instruction.getInstruction(), player.getRegistryManager()).createItemStack())
|
||||
.setName(Text.literal(instructionName))
|
||||
.setCallback(() -> ConfigureInstructionGui.configureInstructionMenu(instructionName, instruction, minion, player))
|
||||
);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void createNewInstruction(MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||
selectInstructionModuleMenu(minion, player).thenAccept(instructionType ->
|
||||
inputInstructionName(minion, player, "Instruction").thenAccept(name -> {
|
||||
ConfiguredInstruction<MinionRuntime> configuredInstruction = minion.getInstructionManager().createInstruction(name, instructionType);
|
||||
configureInstructionMenu(name, configuredInstruction, minion, player);
|
||||
if (!minion.isRemoved() && !minion.isDisconnected()) {
|
||||
ConfiguredInstruction<MinionRuntime> configuredInstruction = minion.getInstructionManager().createInstruction(name, instructionType);
|
||||
ConfigureInstructionGui.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)) {
|
||||
if (minion.getInstructionManager().hasInstruction(name)) {
|
||||
return new Result.Error<>(Text.translatable("minions.gui.instruction.name_already_used"));
|
||||
}
|
||||
return new Result.Success<>(name);
|
||||
@@ -78,120 +90,49 @@ public class InstructionGui {
|
||||
}
|
||||
|
||||
public static boolean checkInstructionExists(String name, ConfiguredInstruction<?> instruction, MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||
boolean stillExists = minion.getInstructionManager().getInstruction(name) == instruction;
|
||||
if(!stillExists) {
|
||||
boolean stillExists = !minion.isRemoved() && !minion.isDisconnected() && minion.getInstructionManager().getInstruction(name) == instruction;
|
||||
if (!stillExists) {
|
||||
player.closeHandledScreen();
|
||||
player.sendMessage(Text.translatable("minions.gui.instruction.removed"));
|
||||
}
|
||||
return stillExists;
|
||||
}
|
||||
|
||||
public static void configureInstructionMenu(String name, ConfiguredInstruction<MinionRuntime> instruction, MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||
if(!checkInstructionExists(name, instruction, minion, player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
|
||||
gui.setTitle(Text.literal(name));
|
||||
|
||||
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);
|
||||
}))
|
||||
);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
private static void updateRunSlot(ConfiguredInstruction<MinionRuntime> instruction, MinionFakePlayer minion, SimpleGui gui) {
|
||||
if(!instruction.isRunning()) {
|
||||
gui.setSlot(26, new GuiElementBuilder(Items.ARROW)
|
||||
.setName(Text.translatable("minions.gui.instruction.run"))
|
||||
.setCallback(() -> {
|
||||
instruction.run(minion.getInstructionManager());
|
||||
updateRunSlot(instruction, minion, gui);
|
||||
})
|
||||
);
|
||||
} else {
|
||||
gui.setSlot(26, new GuiElementBuilder(Items.BARRIER)
|
||||
.setName(Text.translatable("minions.gui.instruction.stop"))
|
||||
.setCallback(() -> {
|
||||
instruction.stop(minion.getInstructionManager());
|
||||
updateRunSlot(instruction, minion, gui);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T, A extends ValueSupplier<T, MinionRuntime>> void configureArgumentMenu(String name, ConfiguredInstruction<MinionRuntime> instruction, Parameter<T> parameter, MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||
if(!checkInstructionExists(name, instruction, minion, player)) {
|
||||
public static <T, A extends ValueSupplier<T, MinionRuntime>> void configureArgumentMenu(String instructionName, ConfiguredInstruction<MinionRuntime> instruction, Parameter<T> parameter, MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||
if (!checkInstructionExists(instructionName, instruction, minion, player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@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.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 -> {
|
||||
instruction.getArguments().setArgument(parameter, newArgument);
|
||||
configureArgumentMenu(name, instruction, parameter, minion, player);
|
||||
})
|
||||
)
|
||||
if(argument == null) {
|
||||
configureTypeAndValue(instructionName, instruction, parameter, minion, player);
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleGui gui = new InstructionBoundSimpleGui(ScreenHandlerType.GENERIC_3X3, player, minion, instruction);
|
||||
|
||||
ItemStack displayStack = GuiDisplay.getDisplayStack(MinionRegistries.VALUE_SUPPLIER_TYPES, argument.getType(), player.getRegistryManager());
|
||||
|
||||
gui.setSlot(3, new GuiElementBuilder(displayStack)
|
||||
.setName(Text.translatable("minions.gui.instruction.argument.configure.type", Text.translatable(TranslationUtil.getTranslationKey(argument.getType(), MinionRegistries.VALUE_SUPPLIER_TYPES, "minions.gui.instruction.argument.configure.type.unset"))))
|
||||
.setCallback(() -> configureTypeAndValue(instructionName, instruction, parameter, minion, player))
|
||||
);
|
||||
gui.setSlot(5, new GuiElementBuilder(Items.STRUCTURE_VOID)
|
||||
.setName(Text.literal("Configure"))
|
||||
.setCallback(() -> argument.getType().openConfiguration(player, argument.getValueType(), argument)
|
||||
.thenAccept(newArgument -> instruction.getArguments().setArgument(parameter, newArgument))
|
||||
)
|
||||
);
|
||||
|
||||
if(argument != null) {
|
||||
gui.setSlot(5, new GuiElementBuilder(Items.STRUCTURE_VOID)
|
||||
.setName(Text.literal("Configure"))
|
||||
.setCallback(() -> argument.getType().openConfiguration(player, argument.getValueType(), argument)
|
||||
.thenAccept(newArgument -> instruction.getArguments().setArgument(parameter, newArgument))
|
||||
)
|
||||
);
|
||||
}
|
||||
gui.open();
|
||||
}
|
||||
|
||||
public static CompletableFuture<ValueSupplierType<MinionRuntime>> selectArgumentType(ServerPlayerEntity player) {
|
||||
public static CompletableFuture<ValueSupplierType<MinionRuntime>> selectArgumentType(ServerPlayerEntity player, MinionFakePlayer minion, ConfiguredInstruction<MinionRuntime> instruction) {
|
||||
CompletableFuture<ValueSupplierType<MinionRuntime>> future = new CompletableFuture<>();
|
||||
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
|
||||
for(ValueSupplierType<MinionRuntime> type : MinionRegistries.ARGUMENT_TYPES) {
|
||||
gui.addSlot(new GuiElementBuilder()
|
||||
.setName(Text.translatable(TranslationUtil.getTranslationKey(type, MinionRegistries.ARGUMENT_TYPES)))
|
||||
SimpleGui gui = new InstructionBoundSimpleGui(ScreenHandlerType.GENERIC_9X3, player, minion, instruction);
|
||||
for (ValueSupplierType<MinionRuntime> type : MinionRegistries.VALUE_SUPPLIER_TYPES) {
|
||||
gui.addSlot(new GuiElementBuilder(GuiDisplay.getDisplayStackWithName(MinionRegistries.VALUE_SUPPLIER_TYPES, type, player.getRegistryManager()))
|
||||
.setCallback(() -> future.complete(type))
|
||||
);
|
||||
}
|
||||
@@ -199,28 +140,40 @@ public class InstructionGui {
|
||||
return future;
|
||||
}
|
||||
|
||||
public static <T> void configureTypeAndValue(String name, ConfiguredInstruction<MinionRuntime> instruction, Parameter<T> parameter, MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||
selectArgumentType(player, minion, instruction)
|
||||
.thenApply(type -> type.openConfiguration(player, parameter.type(), null)
|
||||
.thenAccept(newArgument -> {
|
||||
instruction.getArguments().setArgument(parameter, newArgument);
|
||||
configureArgumentMenu(name, instruction, parameter, minion, player);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public static CompletableFuture<InstructionType<MinionRuntime>> selectInstructionModuleMenu(MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||
if(minion.getModuleInventory().getModules().isEmpty()) {
|
||||
player.sendMessage(Text.literal("This minion has no modules"));
|
||||
if (minion.getModuleInventory().getModules().isEmpty()) {
|
||||
player.sendMessage(Text.translatable("minions.gui.instruction.no_modules"));
|
||||
return CompletableFuture.failedFuture(new NoSuchElementException("No modules"));
|
||||
}
|
||||
|
||||
CompletableFuture<InstructionType<MinionRuntime>> future = new CompletableFuture<>();
|
||||
|
||||
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false) {
|
||||
SimpleGui gui = new MinionBoundSimpleGui(ScreenHandlerType.GENERIC_9X3, player, minion) {
|
||||
@Override
|
||||
public void onClose() {
|
||||
if(!future.isDone()) {
|
||||
if (!future.isDone()) {
|
||||
future.cancel(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
gui.setTitle(Text.translatable("minions.gui.instruction.select_instruction"));
|
||||
|
||||
for(int i = 0; i < minion.getModuleInventory().size(); i++) {
|
||||
ItemStack module = minion.getModuleInventory().getStack(i);
|
||||
if(module.contains(MinionModule.COMPONENT_TYPE)) {
|
||||
gui.addSlot(new GuiElementBuilder(module)
|
||||
.setCallback(() -> selectInstructionMenu(module.get(MinionModule.COMPONENT_TYPE), minion, player)
|
||||
for (int i = 0; i < minion.getModuleInventory().size(); i++) {
|
||||
ItemStack moduleItem = minion.getModuleInventory().getStack(i);
|
||||
MinionModule module = moduleItem.get(MinionModule.COMPONENT_TYPE);
|
||||
if (module != null && !module.instructions().isEmpty()) {
|
||||
gui.addSlot(new GuiElementBuilder(moduleItem)
|
||||
.setCallback(() -> selectInstructionMenu(module, minion, player)
|
||||
.thenApply(future::complete)
|
||||
)
|
||||
);
|
||||
@@ -234,9 +187,18 @@ public class InstructionGui {
|
||||
public static CompletableFuture<InstructionType<MinionRuntime>> selectInstructionMenu(MinionModule module, MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||
CompletableFuture<InstructionType<MinionRuntime>> future = new CompletableFuture<>();
|
||||
|
||||
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
|
||||
for(InstructionType<MinionRuntime> instructionType : module.instructions()) {
|
||||
gui.addSlot(createInstructionElement(instructionType)
|
||||
SimpleGui gui = new MinionBoundSimpleGui(ScreenHandlerType.GENERIC_9X3, player, minion) {
|
||||
@Override
|
||||
public void onClose() {
|
||||
if (!future.isDone()) {
|
||||
future.cancel(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
gui.setTitle(Text.translatable("minions.gui.instruction.select_instruction"));
|
||||
|
||||
for (InstructionType<MinionRuntime> instructionType : module.instructions()) {
|
||||
gui.addSlot(createInstructionElement(instructionType, player.getRegistryManager())
|
||||
.setCallback(() -> future.complete(instructionType))
|
||||
);
|
||||
}
|
||||
@@ -245,10 +207,10 @@ public class InstructionGui {
|
||||
return future;
|
||||
}
|
||||
|
||||
public static GuiElementBuilder createInstructionElement(InstructionType<?> instructionType) {
|
||||
public static GuiElementBuilder createInstructionElement(InstructionType<MinionRuntime> instructionType, DynamicRegistryManager manager) {
|
||||
GuiElementBuilder instructionBuilder;
|
||||
if(instructionType != null) {
|
||||
instructionBuilder = instructionType.getDisplay().createElement();
|
||||
if (instructionType != null) {
|
||||
instructionBuilder = new GuiElementBuilder(GuiDisplay.getDisplayStackWithName(MinionRegistries.INSTRUCTION_TYPES, instructionType, manager));
|
||||
} else {
|
||||
instructionBuilder = new GuiElementBuilder(Items.RED_WOOL)
|
||||
.setName(Text.translatable("minions.gui.instruction.no_instruction_set"));
|
||||
@@ -256,14 +218,19 @@ public class InstructionGui {
|
||||
return instructionBuilder;
|
||||
}
|
||||
|
||||
public static GuiElementBuilder createArgumentElement(ValueSupplier<?,?> valueSupplier) {
|
||||
public static GuiElementBuilder createParameterElement(Parameter<?> parameter, DynamicRegistryManager manager) {
|
||||
return new GuiElementBuilder(GuiDisplay.getDisplayStack(MinionRegistries.VALUE_TYPES, parameter.type(), manager))
|
||||
.setName(Text.translatable("minions.gui.instruction.parameter", parameter.name(), Text.translatable(TranslationUtil.getTranslationKey(parameter.type(), MinionRegistries.VALUE_TYPES))));
|
||||
}
|
||||
|
||||
public static GuiElementBuilder createArgumentElement(ValueSupplier<?, MinionRuntime> valueSupplier, DynamicRegistryManager manager) {
|
||||
GuiElementBuilder argumentBuilder;
|
||||
if(valueSupplier != null) {
|
||||
argumentBuilder = valueSupplier.getDisplay().createElement();
|
||||
if (valueSupplier != null) {
|
||||
argumentBuilder = new GuiElementBuilder(GuiDisplay.getDisplayStack(MinionRegistries.VALUE_SUPPLIER_TYPES, valueSupplier.getType(), manager));
|
||||
} else {
|
||||
argumentBuilder = new GuiElementBuilder(Items.RED_WOOL)
|
||||
.setName(Text.translatable("minions.gui.instruction.no_argument_set"));
|
||||
}
|
||||
return argumentBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package io.github.skippyall.minions.gui;
|
||||
|
||||
import eu.pb4.sgui.api.gui.SimpleGui;
|
||||
import io.github.skippyall.minions.minion.MinionListener;
|
||||
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
public class MinionBoundSimpleGui extends SimpleGui implements MinionListener {
|
||||
protected final MinionFakePlayer minion;
|
||||
|
||||
public MinionBoundSimpleGui(ScreenHandlerType<?> type, ServerPlayerEntity player, MinionFakePlayer minion) {
|
||||
super(type, player, false);
|
||||
this.minion = minion;
|
||||
minion.addMinionListener(this);
|
||||
}
|
||||
|
||||
public MinionFakePlayer getMinion() {
|
||||
return minion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMinionRemove(MinionFakePlayer minion) {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
minion.removeMinionListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof MinionBoundSimpleGui that)) return false;
|
||||
return minion == that.minion && player == that.player;
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,12 @@ import eu.pb4.sgui.api.elements.GuiElementBuilder;
|
||||
import eu.pb4.sgui.api.gui.SimpleGui;
|
||||
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
||||
import io.github.skippyall.minions.module.ModuleInventory;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.screen.slot.ArmorSlot;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
@@ -51,10 +55,31 @@ public class MinionGui {
|
||||
}
|
||||
|
||||
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()));
|
||||
for (int i = 0; i < minion.getInventory().size(); i++) {
|
||||
gui.setSlotRedirect(i, new Slot(minion.getInventory(), i, 0, 0));
|
||||
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X6, player, false);
|
||||
gui.setTitle(Text.translatable("minions.gui.inventory.title"));
|
||||
|
||||
for(int i = 0; i < 18; i++) {
|
||||
gui.setSlot(i, new ItemStack(Items.BARRIER));
|
||||
}
|
||||
|
||||
gui.setSlot(2, new ItemStack(Items.LEATHER_HELMET));
|
||||
gui.setSlot(3, new ItemStack(Items.LEATHER_CHESTPLATE));
|
||||
gui.setSlot(4, new ItemStack(Items.LEATHER_LEGGINGS));
|
||||
gui.setSlot(5, new ItemStack(Items.LEATHER_BOOTS));
|
||||
gui.setSlot(6, new ItemStack(Items.SHIELD));
|
||||
|
||||
gui.setSlotRedirect(2 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.HEAD, EquipmentSlot.HEAD.getOffsetEntitySlotId(PlayerInventory.MAIN_SIZE), 0, 0, null));
|
||||
gui.setSlotRedirect(3 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.CHEST, EquipmentSlot.CHEST.getOffsetEntitySlotId(PlayerInventory.MAIN_SIZE), 0, 0, null));
|
||||
gui.setSlotRedirect(4 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.LEGS, EquipmentSlot.LEGS.getOffsetEntitySlotId(PlayerInventory.MAIN_SIZE), 0, 0, null));
|
||||
gui.setSlotRedirect(5 + 9, new ArmorSlot(minion.getInventory(), minion, EquipmentSlot.FEET, EquipmentSlot.FEET.getOffsetEntitySlotId(PlayerInventory.MAIN_SIZE), 0, 0, null));
|
||||
gui.setSlotRedirect(6 + 9, new Slot(minion.getInventory(), PlayerInventory.OFF_HAND_SLOT, 0, 0));
|
||||
|
||||
for (int i = PlayerInventory.HOTBAR_SIZE; i < PlayerInventory.MAIN_SIZE; i++) {
|
||||
gui.setSlotRedirect(i + 9, new Slot(minion.getInventory(), i, 0, 0));
|
||||
}
|
||||
|
||||
for (int i = 0; i < PlayerInventory.HOTBAR_SIZE; i++) {
|
||||
gui.setSlotRedirect(i + 45, new Slot(minion.getInventory(), i, 0, 0));
|
||||
}
|
||||
gui.open();
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class ChoiceInput {
|
||||
gui.setTitle(title);
|
||||
|
||||
for(T value : values) {
|
||||
gui.addSlot(displayFunction.apply(value).createElement()
|
||||
gui.addSlot(new GuiElementBuilder(displayFunction.apply(value).createItemStack())
|
||||
.setCallback(() -> future.complete(value))
|
||||
);
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public class ChoiceInput {
|
||||
}
|
||||
|
||||
public static <T extends Displayable> BiFunction<ServerPlayerEntity, T, CompletableFuture<T>> createDialogOpener(T[] values) {
|
||||
return createDialogOpener(ScreenHandlerType.GENERIC_9X3, Text.empty(), Displayable::getDisplay, values, null);
|
||||
return createDialogOpener(ScreenHandlerType.GENERIC_9X3, Text.empty(), t -> t != null ? t.getDisplay() : null, values, null);
|
||||
}
|
||||
|
||||
public static CompletableFuture<Void> confirm(ServerPlayerEntity player, Text title) {
|
||||
|
||||
@@ -47,12 +47,12 @@ public class TextInput<T> extends AnvilInputGui {
|
||||
return inputSync(player, title, defaultValue, Result.Success::new);
|
||||
}
|
||||
|
||||
public static CompletableFuture<Integer> inputInt(ServerPlayerEntity player, Text title, String defaultValue) {
|
||||
return inputSync(player, title, defaultValue, string -> Result.wrapCustomError(() -> Integer.valueOf(string), Text.translatable("minions.command.input.int.fail")));
|
||||
public static CompletableFuture<Long> inputLong(ServerPlayerEntity player, Text title, String defaultValue) {
|
||||
return inputSync(player, title, defaultValue, string -> Result.wrapCustomError(() -> Long.valueOf(string), Text.translatable("minions.command.input.int.fail")));
|
||||
}
|
||||
|
||||
public static CompletableFuture<Float> inputFloat(ServerPlayerEntity player, Text title, String defaultValue) {
|
||||
return inputSync(player, title, defaultValue, string -> Result.wrapCustomError(() -> Float.valueOf(string), Text.translatable("minions.command.input.float.fail")));
|
||||
public static CompletableFuture<Double> inputDouble(ServerPlayerEntity player, Text title, String defaultValue) {
|
||||
return inputSync(player, title, defaultValue, string -> Result.wrapCustomError(() -> Double.valueOf(string), Text.translatable("minions.command.input.float.fail")));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.github.skippyall.minions.minion;
|
||||
|
||||
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
||||
import io.github.skippyall.minions.program.instruction.ConfiguredInstruction;
|
||||
import io.github.skippyall.minions.util.SerializableListenerManager;
|
||||
|
||||
public interface MinionListener extends SerializableListenerManager.SerializableListener {
|
||||
default void onMinionSpawn(MinionFakePlayer minion) {}
|
||||
|
||||
default void onMinionRemove(MinionFakePlayer minion) {}
|
||||
|
||||
default void onInstructionsUpdate(MinionFakePlayer minion) {}
|
||||
|
||||
default void onInstructionRename(MinionFakePlayer minion, ConfiguredInstruction<?> instruction, String newName) {}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
|
||||
|
||||
ConfiguredInstruction<MinionRuntime> instruction = new ConfiguredInstruction<>(instructionType);
|
||||
configuredInstructions.put(name, instruction);
|
||||
minion.forEachMinionListener(listener -> listener.onInstructionsUpdate(minion));
|
||||
return instruction;
|
||||
}
|
||||
|
||||
@@ -53,6 +54,9 @@ public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
|
||||
ConfiguredInstruction<MinionRuntime> instruction = getInstruction(name);
|
||||
instruction.stop(this);
|
||||
configuredInstructions.remove(name);
|
||||
|
||||
instruction.onInstructionRemove();
|
||||
minion.forEachMinionListener(listener -> listener.onInstructionsUpdate(minion));
|
||||
}
|
||||
|
||||
public ConfiguredInstruction<MinionRuntime> getInstruction(String name) {
|
||||
@@ -64,8 +68,16 @@ public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
|
||||
}
|
||||
|
||||
public void setInstructionName(String oldName, String newName) {
|
||||
if(!configuredInstructions.containsKey(newName)) {
|
||||
configuredInstructions.put(newName, configuredInstructions.remove(oldName));
|
||||
if(!configuredInstructions.containsKey(newName) && configuredInstructions.containsKey(oldName)) {
|
||||
ConfiguredInstruction<MinionRuntime> instruction = configuredInstructions.get(oldName);
|
||||
configuredInstructions.remove(oldName);
|
||||
configuredInstructions.put(newName, instruction);
|
||||
|
||||
|
||||
minion.forEachMinionListener(minionListener -> {
|
||||
minionListener.onInstructionRename(minion , instruction, newName);
|
||||
minionListener.onInstructionsUpdate(minion);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +110,7 @@ public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
|
||||
|
||||
@Override
|
||||
public Registry<ValueSupplierType<MinionRuntime>> getArgumentTypeRegistry() {
|
||||
return MinionRegistries.ARGUMENT_TYPES;
|
||||
return MinionRegistries.VALUE_SUPPLIER_TYPES;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+27
-11
@@ -7,7 +7,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import io.github.skippyall.minions.mixins.EntityAccessor;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.command.argument.EntityAnchorArgumentType;
|
||||
@@ -18,7 +17,6 @@ import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.entity.vehicle.BoatEntity;
|
||||
import net.minecraft.entity.vehicle.MinecartEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
|
||||
import net.minecraft.network.packet.s2c.play.UpdateSelectedSlotS2CPacket;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
@@ -41,7 +39,7 @@ public class EntityPlayerActionPack
|
||||
private final Map<ActionType, Action> actions = new EnumMap<>(ActionType.class);
|
||||
|
||||
private BlockPos currentBlock;
|
||||
private int blockHitDelay;
|
||||
public int blockHitDelay;
|
||||
private boolean isHittingBlock;
|
||||
private float curBlockDamageMP;
|
||||
|
||||
@@ -73,6 +71,14 @@ public class EntityPlayerActionPack
|
||||
itemUseCooldown = other.itemUseCooldown;
|
||||
}
|
||||
|
||||
public Action getAction(ActionType type) {
|
||||
return actions.get(type);
|
||||
}
|
||||
|
||||
public boolean hasAction(ActionType type) {
|
||||
return actions.containsKey(type);
|
||||
}
|
||||
|
||||
public EntityPlayerActionPack start(ActionType type, Action action)
|
||||
{
|
||||
Action previous = actions.remove(type);
|
||||
@@ -255,9 +261,13 @@ public class EntityPlayerActionPack
|
||||
if (strafing != 0.0F || player instanceof MinionFakePlayer) {
|
||||
player.sidewaysSpeed = strafing * vel;
|
||||
}
|
||||
|
||||
if(blockHitDelay > 0) {
|
||||
blockHitDelay--;
|
||||
}
|
||||
}
|
||||
|
||||
static HitResult getTarget(ServerPlayerEntity player)
|
||||
public static HitResult getTarget(ServerPlayerEntity player)
|
||||
{
|
||||
double reach = player.interactionManager.isCreative() ? 5 : 4.5f;
|
||||
return Tracer.rayTrace(player, 1, reach, false);
|
||||
@@ -382,7 +392,7 @@ public class EntityPlayerActionPack
|
||||
switch (hit.getType()) {
|
||||
case ENTITY: {
|
||||
EntityHitResult entityHit = (EntityHitResult) hit;
|
||||
if (!action.isContinuous)
|
||||
if (!action.isContinuous || action.first)
|
||||
{
|
||||
player.attack(entityHit.getEntity());
|
||||
player.swingHand(Hand.MAIN_HAND);
|
||||
@@ -395,7 +405,6 @@ public class EntityPlayerActionPack
|
||||
EntityPlayerActionPack ap = player.getMinionActionPack();
|
||||
if (ap.blockHitDelay > 0)
|
||||
{
|
||||
ap.blockHitDelay--;
|
||||
return false;
|
||||
}
|
||||
BlockHitResult blockHit = (BlockHitResult) hit;
|
||||
@@ -550,8 +559,9 @@ public class EntityPlayerActionPack
|
||||
private int count;
|
||||
private int next;
|
||||
private final boolean isContinuous;
|
||||
boolean first = true;
|
||||
|
||||
private Action(int limit, int interval, int offset, boolean continuous)
|
||||
private Action(int limit, int interval, int offset, boolean continuous, boolean first)
|
||||
{
|
||||
this.limit = limit;
|
||||
this.interval = interval;
|
||||
@@ -562,22 +572,27 @@ public class EntityPlayerActionPack
|
||||
|
||||
public static Action once()
|
||||
{
|
||||
return new Action(1, 1, 0, false);
|
||||
return new Action(1, 1, 0, false, false);
|
||||
}
|
||||
|
||||
public static Action startContinuous()
|
||||
{
|
||||
return new Action(-1, 1, 0, true, true);
|
||||
}
|
||||
|
||||
public static Action continuous()
|
||||
{
|
||||
return new Action(-1, 1, 0, true);
|
||||
return new Action(-1, 1, 0, true, false);
|
||||
}
|
||||
|
||||
public static Action interval(int interval)
|
||||
{
|
||||
return new Action(-1, interval, 0, false);
|
||||
return new Action(-1, interval, 0, false, false);
|
||||
}
|
||||
|
||||
public static Action interval(int interval, int offset)
|
||||
{
|
||||
return new Action(-1, interval, offset, false);
|
||||
return new Action(-1, interval, offset, false, false);
|
||||
}
|
||||
|
||||
Boolean tick(EntityPlayerActionPack actionPack, ActionType type)
|
||||
@@ -608,6 +623,7 @@ public class EntityPlayerActionPack
|
||||
return cancel;
|
||||
}
|
||||
next = interval;
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@ package io.github.skippyall.minions.minion.fakeplayer;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import io.github.skippyall.minions.MinionItems;
|
||||
import io.github.skippyall.minions.MinionRegistries;
|
||||
import io.github.skippyall.minions.minion.MinionListener;
|
||||
import io.github.skippyall.minions.minion.MinionData;
|
||||
import io.github.skippyall.minions.gui.MinionGui;
|
||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||
@@ -11,6 +13,7 @@ import io.github.skippyall.minions.minion.MinionItem;
|
||||
import io.github.skippyall.minions.minion.MinionPersistentState;
|
||||
import io.github.skippyall.minions.minion.MinionProfileUtils;
|
||||
import io.github.skippyall.minions.module.ModuleInventory;
|
||||
import io.github.skippyall.minions.util.SerializableListenerManager;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
@@ -45,12 +48,14 @@ import net.minecraft.world.TeleportTarget;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class MinionFakePlayer extends ServerPlayerEntity {
|
||||
public Runnable fixStartingPosition = () -> {};
|
||||
|
||||
private EntityPlayerActionPack actionPack;
|
||||
|
||||
private final SerializableListenerManager<MinionListener> minionListeners = new SerializableListenerManager<>(MinionRegistries.MINION_LISTENER_CODECS);
|
||||
private final ModuleInventory moduleInventory = new ModuleInventory();
|
||||
private final MinionRuntime instructionManager = new MinionRuntime(this);
|
||||
|
||||
@@ -90,9 +95,11 @@ public class MinionFakePlayer extends ServerPlayerEntity {
|
||||
instance.interactionManager.changeGameMode(GameMode.SURVIVAL);
|
||||
server.getPlayerManager().sendToDimension(new EntitySetHeadYawS2CPacket(instance, (byte) (instance.headYaw * 256 / 360)), level.getRegistryKey());//instance.dimension);
|
||||
server.getPlayerManager().sendToDimension(EntityPositionSyncS2CPacket.create(instance), level.getRegistryKey());//instance.dimension);
|
||||
//instance.world.getChunkManager(). updatePosition(instance);
|
||||
instance.getWorld().getChunkManager().updatePosition(instance);
|
||||
instance.dataTracker.set(PLAYER_MODEL_PARTS, (byte) 0x7f); // show all model layers (incl. capes)
|
||||
instance.getAbilities().flying = false;
|
||||
|
||||
instance.minionListeners.forEachListener(listener -> listener.onMinionSpawn(instance));
|
||||
}
|
||||
|
||||
public static MinionFakePlayer respawnFake(MinecraftServer server, ServerWorld level, GameProfile profile, SyncedClientOptions cli, MinionData data)
|
||||
@@ -123,6 +130,18 @@ public class MinionFakePlayer extends ServerPlayerEntity {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void addMinionListener(MinionListener listener) {
|
||||
minionListeners.addListener(listener);
|
||||
}
|
||||
|
||||
public void removeMinionListener(MinionListener listener) {
|
||||
minionListeners.removeListener(listener);
|
||||
}
|
||||
|
||||
public void forEachMinionListener(Consumer<MinionListener> listenerConsumer) {
|
||||
minionListeners.forEachListener(listenerConsumer);
|
||||
}
|
||||
|
||||
public boolean canSpawnMobs() {
|
||||
return moduleInventory.hasAbility("mobSpawning");
|
||||
}
|
||||
@@ -150,14 +169,10 @@ public class MinionFakePlayer extends ServerPlayerEntity {
|
||||
if (!isUsingItem()) super.onEquipStack(slot, previous, stack);
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public void kill()
|
||||
{
|
||||
kill(Text.literal("Killed"));
|
||||
}*/
|
||||
|
||||
public void kill(Text reason)
|
||||
{
|
||||
minionListeners.forEachListener(listener -> listener.onMinionRemove(this));
|
||||
|
||||
shakeOff();
|
||||
|
||||
if (reason.getContent() instanceof TranslatableTextContent text && text.getKey().equals("multiplayer.disconnect.duplicate_login")) {
|
||||
@@ -266,6 +281,7 @@ public class MinionFakePlayer extends ServerPlayerEntity {
|
||||
super.writeCustomData(view);
|
||||
moduleInventory.writeData(view.get("modules"));
|
||||
instructionManager.save(view.get("instructionManager"));
|
||||
minionListeners.save(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -273,5 +289,6 @@ public class MinionFakePlayer extends ServerPlayerEntity {
|
||||
super.readCustomData(view);
|
||||
moduleInventory.readData(view.getReadView("modules"));
|
||||
instructionManager.load(view.getReadView("instructionManager"));
|
||||
minionListeners.load(view);
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,26 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||
import net.minecraft.server.world.ChunkLevelManager;
|
||||
import net.minecraft.server.world.ChunkTicketManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@Mixin(value = ChunkLevelManager.class)
|
||||
public class ChunkTicketManagerFixMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private static Logger LOGGER;
|
||||
|
||||
@WrapOperation(method = "handleChunkLeave", at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/objects/ObjectSet;remove(Ljava/lang/Object;)Z", remap = false))
|
||||
public boolean filterIfNull(ObjectSet instance, Object o, Operation<Boolean> original) {
|
||||
if (instance != null) {
|
||||
return original.call(instance, o);
|
||||
}
|
||||
|
||||
LOGGER.error("Prevented NPE in handleChunkLeave");
|
||||
|
||||
return false;//Unused
|
||||
}
|
||||
|
||||
@@ -25,6 +33,8 @@ public class ChunkTicketManagerFixMixin {
|
||||
return original.call(instance);
|
||||
}
|
||||
|
||||
LOGGER.error("Prevented NPE in handleChunkLeave");
|
||||
|
||||
return true;//Unused
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import java.util.concurrent.Executor;
|
||||
|
||||
@Mixin(ChunkLevelManager.class)
|
||||
public class ChunkLevelManagerMixin implements ChunkLevelManagerAccessor {
|
||||
@Shadow @Final private Long2ObjectMap<ObjectSet<ServerPlayerEntity>> playersByChunkPos;
|
||||
@Shadow @Final Long2ObjectMap<ObjectSet<ServerPlayerEntity>> playersByChunkPos;
|
||||
@Shadow @Final private ChunkLevelManager.DistanceFromNearestPlayerTracker distanceFromNearestPlayerTracker;
|
||||
@Unique
|
||||
ChunkLevelManager.DistanceFromNearestPlayerTracker minionless;
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package io.github.skippyall.minions.mixins;
|
||||
package io.github.skippyall.minions.mixins.compat.universal_graves;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import eu.pb4.graves.grave.Grave;
|
||||
@@ -9,7 +9,7 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
|
||||
@Mixin(Grave.class)
|
||||
public class GraveCompatMixin {
|
||||
public class GraveMixin {
|
||||
@ModifyArg(method = "createBlock", at = @At(value = "INVOKE", target = "Leu/pb4/graves/grave/Grave;<init>(JLcom/mojang/authlib/GameProfile;BLnet/minecraft/util/Arm;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Identifier;Leu/pb4/graves/grave/GraveType;JJILnet/minecraft/text/Text;Ljava/util/Collection;Ljava/util/Collection;ZI)V"))
|
||||
private static boolean createGrave(boolean profile, @Local(argsOnly = true) ServerPlayerEntity player) {
|
||||
if(player instanceof MinionFakePlayer) {
|
||||
@@ -2,7 +2,6 @@ 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;
|
||||
@@ -16,8 +15,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
public interface ValueConsumer<T,R extends InstructionRuntime<R>> {
|
||||
void consume(T value, R runtime);
|
||||
|
||||
GuiDisplay getDisplay();
|
||||
|
||||
ValueType<T> getValueType();
|
||||
|
||||
ValueConsumerType<R> getType();
|
||||
|
||||
@@ -4,11 +4,15 @@ import com.mojang.serialization.Codec;
|
||||
import io.github.skippyall.minions.program.InstructionRuntime;
|
||||
import io.github.skippyall.minions.program.supplier.Parameter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ValueConsumerList<R extends InstructionRuntime<R>> {
|
||||
private final Map<String, ValueConsumer<?, R>> valueConsumers;
|
||||
private final List<Consumer<Parameter<?>>> changeListeners = new ArrayList<>();
|
||||
|
||||
public ValueConsumerList() {
|
||||
valueConsumers = new HashMap<>();
|
||||
@@ -25,15 +29,30 @@ public class ValueConsumerList<R extends InstructionRuntime<R>> {
|
||||
|
||||
public <T> void setValueConsumer(Parameter<T> parameter, ValueConsumer<?,R> consumer) {
|
||||
valueConsumers.put(parameter.name(), consumer);
|
||||
onChange(parameter);
|
||||
}
|
||||
|
||||
public <T> void setValue(Parameter<T> parameter, T value, R runtime) {
|
||||
public <T> void consumeValue(Parameter<T> parameter, T value, R runtime) {
|
||||
ValueConsumer<T,R> consumer = getValueConsumer(parameter).cast(parameter.type());
|
||||
if (consumer != null) {
|
||||
consumer.consume(value, runtime);
|
||||
}
|
||||
}
|
||||
|
||||
private void onChange(Parameter<?> parameter) {
|
||||
for (Consumer<Parameter<?>> listener : changeListeners) {
|
||||
listener.accept(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(Consumer<Parameter<?>> listener) {
|
||||
changeListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(Consumer<Parameter<?>> listener) {
|
||||
changeListeners.remove(listener);
|
||||
}
|
||||
|
||||
public static <R extends InstructionRuntime<R>> Codec<ValueConsumerList<R>> getCodec(Codec<ValueConsumer<?,R>> valueConsumerCodec) {
|
||||
return Codec.unboundedMap(Codec.STRING, valueConsumerCodec)
|
||||
.xmap(ValueConsumerList::new, list -> list.valueConsumers);
|
||||
|
||||
+46
-6
@@ -1,9 +1,12 @@
|
||||
package io.github.skippyall.minions.program.instruction;
|
||||
|
||||
import io.github.skippyall.minions.MinionRegistries;
|
||||
import io.github.skippyall.minions.Minions;
|
||||
import io.github.skippyall.minions.program.InstructionRuntime;
|
||||
import io.github.skippyall.minions.program.supplier.Parameter;
|
||||
import io.github.skippyall.minions.program.supplier.ValueSupplierList;
|
||||
import io.github.skippyall.minions.program.consumer.ValueConsumerList;
|
||||
import io.github.skippyall.minions.util.SerializableListenerManager;
|
||||
import net.minecraft.storage.ReadView;
|
||||
import net.minecraft.storage.WriteView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -14,11 +17,21 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
|
||||
private final ValueConsumerList<R> valueConsumers;
|
||||
private @Nullable InstructionExecution<R> execution;
|
||||
|
||||
private SerializableListenerManager<ConfiguredInstructionListener> listeners;
|
||||
|
||||
private ConfiguredInstruction(InstructionType<R> instruction, ValueSupplierList<R> arguments, ValueConsumerList<R> valueConsumers, @Nullable InstructionExecution<R> execution, SerializableListenerManager<ConfiguredInstructionListener> listeners) {
|
||||
this(instruction, arguments, valueConsumers, execution);
|
||||
this.listeners = listeners;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
arguments.addListener(this::onSupplierChange);
|
||||
valueConsumers.addListener(this::onConsumerChange);
|
||||
}
|
||||
|
||||
public ConfiguredInstruction(InstructionType<R> instruction) {
|
||||
@@ -52,13 +65,14 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
|
||||
execution.start(minion);
|
||||
} catch (Exception e) {
|
||||
Minions.LOGGER.error("An error occurred while executing configured Instruction", e);
|
||||
|
||||
}
|
||||
|
||||
listeners.forEachListener(listener -> listener.onRun(this));
|
||||
}
|
||||
}
|
||||
|
||||
public void tick(R minion) {
|
||||
if(isRunning()) {
|
||||
if(execution != null) {
|
||||
if(execution.isDone(minion)) {
|
||||
stop(minion);
|
||||
} else {
|
||||
@@ -71,20 +85,43 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
|
||||
}
|
||||
|
||||
public void stop(R minion) {
|
||||
if(isRunning()) {
|
||||
if(execution != null) {
|
||||
execution.stop(minion, valueConsumers);
|
||||
execution = null;
|
||||
listeners.forEachListener(listener -> listener.onStop(this));
|
||||
}
|
||||
}
|
||||
|
||||
private void onSupplierChange(Parameter<?> parameter) {
|
||||
listeners.forEachListener(listener -> listener.onSupplierChange(this, parameter));
|
||||
}
|
||||
|
||||
private void onConsumerChange(Parameter<?> parameter) {
|
||||
listeners.forEachListener(listener -> listener.onConsumerChange(this, parameter));
|
||||
}
|
||||
|
||||
public void onInstructionRemove() {
|
||||
listeners.forEachListener(listener -> listener.onInstructionRemove(this));
|
||||
}
|
||||
|
||||
public void addListener(ConfiguredInstructionListener listener) {
|
||||
listeners.addListener(listener);
|
||||
}
|
||||
|
||||
public void removeListener(ConfiguredInstructionListener listener) {
|
||||
listeners.removeListener(listener);
|
||||
}
|
||||
|
||||
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()) {
|
||||
if(execution != null) {
|
||||
execution.save(view.get("execution"), minion);
|
||||
}
|
||||
|
||||
listeners.save(view);
|
||||
}
|
||||
|
||||
public static <R extends InstructionRuntime<R>> ConfiguredInstruction<R> load(ReadView view, R minion) {
|
||||
@@ -95,16 +132,19 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
|
||||
|
||||
boolean running = view.getBoolean("running", false);
|
||||
|
||||
SerializableListenerManager<ConfiguredInstructionListener> listeners = new SerializableListenerManager<>(MinionRegistries.INSTRUCTION_LISTENER_CODECS);
|
||||
listeners.load(view);
|
||||
|
||||
if(running) {
|
||||
ReadView executionView = view.getReadView("execution");
|
||||
try {
|
||||
InstructionExecution<R> execution = instructionType.loadExecution(executionView, minion);
|
||||
return new ConfiguredInstruction<>(instructionType, arguments, valueConsumers, execution);
|
||||
return new ConfiguredInstruction<>(instructionType, arguments, valueConsumers, execution, listeners);
|
||||
} catch (Exception e) {
|
||||
Minions.LOGGER.error("Error while loading execution", e);
|
||||
}
|
||||
}
|
||||
|
||||
return new ConfiguredInstruction<>(instructionType, arguments, valueConsumers, null);
|
||||
return new ConfiguredInstruction<>(instructionType, arguments, valueConsumers, null, listeners);
|
||||
}
|
||||
}
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package io.github.skippyall.minions.program.instruction;
|
||||
|
||||
import io.github.skippyall.minions.program.supplier.Parameter;
|
||||
import io.github.skippyall.minions.util.SerializableListenerManager;
|
||||
|
||||
public interface ConfiguredInstructionListener extends SerializableListenerManager.SerializableListener {
|
||||
default void onRun(ConfiguredInstruction<?> instruction) {}
|
||||
|
||||
default void onStop(ConfiguredInstruction<?> instruction) {}
|
||||
|
||||
default void onSupplierChange(ConfiguredInstruction<?> instruction, Parameter<?> parameter) {}
|
||||
|
||||
default void onConsumerChange(ConfiguredInstruction<?> instruction, Parameter<?> parameter) {}
|
||||
|
||||
default void onInstructionRemove(ConfiguredInstruction<?> instruction) {}
|
||||
}
|
||||
+12
-1
@@ -37,7 +37,7 @@ public interface InstructionExecution<R extends InstructionRuntime<R>> {
|
||||
*
|
||||
* @param runtime The runtime that was executing this instruction.
|
||||
*/
|
||||
void stop(R runtime, ValueConsumerList<R> valueConsumers);
|
||||
default void stop(R runtime, ValueConsumerList<R> valueConsumers) {}
|
||||
|
||||
/**
|
||||
* Initializes the execution with its parameters. The parameters must be defined by the InstructionType
|
||||
@@ -55,4 +55,15 @@ public interface InstructionExecution<R extends InstructionRuntime<R>> {
|
||||
* Loads the execution, e.g. when the server is started.
|
||||
*/
|
||||
void load(ReadView view, R runtime);
|
||||
|
||||
interface Stateless<R extends InstructionRuntime<R>> extends InstructionExecution<R> {
|
||||
@Override
|
||||
default void readArguments(ValueSupplierList<R> arguments, R runtime) {}
|
||||
|
||||
@Override
|
||||
default void save(WriteView view, R runtime) {}
|
||||
|
||||
@Override
|
||||
default void load(ReadView view, R runtime) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
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.supplier.Parameter;
|
||||
import io.github.skippyall.minions.program.supplier.ValueSupplierList;
|
||||
@@ -11,30 +10,24 @@ import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class InstructionType<R extends InstructionRuntime<R>> {
|
||||
private final GuiDisplay display;
|
||||
private final Collection<Parameter<?>> parameters;
|
||||
private final Collection<Parameter<?>> returnParameters;
|
||||
private final List<Parameter<?>> parameters;
|
||||
private final List<Parameter<?>> returnParameters;
|
||||
private final Supplier<InstructionExecution<R>> executionFactory;
|
||||
|
||||
public InstructionType(GuiDisplay display, Supplier<InstructionExecution<R>> executionFactory, Collection<Parameter<?>> parameters, Collection<Parameter<?>> returnParameters) {
|
||||
this.display = display;
|
||||
public InstructionType(Supplier<InstructionExecution<R>> executionFactory, Collection<Parameter<?>> parameters, Collection<Parameter<?>> returnParameters) {
|
||||
this.parameters = List.copyOf(parameters);
|
||||
this.returnParameters = List.copyOf(returnParameters);
|
||||
this.executionFactory = executionFactory;
|
||||
}
|
||||
|
||||
public Collection<Parameter<?>> getParameters() {
|
||||
public List<Parameter<?>> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public Collection<Parameter<?>> getReturnParameters() {
|
||||
public List<Parameter<?>> getReturnParameters() {
|
||||
return returnParameters;
|
||||
}
|
||||
|
||||
public GuiDisplay getDisplay() {
|
||||
return display;
|
||||
}
|
||||
|
||||
public InstructionExecution<R> createExecution(ValueSupplierList<R> parameters, R minion) {
|
||||
InstructionExecution<R> execution = executionFactory.get();
|
||||
execution.readArguments(parameters, minion);
|
||||
|
||||
@@ -2,60 +2,71 @@ 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.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.instruction.execution.MineBlockExecution;
|
||||
import io.github.skippyall.minions.program.instruction.execution.move.ContinuousWalkExecution;
|
||||
import io.github.skippyall.minions.program.instruction.execution.move.TurnExecution;
|
||||
import io.github.skippyall.minions.program.instruction.execution.move.TurnVectorExecution;
|
||||
import io.github.skippyall.minions.program.instruction.execution.move.WalkExecution;
|
||||
import io.github.skippyall.minions.program.supplier.Parameter;
|
||||
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<MinionRuntime> WALK = register(
|
||||
"walk",
|
||||
base -> new GuiDisplay.ModelBased(Items.IRON_BOOTS, base, true),
|
||||
WalkExecution::new,
|
||||
List.of(WalkExecution.blocksToMoveParam)
|
||||
);
|
||||
public static final InstructionType<MinionRuntime> WALK_CONTINUOUS = register(
|
||||
"walk_continuous",
|
||||
ContinuousWalkExecution::new
|
||||
);
|
||||
|
||||
public static final InstructionType<MinionRuntime> TURN = register(
|
||||
"turn",
|
||||
base -> new GuiDisplay.ModelBased(Items.STRUCTURE_VOID, base, true),
|
||||
TurnExecution::new,
|
||||
List.of(TurnExecution.ANGLE, TurnExecution.DIRECTION)
|
||||
);
|
||||
|
||||
public static final InstructionType<MinionRuntime> TURN_VECTOR = register(
|
||||
"turn_vector",
|
||||
TurnVectorExecution::new,
|
||||
List.of(TurnVectorExecution.X, TurnVectorExecution.Y, TurnVectorExecution.Z)
|
||||
);
|
||||
|
||||
public static final InstructionType<MinionRuntime> ATTACK = register(
|
||||
"attack",
|
||||
base -> new GuiDisplay.ModelBased(Items.IRON_PICKAXE, base, true),
|
||||
() -> new ActionExecution(EntityPlayerActionPack.ActionType.ATTACK)
|
||||
);
|
||||
|
||||
public static final InstructionType<MinionRuntime> MINE_BLOCK = register(
|
||||
"mine_block",
|
||||
MineBlockExecution::new
|
||||
);
|
||||
|
||||
public static final InstructionType<MinionRuntime> USE = register(
|
||||
"use",
|
||||
base -> new GuiDisplay.ModelBased(Items.LEVER, base, true),
|
||||
() -> new ActionExecution(EntityPlayerActionPack.ActionType.USE)
|
||||
);
|
||||
|
||||
private static InstructionType<MinionRuntime> register(String id, Function<String, GuiDisplay> displayFunction, Supplier<InstructionExecution<MinionRuntime>> factory, Collection<Parameter<?>> parameters, Collection<Parameter<?>> returnParameters) {
|
||||
private static InstructionType<MinionRuntime> register(String id, Supplier<InstructionExecution<MinionRuntime>> factory, Collection<Parameter<?>> parameters, Collection<Parameter<?>> returnParameters) {
|
||||
Identifier identifier = Identifier.of(Minions.MOD_ID, id);
|
||||
return Registry.register(MinionRegistries.INSTRUCTION_TYPES, identifier, new InstructionType<>(displayFunction.apply(identifier.toTranslationKey("instruction_type")), factory, parameters, returnParameters));
|
||||
return Registry.register(MinionRegistries.INSTRUCTION_TYPES, identifier, new InstructionType<>(factory, parameters, returnParameters));
|
||||
}
|
||||
|
||||
private static InstructionType<MinionRuntime> register(String id, Function<String, GuiDisplay> displayFunction, Supplier<InstructionExecution<MinionRuntime>> factory, Collection<Parameter<?>> parameters) {
|
||||
return register(id, displayFunction, factory, parameters, List.of());
|
||||
private static InstructionType<MinionRuntime> register(String id, Supplier<InstructionExecution<MinionRuntime>> factory, Collection<Parameter<?>> parameters) {
|
||||
return register(id, factory, parameters, List.of());
|
||||
}
|
||||
|
||||
private static InstructionType<MinionRuntime> register(String id, Function<String, GuiDisplay> displayFunction, Supplier<InstructionExecution<MinionRuntime>> factory) {
|
||||
return register(id, displayFunction, factory, List.of(), List.of());
|
||||
private static InstructionType<MinionRuntime> register(String id, Supplier<InstructionExecution<MinionRuntime>> factory) {
|
||||
return register(id, factory, List.of(), List.of());
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
|
||||
+4
-1
@@ -16,7 +16,10 @@ public class ActionExecution implements ContinuousInstructionExecution<MinionRun
|
||||
|
||||
@Override
|
||||
public void start(MinionRuntime minion) {
|
||||
minion.getMinion().getMinionActionPack().start(action, EntityPlayerActionPack.Action.continuous());
|
||||
EntityPlayerActionPack ap = minion.getMinion().getMinionActionPack();
|
||||
if(!ap.hasAction(action)) {
|
||||
minion.getMinion().getMinionActionPack().start(action, EntityPlayerActionPack.Action.startContinuous());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
//partially code from https://github.com/gnembon/fabric-carpet (EntityPlayerActionPack)
|
||||
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.consumer.ValueConsumerList;
|
||||
import io.github.skippyall.minions.program.instruction.InstructionExecution;
|
||||
import io.github.skippyall.minions.program.supplier.ValueSupplierList;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
|
||||
import net.minecraft.storage.ReadView;
|
||||
import net.minecraft.storage.WriteView;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
public class MineBlockExecution implements InstructionExecution<MinionRuntime> {
|
||||
private BlockPos currentBlock;
|
||||
private float currentBlockDamage = 0;
|
||||
private boolean first = true;
|
||||
private boolean done = false;
|
||||
private boolean success = false;
|
||||
|
||||
@Override
|
||||
public void start(MinionRuntime runtime) {
|
||||
MinionFakePlayer player = runtime.getMinion();
|
||||
if(EntityPlayerActionPack.getTarget(player) instanceof BlockHitResult hit) {
|
||||
this.currentBlock = hit.getBlockPos();
|
||||
|
||||
EntityPlayerActionPack ap = player.getMinionActionPack();
|
||||
if (ap.blockHitDelay > 0) {
|
||||
ap.blockHitDelay--;
|
||||
done = true;
|
||||
return;
|
||||
}
|
||||
if (player.isBlockBreakingRestricted(player.getWorld(), hit.getBlockPos(), player.interactionManager.getGameMode())) {
|
||||
done = true;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(MinionRuntime runtime) {
|
||||
if(done) {
|
||||
return;
|
||||
}
|
||||
|
||||
MinionFakePlayer player = runtime.getMinion();
|
||||
EntityPlayerActionPack ap = player.getMinionActionPack();
|
||||
|
||||
HitResult newHit = EntityPlayerActionPack.getTarget(player);
|
||||
if(!(newHit instanceof BlockHitResult newBlockHit)) {
|
||||
done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos newPos = newBlockHit.getBlockPos();
|
||||
if(!newPos.equals(currentBlock)) {
|
||||
done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.getWorld().getBlockState(currentBlock).isAir()) {
|
||||
done = true;
|
||||
return;
|
||||
}
|
||||
BlockState state = player.getWorld().getBlockState(currentBlock);
|
||||
boolean blockBroken = false;
|
||||
if (first) {
|
||||
first = false;
|
||||
player.interactionManager.processBlockBreakingAction(currentBlock, PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, newBlockHit.getSide(), player.getWorld().getTopYInclusive(), -1);
|
||||
boolean notAir = !state.isAir();
|
||||
if (notAir)
|
||||
{
|
||||
state.onBlockBreakStart(player.getWorld(), currentBlock, player);
|
||||
}
|
||||
if (notAir && state.calcBlockBreakingDelta(player, player.getWorld(), currentBlock) >= 1)
|
||||
{
|
||||
//instamine??
|
||||
blockBroken = true;
|
||||
}
|
||||
} else {
|
||||
currentBlockDamage += state.calcBlockBreakingDelta(player, player.getWorld(), currentBlock);
|
||||
if (currentBlockDamage >= 1) {
|
||||
player.interactionManager.processBlockBreakingAction(currentBlock, PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, newBlockHit.getSide(), player.getWorld().getTopYInclusive(), -1);
|
||||
ap.blockHitDelay = 5;
|
||||
blockBroken = true;
|
||||
}
|
||||
player.getWorld().setBlockBreakingInfo(-1, currentBlock, (int) (currentBlockDamage * 10));
|
||||
|
||||
}
|
||||
player.updateLastActionTime();
|
||||
player.swingHand(Hand.MAIN_HAND);
|
||||
|
||||
if(blockBroken) {
|
||||
done = true;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone(MinionRuntime runtime) {
|
||||
return done;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(MinionRuntime runtime, ValueConsumerList<MinionRuntime> valueConsumers) {
|
||||
MinionFakePlayer player = runtime.getMinion();
|
||||
EntityPlayerActionPack ap = player.getMinionActionPack();
|
||||
|
||||
player.getWorld().setBlockBreakingInfo(-1, currentBlock, -1);
|
||||
player.interactionManager.processBlockBreakingAction(currentBlock, PlayerActionC2SPacket.Action.ABORT_DESTROY_BLOCK, Direction.DOWN, player.getWorld().getTopYInclusive(), -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readArguments(ValueSupplierList<MinionRuntime> arguments, MinionRuntime runtime) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(WriteView view, MinionRuntime runtime) {
|
||||
view.put("currentBlock", BlockPos.CODEC, currentBlock);
|
||||
view.putFloat("currentBlockDamage", currentBlockDamage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(ReadView view, MinionRuntime runtime) {
|
||||
currentBlock = view.read("currentBlock", BlockPos.CODEC).orElse(null);
|
||||
currentBlockDamage = view.getFloat("currentBlockDamage", 0);
|
||||
if(currentBlock == null) {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
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.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;
|
||||
import net.minecraft.storage.WriteView;
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class TurnExecution implements InstructionExecution<MinionRuntime> {
|
||||
public static final Parameter<Float> ANGLE = new Parameter<>("maxAngle", ValueTypes.FLOAT);
|
||||
public static final Parameter<TurnDirection> DIRECTION = new Parameter<>("direction", ValueTypes.TURN_DIRECTION);
|
||||
|
||||
private static final float anglePerTick = 5;
|
||||
|
||||
private float maxAngle;
|
||||
private float rotatedAngle;
|
||||
private TurnDirection direction;
|
||||
|
||||
@Override
|
||||
public void tick(MinionRuntime minion) {
|
||||
float toRotate = Math.min(anglePerTick, maxAngle - rotatedAngle);
|
||||
minion.getMinion().getMinionActionPack().turn(direction.xFactor * toRotate, direction.yFactor * toRotate);
|
||||
|
||||
rotatedAngle += toRotate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone(MinionRuntime minion) {
|
||||
return Math.abs(maxAngle - rotatedAngle) < 0.001F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(MinionRuntime minion, ValueConsumerList<MinionRuntime> valueConsumers) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readArguments(ValueSupplierList<MinionRuntime> arguments, MinionRuntime minion) {
|
||||
maxAngle = arguments.getValue(ANGLE, minion);
|
||||
direction = arguments.getValue(DIRECTION, minion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(WriteView view, MinionRuntime minion) {
|
||||
view.putFloat("maxAngle", maxAngle);
|
||||
view.put("direction", TurnDirection.CODEC, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(ReadView view, MinionRuntime minion) {
|
||||
maxAngle = view.getFloat("maxAngle", 0);
|
||||
direction = view.read("direction", TurnDirection.CODEC).orElseThrow();
|
||||
}
|
||||
|
||||
public enum TurnDirection implements StringIdentifiable, Displayable {
|
||||
LEFT("left", -1, 0),
|
||||
UP("up", 0, -1),
|
||||
RIGHT("right", 1, 0),
|
||||
DOWN("down", 0, 1);
|
||||
|
||||
public static final Codec<TurnDirection> CODEC = StringIdentifiable.createCodec(TurnDirection::values);
|
||||
|
||||
private static final UUID MHF_ArrowLeft = UUID.fromString("a68f0b64-8d14-4000-a95f-4b9ba14f8df9");
|
||||
private static final UUID MHF_ArrowUp = UUID.fromString("fef039ef-e6cd-4987-9c84-26a3e6134277");
|
||||
private static final UUID MHF_ArrowRight = UUID.fromString("50c8510b-5ea0-4d60-be9a-7d542d6cd156");
|
||||
private static final UUID MHF_ArrowDown = UUID.fromString("68f59b9b-5b0b-4b05-a9f2-e1d1405aa348");
|
||||
|
||||
public final String name;
|
||||
public final int xFactor;
|
||||
public final int yFactor;
|
||||
|
||||
TurnDirection(String name, int xFactor, int yFactor) {
|
||||
this.xFactor = xFactor;
|
||||
this.yFactor = yFactor;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiDisplay getDisplay() {
|
||||
return switch (this) {
|
||||
case LEFT -> new GuiDisplay.HeadBased(MHF_ArrowLeft, "minions.direction.left", false);
|
||||
case UP -> new GuiDisplay.HeadBased(MHF_ArrowUp, "minions.direction.up", false);
|
||||
case RIGHT -> new GuiDisplay.HeadBased(MHF_ArrowRight, "minions.direction.right", false);
|
||||
case DOWN -> new GuiDisplay.HeadBased(MHF_ArrowDown, "minions.direction.down", false);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package io.github.skippyall.minions.program.instruction.execution.move;
|
||||
|
||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||
import io.github.skippyall.minions.program.instruction.InstructionExecution;
|
||||
import net.minecraft.storage.ReadView;
|
||||
import net.minecraft.storage.WriteView;
|
||||
|
||||
public abstract class AbstractTurnExecution implements InstructionExecution<MinionRuntime> {
|
||||
protected float targetYaw;
|
||||
protected float targetPitch;
|
||||
|
||||
private static final float anglePerTick = 10;
|
||||
|
||||
@Override
|
||||
public void tick(MinionRuntime minion) {
|
||||
float rotateYaw = targetYaw - minion.getMinion().getYaw();
|
||||
float rotatePitch = targetPitch - minion.getMinion().getPitch();
|
||||
|
||||
minion.getMinion().getMinionActionPack().turn(Math.min(rotateYaw, anglePerTick), Math.min(rotatePitch, anglePerTick));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone(MinionRuntime minion) {
|
||||
return Math.abs(targetYaw - minion.getMinion().getYaw()) < 0.001F && Math.abs(targetPitch - minion.getMinion().getPitch()) < 0.001F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(WriteView view, MinionRuntime runtime) {
|
||||
view.putFloat("targetYaw", targetYaw);
|
||||
view.putFloat("targetPitch", targetPitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(ReadView view, MinionRuntime runtime) {
|
||||
targetYaw = view.getFloat("targetYaw", 0);
|
||||
targetPitch = view.getFloat("targetPitch", 0);
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package io.github.skippyall.minions.program.instruction.execution.move;
|
||||
|
||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||
import io.github.skippyall.minions.program.instruction.InstructionExecution;
|
||||
import io.github.skippyall.minions.program.instruction.execution.ContinuousInstructionExecution;
|
||||
import net.minecraft.entity.MovementType;
|
||||
|
||||
public class ContinuousWalkExecution implements ContinuousInstructionExecution<MinionRuntime>, InstructionExecution.Stateless<MinionRuntime> {
|
||||
@Override
|
||||
public void tick(MinionRuntime minion) {
|
||||
minion.getMinion().move(MovementType.SELF, minion.getMinion().getHorizontalFacing().getDoubleVector().normalize().multiply(minion.getMinion().getMovementSpeed()));
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package io.github.skippyall.minions.program.instruction.execution.move;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import io.github.skippyall.minions.gui.Displayable;
|
||||
import io.github.skippyall.minions.gui.GuiDisplay;
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public enum TurnDirection implements StringIdentifiable, Displayable {
|
||||
LEFT("left", -1, 0),
|
||||
UP("up", 0, -1),
|
||||
RIGHT("right", 1, 0),
|
||||
DOWN("down", 0, 1);
|
||||
|
||||
public static final Codec<TurnDirection> CODEC = StringIdentifiable.createCodec(TurnDirection::values);
|
||||
|
||||
private static final UUID MHF_ArrowLeft = UUID.fromString("a68f0b64-8d14-4000-a95f-4b9ba14f8df9");
|
||||
private static final UUID MHF_ArrowUp = UUID.fromString("fef039ef-e6cd-4987-9c84-26a3e6134277");
|
||||
private static final UUID MHF_ArrowRight = UUID.fromString("50c8510b-5ea0-4d60-be9a-7d542d6cd156");
|
||||
private static final UUID MHF_ArrowDown = UUID.fromString("68f59b9b-5b0b-4b05-a9f2-e1d1405aa348");
|
||||
|
||||
public final String name;
|
||||
public final int xFactor;
|
||||
public final int yFactor;
|
||||
|
||||
TurnDirection(String name, int xFactor, int yFactor) {
|
||||
this.xFactor = xFactor;
|
||||
this.yFactor = yFactor;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiDisplay getDisplay() {
|
||||
return switch (this) {
|
||||
case LEFT -> new GuiDisplay.HeadBased(MHF_ArrowLeft);
|
||||
case UP -> new GuiDisplay.HeadBased(MHF_ArrowUp);
|
||||
case RIGHT -> new GuiDisplay.HeadBased(MHF_ArrowRight);
|
||||
case DOWN -> new GuiDisplay.HeadBased(MHF_ArrowDown);
|
||||
};
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package io.github.skippyall.minions.program.instruction.execution.move;
|
||||
|
||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||
import io.github.skippyall.minions.program.supplier.ValueSupplierList;
|
||||
import io.github.skippyall.minions.program.supplier.Parameter;
|
||||
import io.github.skippyall.minions.program.value.ValueTypes;
|
||||
|
||||
public class TurnExecution extends AbstractTurnExecution {
|
||||
public static final Parameter<Double> ANGLE = new Parameter<>("maxAngle", ValueTypes.DOUBLE);
|
||||
public static final Parameter<TurnDirection> DIRECTION = new Parameter<>("direction", ValueTypes.TURN_DIRECTION);
|
||||
|
||||
@Override
|
||||
public void readArguments(ValueSupplierList<MinionRuntime> arguments, MinionRuntime minion) {
|
||||
float maxAngle = arguments.getValue(ANGLE, minion).floatValue();
|
||||
TurnDirection direction = arguments.getValue(DIRECTION, minion);
|
||||
|
||||
float turnYaw = maxAngle * direction.xFactor;
|
||||
float turnPitch = maxAngle * direction.yFactor;
|
||||
|
||||
targetYaw = minion.getMinion().getYaw() + turnYaw;
|
||||
targetPitch = minion.getMinion().getPitch() + turnPitch;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package io.github.skippyall.minions.program.instruction.execution.move;
|
||||
|
||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||
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.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec2f;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class TurnVectorExecution extends AbstractTurnExecution {
|
||||
public static final Parameter<Double> X = new Parameter<>("x", ValueTypes.DOUBLE);
|
||||
public static final Parameter<Double> Y = new Parameter<>("y", ValueTypes.DOUBLE);
|
||||
public static final Parameter<Double> Z = new Parameter<>("z", ValueTypes.DOUBLE);
|
||||
|
||||
@Override
|
||||
public void readArguments(ValueSupplierList<MinionRuntime> arguments, MinionRuntime runtime) {
|
||||
double x = arguments.getValue(X, runtime);
|
||||
double y = arguments.getValue(Y, runtime);
|
||||
double z = arguments.getValue(Z, runtime);
|
||||
|
||||
Vec3d vector = new Vec3d(x, y, z);
|
||||
Vec2f rotation = vectorToRotation(vector);
|
||||
targetYaw = rotation.x;
|
||||
targetPitch = rotation.y;
|
||||
}
|
||||
|
||||
//copied from Entity#lookAt (why no helper, Mojang?)
|
||||
public static Vec2f vectorToRotation(Vec3d vector) {
|
||||
double g = Math.sqrt(vector.x * vector.x + vector.z * vector.z);
|
||||
float pitch = MathHelper.wrapDegrees((float)(-(MathHelper.atan2(vector.y, g) * 180.0F / (float)Math.PI)));
|
||||
float yaw = MathHelper.wrapDegrees((float)(MathHelper.atan2(vector.z, vector.x) * 180.0F / (float)Math.PI) - 90.0F);
|
||||
|
||||
return new Vec2f(yaw, pitch);
|
||||
}
|
||||
}
|
||||
+10
-16
@@ -1,7 +1,6 @@
|
||||
package io.github.skippyall.minions.program.instruction.execution;
|
||||
package io.github.skippyall.minions.program.instruction.execution.move;
|
||||
|
||||
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.supplier.Parameter;
|
||||
import io.github.skippyall.minions.program.supplier.ValueSupplierList;
|
||||
@@ -11,15 +10,15 @@ import net.minecraft.storage.ReadView;
|
||||
import net.minecraft.storage.WriteView;
|
||||
|
||||
public class WalkExecution implements InstructionExecution<MinionRuntime> {
|
||||
public static final Parameter<Float> blocksToMoveParam = new Parameter<>("blocksToMove", ValueTypes.FLOAT);
|
||||
public static final Parameter<Double> blocksToMoveParam = new Parameter<>("blocksToMove", ValueTypes.DOUBLE);
|
||||
private static final float ACCURACY = 1F / 32F;
|
||||
|
||||
private float totalBlocksToMove;
|
||||
private float blocksMoved;
|
||||
private double totalBlocksToMove;
|
||||
private double blocksMoved;
|
||||
|
||||
@Override
|
||||
public void tick(MinionRuntime minion) {
|
||||
float speed = Math.min(minion.getMinion().getMovementSpeed(), totalBlocksToMove - blocksMoved);
|
||||
double speed = Math.min(minion.getMinion().getMovementSpeed(), totalBlocksToMove - blocksMoved);
|
||||
minion.getMinion().move(MovementType.SELF, minion.getMinion().getHorizontalFacing().getDoubleVector().normalize().multiply(speed));
|
||||
blocksMoved += speed;
|
||||
}
|
||||
@@ -29,26 +28,21 @@ public class WalkExecution implements InstructionExecution<MinionRuntime> {
|
||||
return totalBlocksToMove - blocksMoved < ACCURACY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(MinionRuntime minion, ValueConsumerList<MinionRuntime> valueConsumers) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readArguments(ValueSupplierList<MinionRuntime> parameters, MinionRuntime minion) {
|
||||
totalBlocksToMove = parameters.getValue(blocksToMoveParam, minion);
|
||||
totalBlocksToMove = parameters.getValue(blocksToMoveParam, minion).floatValue();
|
||||
blocksMoved = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(WriteView view, MinionRuntime minion) {
|
||||
view.putFloat("totalBlocksToMove", totalBlocksToMove);
|
||||
view.putFloat("blocksMoved", blocksMoved);
|
||||
view.putDouble("totalBlocksToMove", totalBlocksToMove);
|
||||
view.putDouble("blocksMoved", blocksMoved);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(ReadView view, MinionRuntime minion) {
|
||||
totalBlocksToMove = view.getFloat("totalBlocksToMove", 0F);
|
||||
blocksMoved = view.getFloat("blocksMoved", 0F);
|
||||
totalBlocksToMove = view.getDouble("totalBlocksToMove", 0F);
|
||||
blocksMoved = view.getDouble("blocksMoved", 0F);
|
||||
}
|
||||
}
|
||||
+5
-11
@@ -1,18 +1,17 @@
|
||||
package io.github.skippyall.minions.program.supplier;
|
||||
|
||||
import io.github.skippyall.minions.gui.GuiDisplay;
|
||||
import io.github.skippyall.minions.program.InstructionRuntime;
|
||||
import io.github.skippyall.minions.program.value.ValueType;
|
||||
|
||||
/**
|
||||
* An supplier that always resolves to a fixed value
|
||||
* A supplier that always resolves to a fixed value
|
||||
*/
|
||||
public class ValueArgument<T, R extends InstructionRuntime<R>> implements ValueSupplier<T, R> {
|
||||
private final ValueArgumentType<R> type;
|
||||
public class FixedValueSupplier<T, R extends InstructionRuntime<R>> implements ValueSupplier<T, R> {
|
||||
private final FixedValueSupplierType<R> type;
|
||||
private final ValueType<T> valueType;
|
||||
private final T value;
|
||||
|
||||
public ValueArgument(ValueArgumentType<R> type, ValueType<T> valueType, T value) {
|
||||
public FixedValueSupplier(FixedValueSupplierType<R> type, ValueType<T> valueType, T value) {
|
||||
this.type = type;
|
||||
this.valueType = valueType;
|
||||
this.value = value;
|
||||
@@ -27,18 +26,13 @@ public class ValueArgument<T, R extends InstructionRuntime<R>> implements ValueS
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiDisplay getDisplay() {
|
||||
return getValueType().display();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueType<T> getValueType() {
|
||||
return valueType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueArgumentType<R> getType() {
|
||||
public FixedValueSupplierType<R> getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
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 class FixedValueSupplierType<R extends InstructionRuntime<R>> extends ValueSupplierType<R> {
|
||||
@Override
|
||||
public <T> Codec<FixedValueSupplier<T,R>> getCodec(ValueType<T> valueType) {
|
||||
return valueType.codec().xmap(value -> new FixedValueSupplier<>(this, valueType, value), FixedValueSupplier::getValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> CompletableFuture<FixedValueSupplier<V,R>> openConfiguration(ServerPlayerEntity player, ValueType<V> valueType, @Nullable ValueSupplier<V,R> previousValueSupplier) {
|
||||
return valueType.openValueDialog(
|
||||
player,
|
||||
previousValueSupplier instanceof FixedValueSupplier<V,R> val ? val.getValue() : valueType.defaultValue()
|
||||
).thenApply(value -> new FixedValueSupplier<>(this, valueType, value));
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
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 class ValueArgumentType<R extends InstructionRuntime<R>> extends ValueSupplierType<R> {
|
||||
@Override
|
||||
public <T> Codec<ValueArgument<T,R>> getCodec(ValueType<T> valueType) {
|
||||
return valueType.codec().xmap(value -> new ValueArgument<>(this, valueType, value), ValueArgument::getValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> CompletableFuture<ValueArgument<V,R>> openConfiguration(ServerPlayerEntity player, ValueType<V> valueType, @Nullable ValueSupplier<V,R> previousValueSupplier) {
|
||||
return valueType.openValueDialog(
|
||||
player,
|
||||
previousValueSupplier instanceof ValueArgument<V,R> val ? val.getValue() : valueType.defaultValue()
|
||||
).thenApply(value -> new ValueArgument<>(this, valueType, value));
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ 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;
|
||||
@@ -16,8 +15,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
public interface ValueSupplier<T, R extends InstructionRuntime<R>> {
|
||||
T resolve(R minion);
|
||||
|
||||
GuiDisplay getDisplay();
|
||||
|
||||
ValueType<T> getValueType();
|
||||
|
||||
ValueSupplierType<R> getType();
|
||||
|
||||
@@ -3,12 +3,16 @@ package io.github.skippyall.minions.program.supplier;
|
||||
import com.mojang.serialization.Codec;
|
||||
import io.github.skippyall.minions.program.InstructionRuntime;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ValueSupplierList<R extends InstructionRuntime<R>> {
|
||||
private final Map<String, ValueSupplier<?, R>> arguments;
|
||||
private final List<Consumer<Parameter<?>>> changeListeners = new ArrayList<>();
|
||||
|
||||
public ValueSupplierList() {
|
||||
arguments = new HashMap<>();
|
||||
@@ -30,10 +34,11 @@ public class ValueSupplierList<R extends InstructionRuntime<R>> {
|
||||
|
||||
public <T> void setArgument(Parameter<T> parameter, ValueSupplier<T,R> valueSupplier) {
|
||||
arguments.put(parameter.name(), valueSupplier);
|
||||
onChange(parameter);
|
||||
}
|
||||
|
||||
public boolean hasArgumentFor(Parameter<?> parameter) {
|
||||
return getArgument(parameter) != null;
|
||||
return arguments.containsKey(parameter.name());
|
||||
}
|
||||
|
||||
public boolean hasArgumentForAll(Collection<Parameter<?>> checkParameters) {
|
||||
@@ -45,6 +50,21 @@ public class ValueSupplierList<R extends InstructionRuntime<R>> {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void onChange(Parameter<?> parameter) {
|
||||
for (Consumer<Parameter<?>> listener : changeListeners) {
|
||||
listener.accept(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(Consumer<Parameter<?>> listener) {
|
||||
changeListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(Consumer<Parameter<?>> listener) {
|
||||
changeListeners.remove(listener);
|
||||
}
|
||||
|
||||
public static <R extends InstructionRuntime<R>> Codec<ValueSupplierList<R>> getCodec(Codec<ValueSupplier<?,R>> argumentCodec) {
|
||||
return Codec.unboundedMap(Codec.STRING, argumentCodec)
|
||||
.xmap(ValueSupplierList::new, list -> list.arguments);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.github.skippyall.minions.program.supplier;
|
||||
|
||||
import io.github.skippyall.minions.MinionRegistries;
|
||||
import io.github.skippyall.minions.Minions;
|
||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class ValueSuppliers {
|
||||
public static final FixedValueSupplierType<MinionRuntime> FIXED_VALUE_SUPPLIER_TYPE = register("fixed", new FixedValueSupplierType<>());
|
||||
|
||||
public static <T extends ValueSupplierType<MinionRuntime>> T register(String id, T type) {
|
||||
return Registry.register(MinionRegistries.VALUE_SUPPLIER_TYPES, Identifier.of(Minions.MOD_ID, id), type);
|
||||
}
|
||||
|
||||
public static void register() {}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package io.github.skippyall.minions.program.value;
|
||||
|
||||
import io.github.skippyall.minions.gui.input.Result;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public interface RestrictionRule<T> {
|
||||
Result<Void, Text> validate(T value);
|
||||
|
||||
default boolean matches(T value) {
|
||||
return validate(value).isSuccess();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package io.github.skippyall.minions.program.value;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public record TypeRestriction<T>(ValueType<T> type, Collection<RestrictionRule<T>> rules) {
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
package io.github.skippyall.minions.program.value;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import io.github.skippyall.minions.gui.Displayable;
|
||||
import io.github.skippyall.minions.gui.GuiDisplay;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public record ValueType<T>(Codec<T> codec, GuiDisplay display, T defaultValue, BiFunction<ServerPlayerEntity, T, CompletableFuture<T>> valueDialogOpener) {
|
||||
public record ValueType<T>(Codec<T> codec, T defaultValue, BiFunction<ServerPlayerEntity, T, CompletableFuture<T>> valueDialogOpener) {
|
||||
public CompletableFuture<T> openValueDialog(ServerPlayerEntity player, T previousValue) {
|
||||
return valueDialogOpener.apply(player, previousValue);
|
||||
}
|
||||
|
||||
@@ -3,11 +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.GuiDisplay;
|
||||
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 io.github.skippyall.minions.program.instruction.execution.move.TurnDirection;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
@@ -15,27 +13,24 @@ import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ValueTypes {
|
||||
public static ValueType<Integer> INTEGER = registerSimple(
|
||||
"integer",
|
||||
Codec.INT,
|
||||
key -> new GuiDisplay.ModelBased(Items.NETHERITE_SCRAP, key, true),
|
||||
0,
|
||||
(player, oldValue) -> TextInput.inputInt(
|
||||
public static ValueType<Long> LONG = registerSimple(
|
||||
"long",
|
||||
Codec.LONG,
|
||||
0L,
|
||||
(player, oldValue) -> TextInput.inputLong(
|
||||
player,
|
||||
Text.literal("Integer"),
|
||||
String.valueOf(oldValue)
|
||||
)
|
||||
);
|
||||
|
||||
public static ValueType<Float> FLOAT = registerSimple(
|
||||
"float",
|
||||
Codec.FLOAT,
|
||||
key -> new GuiDisplay.ModelBased(Items.BAMBOO_RAFT, key, true),
|
||||
0F,
|
||||
(player, oldValue) -> TextInput.inputFloat(
|
||||
public static ValueType<Double> DOUBLE = registerSimple(
|
||||
"double",
|
||||
Codec.DOUBLE,
|
||||
0D,
|
||||
(player, oldValue) -> TextInput.inputDouble(
|
||||
player,
|
||||
Text.literal("Number"),
|
||||
String.valueOf(oldValue)
|
||||
@@ -45,7 +40,6 @@ public class ValueTypes {
|
||||
public static ValueType<String> STRING = registerSimple(
|
||||
"string",
|
||||
Codec.STRING,
|
||||
key -> new GuiDisplay.ModelBased(Items.STRING, key, true),
|
||||
"",
|
||||
((player, oldValue) -> TextInput.inputString(
|
||||
player,
|
||||
@@ -54,30 +48,20 @@ public class ValueTypes {
|
||||
)
|
||||
);
|
||||
|
||||
public static ValueType<TurnExecution.TurnDirection> TURN_DIRECTION = registerSimple(
|
||||
public static ValueType<TurnDirection> TURN_DIRECTION = registerSimple(
|
||||
"turn_direction",
|
||||
TurnExecution.TurnDirection.CODEC,
|
||||
base -> new GuiDisplay.ModelBased(Items.STRUCTURE_VOID, base, true),
|
||||
TurnExecution.TurnDirection.RIGHT,
|
||||
ChoiceInput.createDialogOpener(TurnExecution.TurnDirection.values())
|
||||
TurnDirection.CODEC,
|
||||
TurnDirection.RIGHT,
|
||||
ChoiceInput.createDialogOpener(TurnDirection.values())
|
||||
);
|
||||
|
||||
public static ValueType<Void> VOID = registerSimple(
|
||||
"void",
|
||||
Codec.unit(null),
|
||||
key -> new GuiDisplay.ModelBased(Items.BARRIER, key, false),
|
||||
null,
|
||||
(player, oldValue) -> CompletableFuture.completedFuture(null)
|
||||
);
|
||||
|
||||
private static <T> ValueType<T> registerSimple(String id, Codec<T> codec, Function<String, GuiDisplay> displayFunction, T defaultValue, BiFunction<ServerPlayerEntity, T, CompletableFuture<T>> valueDialogOpener) {
|
||||
private static <T> ValueType<T> registerSimple(String id, Codec<T> codec, T defaultValue, BiFunction<ServerPlayerEntity, T, CompletableFuture<T>> valueDialogOpener) {
|
||||
Identifier identifier = Identifier.of(Minions.MOD_ID, id);
|
||||
return Registry.register(
|
||||
MinionRegistries.VALUE_TYPES,
|
||||
identifier,
|
||||
new ValueType<>(
|
||||
codec,
|
||||
displayFunction.apply(identifier.toTranslationKey("value_type")),
|
||||
defaultValue,
|
||||
valueDialogOpener
|
||||
)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package io.github.skippyall.minions.reference;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.component.ComponentsAccess;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.tooltip.TooltipType;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Uuids;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public record InstructionReference(UUID selectedMinion, String selectedInstruction, String visualMinionName) implements Reference {
|
||||
public static final MapCodec<InstructionReference> CODEC = RecordCodecBuilder.mapCodec(instance ->
|
||||
instance.group(
|
||||
Uuids.CODEC.fieldOf("selectedMinion").forGetter(InstructionReference::selectedMinion),
|
||||
Codec.STRING.fieldOf("selectedInstruction").forGetter(InstructionReference::selectedInstruction),
|
||||
Codec.STRING.fieldOf("visualMinionName").forGetter(InstructionReference::visualMinionName)
|
||||
).apply(instance, InstructionReference::new));
|
||||
|
||||
@Override
|
||||
public MapCodec<? extends Reference> getCodec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(Item.TooltipContext context, Consumer<Text> textConsumer, TooltipType type, ComponentsAccess components) {
|
||||
textConsumer.accept(Text.translatable("minions.reference.instruction.tooltip", selectedInstruction, visualMinionName));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package io.github.skippyall.minions.reference;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import eu.pb4.polymer.core.api.other.PolymerComponent;
|
||||
import io.github.skippyall.minions.MinionRegistries;
|
||||
import io.github.skippyall.minions.Minions;
|
||||
import net.fabricmc.fabric.api.item.v1.ComponentTooltipAppenderRegistry;
|
||||
import net.minecraft.component.ComponentType;
|
||||
import net.minecraft.item.tooltip.TooltipAppender;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface Reference extends TooltipAppender {
|
||||
Codec<Reference> CODEC = MinionRegistries.REFERENCE_CODEC.getCodec().dispatch(Reference::getCodec, Function.identity());
|
||||
ComponentType<Reference> COMPONENT_TYPE = ComponentType.<Reference>builder().codec(CODEC).build();
|
||||
|
||||
MapCodec<? extends Reference> getCodec();
|
||||
|
||||
static void register() {
|
||||
Registry.register(MinionRegistries.REFERENCE_CODEC, Identifier.of(Minions.MOD_ID, "instruction"), InstructionReference.CODEC);
|
||||
|
||||
Registry.register(Registries.DATA_COMPONENT_TYPE, Identifier.of(Minions.MOD_ID, "reference"), COMPONENT_TYPE);
|
||||
PolymerComponent.registerDataComponent(COMPONENT_TYPE);
|
||||
|
||||
ComponentTooltipAppenderRegistry.addFirst(COMPONENT_TYPE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.github.skippyall.minions.reference;
|
||||
|
||||
import eu.pb4.polymer.core.api.item.PolymerItem;
|
||||
import io.github.skippyall.minions.MinionItems;
|
||||
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.item.tooltip.TooltipType;
|
||||
import xyz.nucleoid.packettweaker.PacketContext;
|
||||
|
||||
public class ReferenceItem extends Item implements PolymerItem {
|
||||
public ReferenceItem(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getPolymerItem(ItemStack itemStack, PacketContext context) {
|
||||
return Items.PAPER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getPolymerItemStack(ItemStack itemStack, TooltipType tooltipType, PacketContext context) {
|
||||
ItemStack stack = PolymerItem.super.getPolymerItemStack(itemStack, tooltipType, context);
|
||||
stack.set(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, true);
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static ItemStack createInstructionReference(MinionFakePlayer minion, String instructionName) {
|
||||
ItemStack stack = new ItemStack(MinionItems.REFERENCE_ITEM);
|
||||
stack.set(Reference.COMPONENT_TYPE, new InstructionReference(minion.getUuid(), instructionName, minion.getGameProfile().getName()));
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package io.github.skippyall.minions.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ListenerManager<T> {
|
||||
protected final List<T> listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
public void forEachListener(Consumer<T> listenerConsumer) {
|
||||
for(T listener : listeners) {
|
||||
listenerConsumer.accept(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(T listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(T listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package io.github.skippyall.minions.util;
|
||||
|
||||
import eu.pb4.polymer.networking.api.PolymerNetworking;
|
||||
import eu.pb4.polymer.networking.api.server.PolymerServerNetworking;
|
||||
import io.github.skippyall.minions.Minions;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.util.Identifier;
|
||||
import xyz.nucleoid.packettweaker.PacketContext;
|
||||
|
||||
public class PolymerUtil {
|
||||
public static final int NETWORK_VERSION = 1;
|
||||
|
||||
public static boolean isOnClient(PacketContext context) {
|
||||
if(context.getPlayer() != null) {
|
||||
return isOnClient(context.getPlayer().networkHandler);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isOnClient(ServerPlayNetworkHandler player) {
|
||||
return PolymerServerNetworking.getSupportedVersion(player, VersionSyncPayload.PACKET_ID.id()) == NETWORK_VERSION;
|
||||
}
|
||||
|
||||
public static class VersionSyncPayload implements CustomPayload {
|
||||
|
||||
public static final CustomPayload.Id<VersionSyncPayload> PACKET_ID = new CustomPayload.Id<>(Identifier.of(Minions.MOD_ID, "version_sync"));
|
||||
|
||||
@Override
|
||||
public Id<? extends CustomPayload> getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
PolymerNetworking.registerS2CVersioned(VersionSyncPayload.PACKET_ID, NETWORK_VERSION, PacketCodec.unit(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package io.github.skippyall.minions.util;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.storage.ReadView;
|
||||
import net.minecraft.storage.WriteView;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class SerializableListenerManager<T extends SerializableListenerManager.SerializableListener> extends ListenerManager<T> {
|
||||
private final Registry<Codec<? extends T>> registry;
|
||||
|
||||
public SerializableListenerManager(Registry<Codec<? extends T>> registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
public void save(WriteView view) {
|
||||
WriteView.ListView listView = view.getList("listeners");
|
||||
for (T listener : listeners) {
|
||||
if(listener.getCodecId().isPresent()) {
|
||||
WriteView listenerView = listView.add();
|
||||
Codec<? extends T> codec = registry.get(listener.getCodecId().get());
|
||||
listenerView.put("id", Identifier.CODEC, listener.getCodecId().get());
|
||||
//noinspection unchecked
|
||||
listenerView.put("data", (Codec<T>) codec, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void load(ReadView view) {
|
||||
ReadView.ListReadView listView = view.getListReadView("listeners");
|
||||
for (ReadView listenerView : listView) {
|
||||
Optional<Identifier> id = listenerView.read("id", Identifier.CODEC);
|
||||
if(id.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Codec<? extends T> codec = registry.get(id.get());
|
||||
|
||||
Optional<? extends T> listener = listenerView.read("data", codec);
|
||||
|
||||
if(listener.isPresent()) {
|
||||
listeners.add(listener.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface SerializableListener {
|
||||
default Optional<Identifier> getCodecId() {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"variants": {
|
||||
"powered=false": {
|
||||
"model": "minions:block/minion_trigger_inactive"
|
||||
},
|
||||
"powered=true": {
|
||||
"model": "minions:block/minion_trigger_active"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"model": {
|
||||
"type": "minecraft:model",
|
||||
"model": "minions:block/minion_trigger_active"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"model": {
|
||||
"type": "minecraft:model",
|
||||
"model": "minions:block/minion_trigger_no_plate_active"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"model": {
|
||||
"type": "minecraft:model",
|
||||
"model": "minions:block/minion_trigger_no_plate_inactive"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
{
|
||||
"parent": "block/block",
|
||||
"format_version": "1.21.6",
|
||||
"credit": "Made with Blockbench",
|
||||
"ambientocclusion": false,
|
||||
"textures": {
|
||||
"2": "minions:block/wave",
|
||||
"smooth_stone": "block/smooth_stone",
|
||||
"particle": "#torch"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 0],
|
||||
"to": [16, 2, 16],
|
||||
"faces": {
|
||||
"north": {"texture": "#smooth_stone"},
|
||||
"east": {"texture": "#smooth_stone"},
|
||||
"south": {"texture": "#smooth_stone"},
|
||||
"west": {"texture": "#smooth_stone"},
|
||||
"up": {"texture": "#smooth_stone"},
|
||||
"down": {"texture": "#smooth_stone"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 10, 11],
|
||||
"to": [11, 11, 12],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 10, 1]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 10, 4],
|
||||
"to": [11, 11, 5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 21, 4]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 10, 5],
|
||||
"to": [5, 11, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [5, 21, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [11, 10, 5],
|
||||
"to": [12, 11, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [12, 21, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 10, 14],
|
||||
"to": [11, 11, 15],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 10, 4]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 10, 1],
|
||||
"to": [11, 11, 2],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 21, 1]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 10, 5],
|
||||
"to": [2, 11, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [2, 21, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [14, 10, 5],
|
||||
"to": [15, 11, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [15, 21, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 2, 7],
|
||||
"to": [9, 12, 9],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [7, 6, 9, 16], "texture": "#torch"},
|
||||
"east": {"uv": [7, 6, 9, 16], "texture": "#torch"},
|
||||
"south": {"uv": [7, 6, 9, 16], "texture": "#torch"},
|
||||
"west": {"uv": [7, 6, 9, 16], "texture": "#torch"},
|
||||
"up": {"uv": [7, 6, 9, 8], "texture": "#torch"},
|
||||
"down": {"uv": [7, 13, 9, 15], "texture": "#torch", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 9.5, 6.5],
|
||||
"to": [9.5, 9.5, 9.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"up": {"uv": [8, 5, 9, 6], "texture": "#torch"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 12.5, 6.5],
|
||||
"to": [9.5, 12.5, 9.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"down": {"uv": [7, 5, 8, 6], "texture": "#torch"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 9.5, 6.5],
|
||||
"to": [9.5, 12.5, 6.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"south": {"uv": [9, 6, 10, 7], "texture": "#torch"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [9.5, 9.5, 6.5],
|
||||
"to": [9.5, 12.5, 9.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"west": {"uv": [6, 7, 7, 8], "texture": "#torch"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 9.5, 9.5],
|
||||
"to": [9.5, 12.5, 9.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 6, 7, 7], "texture": "#torch"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 9.5, 6.5],
|
||||
"to": [6.5, 12.5, 9.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"east": {"uv": [9, 7, 10, 8], "texture": "#torch"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
0,
|
||||
{
|
||||
"name": "ring",
|
||||
"origin": [12, 21, 0],
|
||||
"color": 0,
|
||||
"children": [1, 2, 3, 4]
|
||||
},
|
||||
{
|
||||
"name": "ring",
|
||||
"origin": [12, 21, 0],
|
||||
"color": 0,
|
||||
"children": [5, 6, 7, 8]
|
||||
},
|
||||
{
|
||||
"name": "template_redstone_torch",
|
||||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": [9, 10, 11, 12, 13, 14, 15]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minions:block/minion_trigger",
|
||||
"textures": {
|
||||
"torch": "block/redstone_torch"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minions:block/minion_trigger",
|
||||
"textures": {
|
||||
"torch": "block/redstone_torch_off"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
{
|
||||
"parent": "block/block",
|
||||
"format_version": "1.21.6",
|
||||
"credit": "Made with Blockbench",
|
||||
"ambientocclusion": false,
|
||||
"textures": {
|
||||
"2": "minions:block/wave",
|
||||
"particle": "#torch"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [5, 10, 11],
|
||||
"to": [11, 11, 12],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 10, 1]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 10, 4],
|
||||
"to": [11, 11, 5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 21, 4]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [4, 10, 5],
|
||||
"to": [5, 11, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [5, 21, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [11, 10, 5],
|
||||
"to": [12, 11, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [12, 21, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 10, 14],
|
||||
"to": [11, 11, 15],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 10, 4]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [5, 10, 1],
|
||||
"to": [11, 11, 2],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 21, 1]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 10, 5],
|
||||
"to": [2, 11, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [2, 21, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [14, 10, 5],
|
||||
"to": [15, 11, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [15, 21, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 2, 2], "rotation": 90, "texture": "#2"},
|
||||
"east": {"uv": [0, 0, 2, 2], "rotation": 180, "texture": "#2"},
|
||||
"south": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
|
||||
"up": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"},
|
||||
"down": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 2, 7],
|
||||
"to": [9, 12, 9],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [7, 6, 9, 16], "texture": "#torch"},
|
||||
"east": {"uv": [7, 6, 9, 16], "texture": "#torch"},
|
||||
"south": {"uv": [7, 6, 9, 16], "texture": "#torch"},
|
||||
"west": {"uv": [7, 6, 9, 16], "texture": "#torch"},
|
||||
"up": {"uv": [7, 6, 9, 8], "texture": "#torch"},
|
||||
"down": {"uv": [7, 13, 9, 15], "texture": "#torch", "cullface": "down"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 9.5, 6.5],
|
||||
"to": [9.5, 9.5, 9.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"up": {"uv": [8, 5, 9, 6], "texture": "#torch"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 12.5, 6.5],
|
||||
"to": [9.5, 12.5, 9.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"down": {"uv": [7, 5, 8, 6], "texture": "#torch"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 9.5, 6.5],
|
||||
"to": [9.5, 12.5, 6.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"south": {"uv": [9, 6, 10, 7], "texture": "#torch"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [9.5, 9.5, 6.5],
|
||||
"to": [9.5, 12.5, 9.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"west": {"uv": [6, 7, 7, 8], "texture": "#torch"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 9.5, 9.5],
|
||||
"to": [9.5, 12.5, 9.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 6, 7, 7], "texture": "#torch"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6.5, 9.5, 6.5],
|
||||
"to": [6.5, 12.5, 9.5],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
|
||||
"faces": {
|
||||
"east": {"uv": [9, 7, 10, 8], "texture": "#torch"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
0,
|
||||
{
|
||||
"name": "ring",
|
||||
"origin": [12, 21, 0],
|
||||
"color": 0,
|
||||
"children": [1, 2, 3, 4]
|
||||
},
|
||||
{
|
||||
"name": "ring",
|
||||
"origin": [12, 21, 0],
|
||||
"color": 0,
|
||||
"children": [5, 6, 7, 8]
|
||||
},
|
||||
{
|
||||
"name": "template_redstone_torch",
|
||||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": [9, 10, 11, 12, 13, 14, 15]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minions:block/minion_trigger_no_plate",
|
||||
"textures": {
|
||||
"torch": "block/redstone_torch"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minions:block/minion_trigger_no_plate",
|
||||
"textures": {
|
||||
"torch": "block/redstone_torch_off"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 89 B |
@@ -3,10 +3,8 @@
|
||||
"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.inventory.title": "Inventory",
|
||||
"minions.gui.modules.title": "Modules",
|
||||
"minions.gui.ok": "OK",
|
||||
"minions.gui.confirm": "Confirm",
|
||||
"minions.gui.abort": "Abort",
|
||||
@@ -19,8 +17,11 @@
|
||||
"minions.gui.look.skin.base64.title": "Enter a skin in base64 encoding",
|
||||
"minions.gui.look.rename.title": "Enter a name",
|
||||
|
||||
"minions.gui.instruction.title": "Instructions",
|
||||
"minions.gui.instruction.list": "Instruction List",
|
||||
"minions.gui.instruction.create": "New Instruction",
|
||||
"minions.gui.instruction.no_modules": "This minion has no modules",
|
||||
"minions.gui.instruction.select_instruction": "Select 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",
|
||||
@@ -35,6 +36,7 @@
|
||||
"minions.gui.instruction.stop": "Stop",
|
||||
"minions.gui.instruction.argument.configure.type": "Type: %s",
|
||||
"minions.gui.instruction.argument.configure.type.unset": "Unset",
|
||||
"minions.gui.instruction.parameter": "%s: %s",
|
||||
|
||||
"minions.command.input.int.fail": "Not an integer",
|
||||
"minions.command.input.float.fail": "Not a number",
|
||||
@@ -51,6 +53,24 @@
|
||||
|
||||
"minions.command.minion.not_present": "This minion does not exist",
|
||||
|
||||
"minions.reference.instruction.tooltip": "Linked to instruction %s in %s",
|
||||
|
||||
"instruction_type.minions.walk": "Walk",
|
||||
"instruction_type.minions.walk.description": "Walk forward a specified amount of blocks",
|
||||
"instruction_type.minions.turn": "Turn",
|
||||
"instruction_type.minions.turn.description": "Turn the head by specific angle",
|
||||
"instruction_type.minions.attack": "Attack",
|
||||
"instruction_type.minions.attack.description": "Attack and mine blocks\n Test",
|
||||
"instruction_type.minions.use": "Use",
|
||||
"instruction_type.minions.use.description": "Use and place blocks",
|
||||
|
||||
"value_type.minions.integer": "Integer",
|
||||
"value_type.minions.float": "Decimal",
|
||||
"value_type.minions.string": "Text",
|
||||
"value_type.minions.turn_direction": "Turn Direction",
|
||||
|
||||
"value_supplier_type.minions.fixed": "Value",
|
||||
|
||||
"item.minions.attack_module": "Attack Module",
|
||||
"item.minions.interact_module": "Interact Module",
|
||||
"item.minions.mob_spawning_module": "Mob Spawning Module",
|
||||
@@ -59,6 +79,7 @@
|
||||
"item.minions.minion": "Minion",
|
||||
"item.minions.basic_upgrade_base": "Basic Upgrade Base",
|
||||
"item.minions.advanced_upgrade_base": "Advanced Upgrade Base",
|
||||
"item.minions.reference": "Reference",
|
||||
|
||||
"minions.minion_item.tooltip": "Name: %s",
|
||||
"minions.generic.name.invalid_char": "Name contains invalid character",
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minions:minion_trigger"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "minions:item",
|
||||
"data": "minecraft:iron_pickaxe"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "minions:item",
|
||||
"data": "minecraft:structure_void"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "minions:item",
|
||||
"data": "minecraft:lever"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "minions:item",
|
||||
"data": "minecraft:iron_boots"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "minions:item",
|
||||
"data": "minecraft:redstone_block"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "minions:item",
|
||||
"data": "minecraft:bamboo_raft"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "minions:item",
|
||||
"data": "minecraft:netherite_scrap"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "minions:item",
|
||||
"data": "minecraft:string"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "minions:item",
|
||||
"data": "minecraft:structure_void"
|
||||
}
|
||||
@@ -12,6 +12,9 @@
|
||||
"icon": "assets/minions/icon.png",
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
"client": [
|
||||
"io.github.skippyall.minions.client.MinionsClient"
|
||||
],
|
||||
"main": [
|
||||
"io.github.skippyall.minions.Minions"
|
||||
]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
accessWidener v2 named
|
||||
|
||||
accessible class net/minecraft/server/world/ChunkLevelManager$DistanceFromNearestPlayerTracker
|
||||
accessible method net/minecraft/server/world/ChunkLevelManager$DistanceFromNearestPlayerTracker <init> (Lnet/minecraft/server/world/ChunkLevelManager;I)V
|
||||
accessible method net/minecraft/server/world/ChunkLevelManager$DistanceFromNearestPlayerTracker <init> (Lnet/minecraft/server/world/ChunkLevelManager;I)V
|
||||
accessible class net/minecraft/screen/slot/ArmorSlot
|
||||
@@ -9,7 +9,7 @@
|
||||
"EntityAccessor",
|
||||
"EntityMixin",
|
||||
"EntityViewMixin",
|
||||
"GraveCompatMixin",
|
||||
"compat.universal_graves.GraveMixin",
|
||||
"MinecraftServerMixin",
|
||||
"MobEntityMixin",
|
||||
"PlayerListEntryS2CPacket$EntryMixin",
|
||||
@@ -28,5 +28,6 @@
|
||||
"server": [],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
},
|
||||
"plugin": "io.github.skippyall.minions.MinionMixinConfigPlugin"
|
||||
}
|
||||
Reference in New Issue
Block a user