Listen up!
This commit is contained in:
+18
-8
@@ -6,16 +6,24 @@ plugins {
|
|||||||
version = project.mod_version
|
version = project.mod_version
|
||||||
group = project.maven_group
|
group = project.maven_group
|
||||||
|
|
||||||
loom {
|
|
||||||
accessWidenerPath = file("src/main/resources/minions.accesswidener")
|
|
||||||
}
|
|
||||||
|
|
||||||
base {
|
base {
|
||||||
archivesName = project.archives_base_name
|
archivesName = project.archives_base_name
|
||||||
}
|
}
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
accessWidenerPath = file("src/main/resources/minions.accesswidener")
|
accessWidenerPath = file("src/main/resources/minions.accesswidener")
|
||||||
|
splitEnvironmentSourceSets()
|
||||||
|
|
||||||
|
mods {
|
||||||
|
minions {
|
||||||
|
sourceSet sourceSets.main
|
||||||
|
sourceSet sourceSets.client
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runs.forEach {
|
||||||
|
it.vmArg("-XX:+AllowEnhancedClassRedefinition")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@@ -40,8 +48,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.jetbrains:annotations:15.0'
|
|
||||||
|
|
||||||
// To change the versions see the gradle.properties file
|
// To change the versions see the gradle.properties file
|
||||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
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.
|
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||||
|
|
||||||
modImplementation "eu.pb4:polymer-core:${project.polymer_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("eu.pb4:sgui:${project.sgui_version}")
|
||||||
modImplementation include("xyz.nucleoid:server-translations-api:${project.server_translations_version}")
|
modImplementation include("xyz.nucleoid:server-translations-api:${project.server_translations_version}")
|
||||||
|
|
||||||
@@ -94,14 +104,14 @@ java {
|
|||||||
|
|
||||||
jar {
|
jar {
|
||||||
from("LICENSE") {
|
from("LICENSE") {
|
||||||
rename { "${it}_${project.archivesBaseName}"}
|
rename { "${it}_${project.archives_base_name}"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// configure the maven publication
|
// configure the maven publication
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
minions (MavenPublication) {
|
maven (MavenPublication) {
|
||||||
from components.java
|
from components.java
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G
|
|||||||
yarn_mappings=1.21.7+build.2
|
yarn_mappings=1.21.7+build.2
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version = 0.2.1-SNAPSHOT
|
mod_version = 1.0.0-SNAPSHOT-1
|
||||||
maven_group = io.github.skippyall
|
maven_group = io.github.skippyall
|
||||||
archives_base_name = Minions
|
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.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||||
import net.minecraft.block.AbstractBlock;
|
import net.minecraft.block.AbstractBlock;
|
||||||
import net.minecraft.block.entity.BlockEntityType;
|
import net.minecraft.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.block.piston.PistonBehavior;
|
||||||
import net.minecraft.registry.Registries;
|
import net.minecraft.registry.Registries;
|
||||||
import net.minecraft.registry.Registry;
|
import net.minecraft.registry.Registry;
|
||||||
import net.minecraft.registry.RegistryKey;
|
import net.minecraft.registry.RegistryKey;
|
||||||
@@ -13,17 +14,17 @@ import net.minecraft.registry.RegistryKeys;
|
|||||||
import net.minecraft.sound.BlockSoundGroup;
|
import net.minecraft.sound.BlockSoundGroup;
|
||||||
import net.minecraft.util.Identifier;
|
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 Identifier MINION_TRIGGER_ID = Identifier.of(Minions.MOD_ID, "minion_trigger");
|
||||||
public static final MinionTriggerBlock MINION_TRIGGER_BLOCK = Registry.register(
|
public static final MinionTriggerBlock MINION_TRIGGER_BLOCK = Registry.register(
|
||||||
Registries.BLOCK,
|
Registries.BLOCK,
|
||||||
MINION_TRIGGER_ID,
|
MINION_TRIGGER_ID,
|
||||||
new MinionTriggerBlock(AbstractBlock.Settings.create()
|
new MinionTriggerBlock(AbstractBlock.Settings.create()
|
||||||
.registryKey(RegistryKey.of(RegistryKeys.BLOCK, MINION_TRIGGER_ID))
|
.registryKey(RegistryKey.of(RegistryKeys.BLOCK, MINION_TRIGGER_ID))
|
||||||
.hardness(5)
|
.nonOpaque()
|
||||||
.strength(5.0F, 6.0F)
|
.breakInstantly()
|
||||||
.sounds(BlockSoundGroup.IRON)
|
.sounds(BlockSoundGroup.STONE)
|
||||||
.requiresTool()
|
.pistonBehavior(PistonBehavior.DESTROY)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
public static final BlockEntityType<MinionTriggerBlockEntity> MINION_TRIGGER_BE_TYPE =
|
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.PolymerBlockItem;
|
||||||
import eu.pb4.polymer.core.api.item.SimplePolymerItem;
|
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.MinionItem;
|
||||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||||
import io.github.skippyall.minions.module.MinionModule;
|
import io.github.skippyall.minions.module.MinionModule;
|
||||||
import io.github.skippyall.minions.program.instruction.InstructionType;
|
import io.github.skippyall.minions.program.instruction.InstructionType;
|
||||||
import io.github.skippyall.minions.program.instruction.Instructions;
|
import io.github.skippyall.minions.program.instruction.Instructions;
|
||||||
|
import io.github.skippyall.minions.reference.ReferenceItem;
|
||||||
import net.minecraft.component.DataComponentTypes;
|
import net.minecraft.component.DataComponentTypes;
|
||||||
import net.minecraft.component.type.DamageResistantComponent;
|
import net.minecraft.component.type.DamageResistantComponent;
|
||||||
import net.minecraft.entity.damage.DamageType;
|
import net.minecraft.entity.damage.DamageType;
|
||||||
@@ -45,13 +47,13 @@ public class MinionItems {
|
|||||||
public static final SimplePolymerItem MOVE_MODULE = registerModule(
|
public static final SimplePolymerItem MOVE_MODULE = registerModule(
|
||||||
Identifier.of(MOD_ID, "move_module"),
|
Identifier.of(MOD_ID, "move_module"),
|
||||||
Items.IRON_BOOTS,
|
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(
|
public static final SimplePolymerItem ATTACK_MODULE = registerModule(
|
||||||
Identifier.of(MOD_ID, "attack_module"),
|
Identifier.of(MOD_ID, "attack_module"),
|
||||||
Items.IRON_PICKAXE,
|
Items.IRON_PICKAXE,
|
||||||
List.of(Instructions.ATTACK)
|
List.of(Instructions.ATTACK, Instructions.MINE_BLOCK)
|
||||||
);
|
);
|
||||||
|
|
||||||
public static final SimplePolymerItem INTERACT_MODULE = registerModule(
|
public static final SimplePolymerItem INTERACT_MODULE = registerModule(
|
||||||
@@ -69,10 +71,12 @@ public class MinionItems {
|
|||||||
|
|
||||||
public static final PolymerBlockItem MINION_TRIGGER_ITEM =
|
public static final PolymerBlockItem MINION_TRIGGER_ITEM =
|
||||||
registerItem(
|
registerItem(
|
||||||
MinionRegistration.MINION_TRIGGER_ID,
|
MinionBlocks.MINION_TRIGGER_ID,
|
||||||
settings -> new PolymerBlockItem(MinionRegistration.MINION_TRIGGER_BLOCK, settings, Items.GOLD_BLOCK)
|
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) {
|
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)));
|
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;
|
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.MinionRuntime;
|
||||||
import io.github.skippyall.minions.minion.skin.SkinProvider;
|
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.supplier.ValueSupplierType;
|
||||||
import io.github.skippyall.minions.program.instruction.InstructionType;
|
import io.github.skippyall.minions.program.instruction.InstructionType;
|
||||||
import io.github.skippyall.minions.program.consumer.ValueConsumerType;
|
import io.github.skippyall.minions.program.consumer.ValueConsumerType;
|
||||||
import io.github.skippyall.minions.program.value.ValueType;
|
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.Registry;
|
||||||
import net.minecraft.registry.RegistryKey;
|
import net.minecraft.registry.RegistryKey;
|
||||||
import net.minecraft.registry.SimpleRegistry;
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
public class MinionRegistries {
|
public class MinionRegistries {
|
||||||
public static final Registry<ValueType<?>> VALUE_TYPES = registry("value_type");
|
public static final Registry<ValueType<?>> VALUE_TYPES = registry("value_type");
|
||||||
public static final Registry<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<ValueConsumerType<MinionRuntime>> VALUE_CONSUMER_TYPES = registry("value_consumer_type");
|
||||||
public static final Registry<InstructionType<MinionRuntime>> INSTRUCTION_TYPES = registry("instruction_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) {
|
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;
|
package io.github.skippyall.minions;
|
||||||
|
|
||||||
|
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
|
||||||
import io.github.skippyall.minions.command.MinionsCommand;
|
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.fakeplayer.MinionFakePlayer;
|
||||||
import io.github.skippyall.minions.minion.MinionData;
|
import io.github.skippyall.minions.minion.MinionData;
|
||||||
import io.github.skippyall.minions.minion.MinionPersistentState;
|
import io.github.skippyall.minions.minion.MinionPersistentState;
|
||||||
import io.github.skippyall.minions.minion.skin.SkinProviders;
|
import io.github.skippyall.minions.minion.skin.SkinProviders;
|
||||||
import io.github.skippyall.minions.module.MinionModule;
|
import io.github.skippyall.minions.module.MinionModule;
|
||||||
import io.github.skippyall.minions.program.instruction.Instructions;
|
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.program.value.ValueTypes;
|
||||||
|
import io.github.skippyall.minions.util.PolymerUtil;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
@@ -21,11 +25,23 @@ public class Minions implements ModInitializer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
|
MinionRegistries.register();
|
||||||
|
|
||||||
Instructions.register();
|
Instructions.register();
|
||||||
|
ValueSuppliers.register();
|
||||||
|
ValueTypes.register();
|
||||||
|
SkinProviders.register();
|
||||||
|
GuiDisplay.register();
|
||||||
|
|
||||||
MinionData.register();
|
MinionData.register();
|
||||||
MinionModule.register();
|
MinionModule.register();
|
||||||
|
|
||||||
|
MinionBlocks.register();
|
||||||
|
MinionItems.register();
|
||||||
|
MinionCreativeTab.registerGroup();
|
||||||
|
|
||||||
|
PolymerUtil.register();
|
||||||
|
|
||||||
ServerLifecycleEvents.SERVER_STARTED.register(server -> {
|
ServerLifecycleEvents.SERVER_STARTED.register(server -> {
|
||||||
MinionPersistentState.create(server);
|
MinionPersistentState.create(server);
|
||||||
MinionPersistentState.INSTANCE.getMinionData().forEach((uuid, data) -> {
|
MinionPersistentState.INSTANCE.getMinionData().forEach((uuid, data) -> {
|
||||||
@@ -39,11 +55,6 @@ public class Minions implements ModInitializer {
|
|||||||
MinionsCommand.register(commandDispatcher);
|
MinionsCommand.register(commandDispatcher);
|
||||||
});
|
});
|
||||||
|
|
||||||
ValueTypes.register();
|
PolymerResourcePackUtils.addModAssets(Minions.MOD_ID);
|
||||||
SkinProviders.register();
|
|
||||||
|
|
||||||
MinionRegistration.register();
|
|
||||||
MinionItems.register();
|
|
||||||
MinionCreativeTab.registerGroup();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 com.mojang.serialization.MapCodec;
|
||||||
import eu.pb4.polymer.core.api.block.PolymerBlock;
|
import eu.pb4.polymer.core.api.block.PolymerBlock;
|
||||||
import io.github.skippyall.minions.MinionRegistration;
|
import eu.pb4.polymer.core.api.utils.PolymerClientDecoded;
|
||||||
import io.github.skippyall.minions.PlayerClipboardAttachment;
|
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.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.BlockWithEntity;
|
import net.minecraft.block.BlockWithEntity;
|
||||||
import net.minecraft.block.Blocks;
|
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.BlockEntity;
|
||||||
import net.minecraft.block.entity.BlockEntityTicker;
|
import net.minecraft.block.entity.BlockEntityTicker;
|
||||||
import net.minecraft.block.entity.BlockEntityType;
|
import net.minecraft.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.component.DataComponentTypes;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
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.SoundCategory;
|
||||||
import net.minecraft.sound.SoundEvents;
|
import net.minecraft.sound.SoundEvents;
|
||||||
import net.minecraft.state.StateManager;
|
import net.minecraft.state.StateManager;
|
||||||
import net.minecraft.state.property.BooleanProperty;
|
import net.minecraft.state.property.BooleanProperty;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.ActionResult;
|
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.hit.BlockHitResult;
|
||||||
import net.minecraft.util.math.BlockPos;
|
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.World;
|
||||||
|
import net.minecraft.world.WorldView;
|
||||||
import net.minecraft.world.block.WireOrientation;
|
import net.minecraft.world.block.WireOrientation;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import xyz.nucleoid.packettweaker.PacketContext;
|
import xyz.nucleoid.packettweaker.PacketContext;
|
||||||
|
|
||||||
import java.util.Optional;
|
public class MinionTriggerBlock extends BlockWithEntity implements PolymerBlock, PolymerKeepModel, PolymerClientDecoded, BlockWithElementHolder {
|
||||||
|
|
||||||
public class MinionTriggerBlock extends BlockWithEntity implements PolymerBlock {
|
|
||||||
public static final MapCodec<MinionTriggerBlock> CODEC = createCodec(MinionTriggerBlock::new);
|
public static final MapCodec<MinionTriggerBlock> CODEC = createCodec(MinionTriggerBlock::new);
|
||||||
|
|
||||||
public static final BooleanProperty POWERED = BooleanProperty.of("powered");
|
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) {
|
public MinionTriggerBlock(Settings settings) {
|
||||||
super(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
|
@Override
|
||||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
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
|
@Override
|
||||||
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
|
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
|
||||||
PlayerClipboardAttachment clipboard = player.getAttached(PlayerClipboardAttachment.TYPE);
|
world.getBlockEntity(pos, MinionBlocks.MINION_TRIGGER_BE_TYPE).ifPresent(be -> {
|
||||||
if(clipboard != null) {
|
String name = MinionPersistentState.INSTANCE.getMinionData(be.getMinionUuid()).name();
|
||||||
Optional<MinionTriggerBlockEntity> be = world.getBlockEntity(pos, MinionRegistration.MINION_TRIGGER_BE_TYPE);
|
player.sendMessage(Text.translatable("minions.reference.instruction.tooltip", name, be.getInstructionName()), true);
|
||||||
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.SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return ActionResult.PASS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void neighborUpdate(BlockState state, World world, BlockPos pos, Block sourceBlock, @Nullable WireOrientation wireOrientation, boolean notify) {
|
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);
|
boolean newPower = world.isReceivingRedstonePower(pos);
|
||||||
if(state.get(POWERED) != newPower) {
|
if(state.get(POWERED) != newPower) {
|
||||||
world.setBlockState(pos, state.with(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
|
@Override
|
||||||
protected int getComparatorOutput(BlockState state, World world, BlockPos pos) {
|
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
|
@Override
|
||||||
@@ -88,15 +139,34 @@ public class MinionTriggerBlock extends BlockWithEntity implements PolymerBlock
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getPolymerBlockState(BlockState state, PacketContext context) {
|
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
|
@Override
|
||||||
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
|
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;
|
return MinionTriggerBlockEntity::tick;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
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;
|
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.MinionRuntime;
|
||||||
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
||||||
import io.github.skippyall.minions.program.instruction.ConfiguredInstruction;
|
import io.github.skippyall.minions.program.instruction.ConfiguredInstruction;
|
||||||
@@ -23,7 +23,7 @@ public class MinionTriggerBlockEntity extends BlockEntity {
|
|||||||
private boolean runningCache = false;
|
private boolean runningCache = false;
|
||||||
|
|
||||||
public MinionTriggerBlockEntity(BlockPos pos, BlockState state) {
|
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) {
|
public void setInstruction(UUID minionUuid, String instructionName) {
|
||||||
@@ -38,12 +38,12 @@ public class MinionTriggerBlockEntity extends BlockEntity {
|
|||||||
}
|
}
|
||||||
if(triggerBlockEntity.first) {
|
if(triggerBlockEntity.first) {
|
||||||
triggerBlockEntity.first = false;
|
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);
|
triggerBlockEntity.runningCache = triggerBlockEntity.getInstruction().map(ConfiguredInstruction::isRunning).orElse(false);
|
||||||
} else {
|
} else {
|
||||||
boolean isRunning = triggerBlockEntity.getInstruction().map(ConfiguredInstruction::isRunning).orElse(false);
|
boolean isRunning = triggerBlockEntity.getInstruction().map(ConfiguredInstruction::isRunning).orElse(false);
|
||||||
if (isRunning != triggerBlockEntity.runningCache) {
|
if (isRunning != triggerBlockEntity.runningCache) {
|
||||||
world.updateComparators(pos, MinionRegistration.MINION_TRIGGER_BLOCK);
|
world.updateComparators(pos, MinionBlocks.MINION_TRIGGER_BLOCK);
|
||||||
triggerBlockEntity.runningCache = isRunning;
|
triggerBlockEntity.runningCache = isRunning;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,6 +78,14 @@ public class MinionTriggerBlockEntity extends BlockEntity {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UUID getMinionUuid() {
|
||||||
|
return minionUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstructionName() {
|
||||||
|
return instructionName;
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<ConfiguredInstruction<MinionRuntime>> getInstruction(MinionFakePlayer minion) {
|
public Optional<ConfiguredInstruction<MinionRuntime>> getInstruction(MinionFakePlayer minion) {
|
||||||
return Optional.ofNullable(minion.getInstructionManager().getInstruction(instructionName));
|
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;
|
package io.github.skippyall.minions.gui;
|
||||||
|
|
||||||
import com.mojang.authlib.properties.PropertyMap;
|
import com.mojang.authlib.properties.PropertyMap;
|
||||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
|
import com.mojang.serialization.Codec;
|
||||||
import io.github.skippyall.minions.util.ModelIdUtil;
|
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.DataComponentTypes;
|
||||||
import net.minecraft.component.type.LoreComponent;
|
|
||||||
import net.minecraft.component.type.ProfileComponent;
|
import net.minecraft.component.type.ProfileComponent;
|
||||||
|
import net.minecraft.component.type.TooltipDisplayComponent;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
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.text.Text;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.Rarity;
|
||||||
|
import net.minecraft.util.Uuids;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface GuiDisplay {
|
public interface GuiDisplay {
|
||||||
default GuiElementBuilder createElement() {
|
Codec<GuiDisplay> CODEC = MinionRegistries.GUI_DISPLAY_TYPE.getCodec().dispatch(GuiDisplay::getCodec, codec -> codec.fieldOf("data"));
|
||||||
return new GuiElementBuilder(createItemStack());
|
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();
|
ItemStack createItemStack();
|
||||||
|
|
||||||
record ModelBased(Identifier model, String translationKeyBase, boolean withLore) implements GuiDisplay {
|
Codec<? extends GuiDisplay> getCodec();
|
||||||
public ModelBased(Item model, String translationKeyBase, boolean withLore) {
|
|
||||||
this(ModelIdUtil.getItemModelId(model), translationKeyBase, withLore);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModelBased(Item model, String translationKeyBase) {
|
class ModelBased implements GuiDisplay {
|
||||||
this(ModelIdUtil.getItemModelId(model), translationKeyBase, false);
|
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
|
@Override
|
||||||
public ItemStack createItemStack() {
|
public ItemStack createItemStack() {
|
||||||
ItemStack stack = new ItemStack(Items.BARRIER);
|
ItemStack stack = new ItemStack(Items.BARRIER);
|
||||||
stack.set(DataComponentTypes.ITEM_MODEL, model);
|
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;
|
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
|
@Override
|
||||||
public ItemStack createItemStack() {
|
public ItemStack createItemStack() {
|
||||||
ItemStack stack = new ItemStack(Items.PLAYER_HEAD);
|
ItemStack stack = new ItemStack(Items.PLAYER_HEAD);
|
||||||
stack.set(DataComponentTypes.PROFILE, new ProfileComponent(Optional.empty(), Optional.of(uuid), new PropertyMap()));
|
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;
|
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.elements.GuiElementBuilder;
|
||||||
import eu.pb4.sgui.api.gui.SimpleGui;
|
import eu.pb4.sgui.api.gui.SimpleGui;
|
||||||
import io.github.skippyall.minions.MinionRegistries;
|
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.Result;
|
||||||
import io.github.skippyall.minions.gui.input.TextInput;
|
import io.github.skippyall.minions.gui.input.TextInput;
|
||||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
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 io.github.skippyall.minions.util.TranslationUtil;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.registry.DynamicRegistryManager;
|
||||||
import net.minecraft.screen.ScreenHandlerType;
|
import net.minecraft.screen.ScreenHandlerType;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.sound.SoundCategory;
|
|
||||||
import net.minecraft.sound.SoundEvents;
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class InstructionGui {
|
public class InstructionGui {
|
||||||
public static void openInstructionMainMenu(MinionFakePlayer minion, ServerPlayerEntity player) {
|
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()
|
gui.setSlot(3, new GuiElementBuilder()
|
||||||
.setItem(Items.BOOK)
|
.setItem(Items.BOOK)
|
||||||
.setName(Text.translatable("minions.gui.instruction.list"))
|
.setName(Text.translatable("minions.gui.instruction.list"))
|
||||||
@@ -47,23 +45,37 @@ public class InstructionGui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void instructionList(MinionFakePlayer minion, ServerPlayerEntity player) {
|
public static void instructionList(MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||||
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
|
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()) {
|
for (String instructionName : minion.getInstructionManager().getInstructionNames()) {
|
||||||
ConfiguredInstruction<MinionRuntime> instruction = minion.getInstructionManager().getInstruction(instructionName);
|
ConfiguredInstruction<MinionRuntime> instruction = minion.getInstructionManager().getInstruction(instructionName);
|
||||||
gui.addSlot(instruction.getInstruction().getDisplay().createElement()
|
gui.setSlot(i, new GuiElementBuilder(GuiDisplay.getGuiDisplayFor(MinionRegistries.INSTRUCTION_TYPES, instruction.getInstruction(), player.getRegistryManager()).createItemStack())
|
||||||
.setName(Text.literal(instructionName))
|
.setName(Text.literal(instructionName))
|
||||||
.setLore(List.of())
|
.setCallback(() -> ConfigureInstructionGui.configureInstructionMenu(instructionName, instruction, minion, player))
|
||||||
.setCallback(() -> configureInstructionMenu(instructionName, instruction, minion, player))
|
|
||||||
);
|
);
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
gui.open();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void createNewInstruction(MinionFakePlayer minion, ServerPlayerEntity player) {
|
public static void createNewInstruction(MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||||
selectInstructionModuleMenu(minion, player).thenAccept(instructionType ->
|
selectInstructionModuleMenu(minion, player).thenAccept(instructionType ->
|
||||||
inputInstructionName(minion, player, "Instruction").thenAccept(name -> {
|
inputInstructionName(minion, player, "Instruction").thenAccept(name -> {
|
||||||
|
if (!minion.isRemoved() && !minion.isDisconnected()) {
|
||||||
ConfiguredInstruction<MinionRuntime> configuredInstruction = minion.getInstructionManager().createInstruction(name, instructionType);
|
ConfiguredInstruction<MinionRuntime> configuredInstruction = minion.getInstructionManager().createInstruction(name, instructionType);
|
||||||
configureInstructionMenu(name, configuredInstruction, minion, player);
|
ConfigureInstructionGui.configureInstructionMenu(name, configuredInstruction, minion, player);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -78,7 +90,7 @@ public class InstructionGui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean checkInstructionExists(String name, ConfiguredInstruction<?> instruction, MinionFakePlayer minion, ServerPlayerEntity player) {
|
public static boolean checkInstructionExists(String name, ConfiguredInstruction<?> instruction, MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||||
boolean stillExists = minion.getInstructionManager().getInstruction(name) == instruction;
|
boolean stillExists = !minion.isRemoved() && !minion.isDisconnected() && minion.getInstructionManager().getInstruction(name) == instruction;
|
||||||
if (!stillExists) {
|
if (!stillExists) {
|
||||||
player.closeHandledScreen();
|
player.closeHandledScreen();
|
||||||
player.sendMessage(Text.translatable("minions.gui.instruction.removed"));
|
player.sendMessage(Text.translatable("minions.gui.instruction.removed"));
|
||||||
@@ -86,112 +98,41 @@ public class InstructionGui {
|
|||||||
return stillExists;
|
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);
|
public static <T, A extends ValueSupplier<T, MinionRuntime>> void configureArgumentMenu(String instructionName, ConfiguredInstruction<MinionRuntime> instruction, Parameter<T> parameter, MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||||
gui.setTitle(Text.literal(name));
|
if (!checkInstructionExists(instructionName, instruction, minion, player)) {
|
||||||
|
|
||||||
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)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable A argument = instruction.getArguments().getArgument(parameter);
|
@Nullable A argument = instruction.getArguments().getArgument(parameter);
|
||||||
|
|
||||||
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_3X3, player, false);
|
if(argument == null) {
|
||||||
gui.setSlot(3, new GuiElementBuilder(Items.STICK)
|
configureTypeAndValue(instructionName, instruction, parameter, minion, player);
|
||||||
.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"))))
|
return;
|
||||||
.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) {
|
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)
|
gui.setSlot(5, new GuiElementBuilder(Items.STRUCTURE_VOID)
|
||||||
.setName(Text.literal("Configure"))
|
.setName(Text.literal("Configure"))
|
||||||
.setCallback(() -> argument.getType().openConfiguration(player, argument.getValueType(), argument)
|
.setCallback(() -> argument.getType().openConfiguration(player, argument.getValueType(), argument)
|
||||||
.thenAccept(newArgument -> instruction.getArguments().setArgument(parameter, newArgument))
|
.thenAccept(newArgument -> instruction.getArguments().setArgument(parameter, newArgument))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
gui.open();
|
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<>();
|
CompletableFuture<ValueSupplierType<MinionRuntime>> future = new CompletableFuture<>();
|
||||||
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false);
|
SimpleGui gui = new InstructionBoundSimpleGui(ScreenHandlerType.GENERIC_9X3, player, minion, instruction);
|
||||||
for(ValueSupplierType<MinionRuntime> type : MinionRegistries.ARGUMENT_TYPES) {
|
for (ValueSupplierType<MinionRuntime> type : MinionRegistries.VALUE_SUPPLIER_TYPES) {
|
||||||
gui.addSlot(new GuiElementBuilder()
|
gui.addSlot(new GuiElementBuilder(GuiDisplay.getDisplayStackWithName(MinionRegistries.VALUE_SUPPLIER_TYPES, type, player.getRegistryManager()))
|
||||||
.setName(Text.translatable(TranslationUtil.getTranslationKey(type, MinionRegistries.ARGUMENT_TYPES)))
|
|
||||||
.setCallback(() -> future.complete(type))
|
.setCallback(() -> future.complete(type))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -199,15 +140,25 @@ public class InstructionGui {
|
|||||||
return future;
|
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) {
|
public static CompletableFuture<InstructionType<MinionRuntime>> selectInstructionModuleMenu(MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||||
if (minion.getModuleInventory().getModules().isEmpty()) {
|
if (minion.getModuleInventory().getModules().isEmpty()) {
|
||||||
player.sendMessage(Text.literal("This minion has no modules"));
|
player.sendMessage(Text.translatable("minions.gui.instruction.no_modules"));
|
||||||
return CompletableFuture.failedFuture(new NoSuchElementException("No modules"));
|
return CompletableFuture.failedFuture(new NoSuchElementException("No modules"));
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletableFuture<InstructionType<MinionRuntime>> future = new CompletableFuture<>();
|
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
|
@Override
|
||||||
public void onClose() {
|
public void onClose() {
|
||||||
if (!future.isDone()) {
|
if (!future.isDone()) {
|
||||||
@@ -215,12 +166,14 @@ public class InstructionGui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
gui.setTitle(Text.translatable("minions.gui.instruction.select_instruction"));
|
||||||
|
|
||||||
for (int i = 0; i < minion.getModuleInventory().size(); i++) {
|
for (int i = 0; i < minion.getModuleInventory().size(); i++) {
|
||||||
ItemStack module = minion.getModuleInventory().getStack(i);
|
ItemStack moduleItem = minion.getModuleInventory().getStack(i);
|
||||||
if(module.contains(MinionModule.COMPONENT_TYPE)) {
|
MinionModule module = moduleItem.get(MinionModule.COMPONENT_TYPE);
|
||||||
gui.addSlot(new GuiElementBuilder(module)
|
if (module != null && !module.instructions().isEmpty()) {
|
||||||
.setCallback(() -> selectInstructionMenu(module.get(MinionModule.COMPONENT_TYPE), minion, player)
|
gui.addSlot(new GuiElementBuilder(moduleItem)
|
||||||
|
.setCallback(() -> selectInstructionMenu(module, minion, player)
|
||||||
.thenApply(future::complete)
|
.thenApply(future::complete)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -234,9 +187,18 @@ public class InstructionGui {
|
|||||||
public static CompletableFuture<InstructionType<MinionRuntime>> selectInstructionMenu(MinionModule module, MinionFakePlayer minion, ServerPlayerEntity player) {
|
public static CompletableFuture<InstructionType<MinionRuntime>> selectInstructionMenu(MinionModule module, MinionFakePlayer minion, ServerPlayerEntity player) {
|
||||||
CompletableFuture<InstructionType<MinionRuntime>> future = new CompletableFuture<>();
|
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()) {
|
||||||
|
future.cancel(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
gui.setTitle(Text.translatable("minions.gui.instruction.select_instruction"));
|
||||||
|
|
||||||
for (InstructionType<MinionRuntime> instructionType : module.instructions()) {
|
for (InstructionType<MinionRuntime> instructionType : module.instructions()) {
|
||||||
gui.addSlot(createInstructionElement(instructionType)
|
gui.addSlot(createInstructionElement(instructionType, player.getRegistryManager())
|
||||||
.setCallback(() -> future.complete(instructionType))
|
.setCallback(() -> future.complete(instructionType))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -245,10 +207,10 @@ public class InstructionGui {
|
|||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GuiElementBuilder createInstructionElement(InstructionType<?> instructionType) {
|
public static GuiElementBuilder createInstructionElement(InstructionType<MinionRuntime> instructionType, DynamicRegistryManager manager) {
|
||||||
GuiElementBuilder instructionBuilder;
|
GuiElementBuilder instructionBuilder;
|
||||||
if (instructionType != null) {
|
if (instructionType != null) {
|
||||||
instructionBuilder = instructionType.getDisplay().createElement();
|
instructionBuilder = new GuiElementBuilder(GuiDisplay.getDisplayStackWithName(MinionRegistries.INSTRUCTION_TYPES, instructionType, manager));
|
||||||
} else {
|
} else {
|
||||||
instructionBuilder = new GuiElementBuilder(Items.RED_WOOL)
|
instructionBuilder = new GuiElementBuilder(Items.RED_WOOL)
|
||||||
.setName(Text.translatable("minions.gui.instruction.no_instruction_set"));
|
.setName(Text.translatable("minions.gui.instruction.no_instruction_set"));
|
||||||
@@ -256,10 +218,15 @@ public class InstructionGui {
|
|||||||
return instructionBuilder;
|
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;
|
GuiElementBuilder argumentBuilder;
|
||||||
if (valueSupplier != null) {
|
if (valueSupplier != null) {
|
||||||
argumentBuilder = valueSupplier.getDisplay().createElement();
|
argumentBuilder = new GuiElementBuilder(GuiDisplay.getDisplayStack(MinionRegistries.VALUE_SUPPLIER_TYPES, valueSupplier.getType(), manager));
|
||||||
} else {
|
} else {
|
||||||
argumentBuilder = new GuiElementBuilder(Items.RED_WOOL)
|
argumentBuilder = new GuiElementBuilder(Items.RED_WOOL)
|
||||||
.setName(Text.translatable("minions.gui.instruction.no_argument_set"));
|
.setName(Text.translatable("minions.gui.instruction.no_argument_set"));
|
||||||
|
|||||||
@@ -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 eu.pb4.sgui.api.gui.SimpleGui;
|
||||||
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
|
||||||
import io.github.skippyall.minions.module.ModuleInventory;
|
import 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.item.Items;
|
||||||
import net.minecraft.screen.ScreenHandlerType;
|
import net.minecraft.screen.ScreenHandlerType;
|
||||||
|
import net.minecraft.screen.slot.ArmorSlot;
|
||||||
import net.minecraft.screen.slot.Slot;
|
import net.minecraft.screen.slot.Slot;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
@@ -51,10 +55,31 @@ public class MinionGui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void openMinionInventory(ServerPlayerEntity player, MinionFakePlayer minion) {
|
public static void openMinionInventory(ServerPlayerEntity player, MinionFakePlayer minion) {
|
||||||
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X5, player, false);
|
SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X6, player, false);
|
||||||
gui.setTitle(Text.translatable("minions.gui.inventory.title", minion.getName()));
|
gui.setTitle(Text.translatable("minions.gui.inventory.title"));
|
||||||
for (int i = 0; i < minion.getInventory().size(); i++) {
|
|
||||||
gui.setSlotRedirect(i, new Slot(minion.getInventory(), i, 0, 0));
|
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();
|
gui.open();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class ChoiceInput {
|
|||||||
gui.setTitle(title);
|
gui.setTitle(title);
|
||||||
|
|
||||||
for(T value : values) {
|
for(T value : values) {
|
||||||
gui.addSlot(displayFunction.apply(value).createElement()
|
gui.addSlot(new GuiElementBuilder(displayFunction.apply(value).createItemStack())
|
||||||
.setCallback(() -> future.complete(value))
|
.setCallback(() -> future.complete(value))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ public class ChoiceInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Displayable> BiFunction<ServerPlayerEntity, T, CompletableFuture<T>> createDialogOpener(T[] values) {
|
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) {
|
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);
|
return inputSync(player, title, defaultValue, Result.Success::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompletableFuture<Integer> inputInt(ServerPlayerEntity player, Text title, String defaultValue) {
|
public static CompletableFuture<Long> inputLong(ServerPlayerEntity player, Text title, String defaultValue) {
|
||||||
return inputSync(player, title, defaultValue, string -> Result.wrapCustomError(() -> Integer.valueOf(string), Text.translatable("minions.command.input.int.fail")));
|
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) {
|
public static CompletableFuture<Double> inputDouble(ServerPlayerEntity player, Text title, String defaultValue) {
|
||||||
return inputSync(player, title, defaultValue, string -> Result.wrapCustomError(() -> Float.valueOf(string), Text.translatable("minions.command.input.float.fail")));
|
return inputSync(player, title, defaultValue, string -> Result.wrapCustomError(() -> Double.valueOf(string), Text.translatable("minions.command.input.float.fail")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
ConfiguredInstruction<MinionRuntime> instruction = new ConfiguredInstruction<>(instructionType);
|
||||||
configuredInstructions.put(name, instruction);
|
configuredInstructions.put(name, instruction);
|
||||||
|
minion.forEachMinionListener(listener -> listener.onInstructionsUpdate(minion));
|
||||||
return instruction;
|
return instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,6 +54,9 @@ public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
|
|||||||
ConfiguredInstruction<MinionRuntime> instruction = getInstruction(name);
|
ConfiguredInstruction<MinionRuntime> instruction = getInstruction(name);
|
||||||
instruction.stop(this);
|
instruction.stop(this);
|
||||||
configuredInstructions.remove(name);
|
configuredInstructions.remove(name);
|
||||||
|
|
||||||
|
instruction.onInstructionRemove();
|
||||||
|
minion.forEachMinionListener(listener -> listener.onInstructionsUpdate(minion));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfiguredInstruction<MinionRuntime> getInstruction(String name) {
|
public ConfiguredInstruction<MinionRuntime> getInstruction(String name) {
|
||||||
@@ -64,8 +68,16 @@ public class MinionRuntime implements InstructionRuntime<MinionRuntime> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setInstructionName(String oldName, String newName) {
|
public void setInstructionName(String oldName, String newName) {
|
||||||
if(!configuredInstructions.containsKey(newName)) {
|
if(!configuredInstructions.containsKey(newName) && configuredInstructions.containsKey(oldName)) {
|
||||||
configuredInstructions.put(newName, configuredInstructions.remove(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
|
@Override
|
||||||
public Registry<ValueSupplierType<MinionRuntime>> getArgumentTypeRegistry() {
|
public Registry<ValueSupplierType<MinionRuntime>> getArgumentTypeRegistry() {
|
||||||
return MinionRegistries.ARGUMENT_TYPES;
|
return MinionRegistries.VALUE_SUPPLIER_TYPES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+27
-11
@@ -7,7 +7,6 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
|
||||||
import io.github.skippyall.minions.mixins.EntityAccessor;
|
import io.github.skippyall.minions.mixins.EntityAccessor;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.command.argument.EntityAnchorArgumentType;
|
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.BoatEntity;
|
||||||
import net.minecraft.entity.vehicle.MinecartEntity;
|
import net.minecraft.entity.vehicle.MinecartEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
|
||||||
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
|
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.UpdateSelectedSlotS2CPacket;
|
import net.minecraft.network.packet.s2c.play.UpdateSelectedSlotS2CPacket;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
@@ -41,7 +39,7 @@ public class EntityPlayerActionPack
|
|||||||
private final Map<ActionType, Action> actions = new EnumMap<>(ActionType.class);
|
private final Map<ActionType, Action> actions = new EnumMap<>(ActionType.class);
|
||||||
|
|
||||||
private BlockPos currentBlock;
|
private BlockPos currentBlock;
|
||||||
private int blockHitDelay;
|
public int blockHitDelay;
|
||||||
private boolean isHittingBlock;
|
private boolean isHittingBlock;
|
||||||
private float curBlockDamageMP;
|
private float curBlockDamageMP;
|
||||||
|
|
||||||
@@ -73,6 +71,14 @@ public class EntityPlayerActionPack
|
|||||||
itemUseCooldown = other.itemUseCooldown;
|
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)
|
public EntityPlayerActionPack start(ActionType type, Action action)
|
||||||
{
|
{
|
||||||
Action previous = actions.remove(type);
|
Action previous = actions.remove(type);
|
||||||
@@ -255,9 +261,13 @@ public class EntityPlayerActionPack
|
|||||||
if (strafing != 0.0F || player instanceof MinionFakePlayer) {
|
if (strafing != 0.0F || player instanceof MinionFakePlayer) {
|
||||||
player.sidewaysSpeed = strafing * vel;
|
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;
|
double reach = player.interactionManager.isCreative() ? 5 : 4.5f;
|
||||||
return Tracer.rayTrace(player, 1, reach, false);
|
return Tracer.rayTrace(player, 1, reach, false);
|
||||||
@@ -382,7 +392,7 @@ public class EntityPlayerActionPack
|
|||||||
switch (hit.getType()) {
|
switch (hit.getType()) {
|
||||||
case ENTITY: {
|
case ENTITY: {
|
||||||
EntityHitResult entityHit = (EntityHitResult) hit;
|
EntityHitResult entityHit = (EntityHitResult) hit;
|
||||||
if (!action.isContinuous)
|
if (!action.isContinuous || action.first)
|
||||||
{
|
{
|
||||||
player.attack(entityHit.getEntity());
|
player.attack(entityHit.getEntity());
|
||||||
player.swingHand(Hand.MAIN_HAND);
|
player.swingHand(Hand.MAIN_HAND);
|
||||||
@@ -395,7 +405,6 @@ public class EntityPlayerActionPack
|
|||||||
EntityPlayerActionPack ap = player.getMinionActionPack();
|
EntityPlayerActionPack ap = player.getMinionActionPack();
|
||||||
if (ap.blockHitDelay > 0)
|
if (ap.blockHitDelay > 0)
|
||||||
{
|
{
|
||||||
ap.blockHitDelay--;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
BlockHitResult blockHit = (BlockHitResult) hit;
|
BlockHitResult blockHit = (BlockHitResult) hit;
|
||||||
@@ -550,8 +559,9 @@ public class EntityPlayerActionPack
|
|||||||
private int count;
|
private int count;
|
||||||
private int next;
|
private int next;
|
||||||
private final boolean isContinuous;
|
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.limit = limit;
|
||||||
this.interval = interval;
|
this.interval = interval;
|
||||||
@@ -562,22 +572,27 @@ public class EntityPlayerActionPack
|
|||||||
|
|
||||||
public static Action once()
|
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()
|
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)
|
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)
|
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)
|
Boolean tick(EntityPlayerActionPack actionPack, ActionType type)
|
||||||
@@ -608,6 +623,7 @@ public class EntityPlayerActionPack
|
|||||||
return cancel;
|
return cancel;
|
||||||
}
|
}
|
||||||
next = interval;
|
next = interval;
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ package io.github.skippyall.minions.minion.fakeplayer;
|
|||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import com.mojang.authlib.properties.PropertyMap;
|
import com.mojang.authlib.properties.PropertyMap;
|
||||||
import io.github.skippyall.minions.MinionItems;
|
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.minion.MinionData;
|
||||||
import io.github.skippyall.minions.gui.MinionGui;
|
import io.github.skippyall.minions.gui.MinionGui;
|
||||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
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.MinionPersistentState;
|
||||||
import io.github.skippyall.minions.minion.MinionProfileUtils;
|
import io.github.skippyall.minions.minion.MinionProfileUtils;
|
||||||
import io.github.skippyall.minions.module.ModuleInventory;
|
import io.github.skippyall.minions.module.ModuleInventory;
|
||||||
|
import io.github.skippyall.minions.util.SerializableListenerManager;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
@@ -45,12 +48,14 @@ import net.minecraft.world.TeleportTarget;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class MinionFakePlayer extends ServerPlayerEntity {
|
public class MinionFakePlayer extends ServerPlayerEntity {
|
||||||
public Runnable fixStartingPosition = () -> {};
|
public Runnable fixStartingPosition = () -> {};
|
||||||
|
|
||||||
private EntityPlayerActionPack actionPack;
|
private EntityPlayerActionPack actionPack;
|
||||||
|
|
||||||
|
private final SerializableListenerManager<MinionListener> minionListeners = new SerializableListenerManager<>(MinionRegistries.MINION_LISTENER_CODECS);
|
||||||
private final ModuleInventory moduleInventory = new ModuleInventory();
|
private final ModuleInventory moduleInventory = new ModuleInventory();
|
||||||
private final MinionRuntime instructionManager = new MinionRuntime(this);
|
private final MinionRuntime instructionManager = new MinionRuntime(this);
|
||||||
|
|
||||||
@@ -90,9 +95,11 @@ public class MinionFakePlayer extends ServerPlayerEntity {
|
|||||||
instance.interactionManager.changeGameMode(GameMode.SURVIVAL);
|
instance.interactionManager.changeGameMode(GameMode.SURVIVAL);
|
||||||
server.getPlayerManager().sendToDimension(new EntitySetHeadYawS2CPacket(instance, (byte) (instance.headYaw * 256 / 360)), level.getRegistryKey());//instance.dimension);
|
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);
|
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.dataTracker.set(PLAYER_MODEL_PARTS, (byte) 0x7f); // show all model layers (incl. capes)
|
||||||
instance.getAbilities().flying = false;
|
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)
|
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;
|
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() {
|
public boolean canSpawnMobs() {
|
||||||
return moduleInventory.hasAbility("mobSpawning");
|
return moduleInventory.hasAbility("mobSpawning");
|
||||||
}
|
}
|
||||||
@@ -150,14 +169,10 @@ public class MinionFakePlayer extends ServerPlayerEntity {
|
|||||||
if (!isUsingItem()) super.onEquipStack(slot, previous, stack);
|
if (!isUsingItem()) super.onEquipStack(slot, previous, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@Override
|
|
||||||
public void kill()
|
|
||||||
{
|
|
||||||
kill(Text.literal("Killed"));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public void kill(Text reason)
|
public void kill(Text reason)
|
||||||
{
|
{
|
||||||
|
minionListeners.forEachListener(listener -> listener.onMinionRemove(this));
|
||||||
|
|
||||||
shakeOff();
|
shakeOff();
|
||||||
|
|
||||||
if (reason.getContent() instanceof TranslatableTextContent text && text.getKey().equals("multiplayer.disconnect.duplicate_login")) {
|
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);
|
super.writeCustomData(view);
|
||||||
moduleInventory.writeData(view.get("modules"));
|
moduleInventory.writeData(view.get("modules"));
|
||||||
instructionManager.save(view.get("instructionManager"));
|
instructionManager.save(view.get("instructionManager"));
|
||||||
|
minionListeners.save(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -273,5 +289,6 @@ public class MinionFakePlayer extends ServerPlayerEntity {
|
|||||||
super.readCustomData(view);
|
super.readCustomData(view);
|
||||||
moduleInventory.readData(view.getReadView("modules"));
|
moduleInventory.readData(view.getReadView("modules"));
|
||||||
instructionManager.load(view.getReadView("instructionManager"));
|
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 com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||||
import net.minecraft.server.world.ChunkLevelManager;
|
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.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
|
||||||
@Mixin(value = ChunkLevelManager.class)
|
@Mixin(value = ChunkLevelManager.class)
|
||||||
public class ChunkTicketManagerFixMixin {
|
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))
|
@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) {
|
public boolean filterIfNull(ObjectSet instance, Object o, Operation<Boolean> original) {
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
return original.call(instance, o);
|
return original.call(instance, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGGER.error("Prevented NPE in handleChunkLeave");
|
||||||
|
|
||||||
return false;//Unused
|
return false;//Unused
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,6 +33,8 @@ public class ChunkTicketManagerFixMixin {
|
|||||||
return original.call(instance);
|
return original.call(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGGER.error("Prevented NPE in handleChunkLeave");
|
||||||
|
|
||||||
return true;//Unused
|
return true;//Unused
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ import java.util.concurrent.Executor;
|
|||||||
|
|
||||||
@Mixin(ChunkLevelManager.class)
|
@Mixin(ChunkLevelManager.class)
|
||||||
public class ChunkLevelManagerMixin implements ChunkLevelManagerAccessor {
|
public class ChunkLevelManagerMixin implements ChunkLevelManagerAccessor {
|
||||||
@Shadow @Final private Long2ObjectMap<ObjectSet<ServerPlayerEntity>> playersByChunkPos;
|
@Shadow @Final Long2ObjectMap<ObjectSet<ServerPlayerEntity>> playersByChunkPos;
|
||||||
@Shadow @Final private ChunkLevelManager.DistanceFromNearestPlayerTracker distanceFromNearestPlayerTracker;
|
@Shadow @Final private ChunkLevelManager.DistanceFromNearestPlayerTracker distanceFromNearestPlayerTracker;
|
||||||
@Unique
|
@Unique
|
||||||
ChunkLevelManager.DistanceFromNearestPlayerTracker minionless;
|
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 com.llamalad7.mixinextras.sugar.Local;
|
||||||
import eu.pb4.graves.grave.Grave;
|
import eu.pb4.graves.grave.Grave;
|
||||||
@@ -9,7 +9,7 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||||
|
|
||||||
@Mixin(Grave.class)
|
@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"))
|
@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) {
|
private static boolean createGrave(boolean profile, @Local(argsOnly = true) ServerPlayerEntity player) {
|
||||||
if(player instanceof MinionFakePlayer) {
|
if(player instanceof MinionFakePlayer) {
|
||||||
@@ -2,7 +2,6 @@ package io.github.skippyall.minions.program.consumer;
|
|||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import io.github.skippyall.minions.MinionRegistries;
|
import io.github.skippyall.minions.MinionRegistries;
|
||||||
import io.github.skippyall.minions.gui.GuiDisplay;
|
|
||||||
import io.github.skippyall.minions.program.InstructionRuntime;
|
import io.github.skippyall.minions.program.InstructionRuntime;
|
||||||
import io.github.skippyall.minions.program.value.ValueType;
|
import io.github.skippyall.minions.program.value.ValueType;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -16,8 +15,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
public interface ValueConsumer<T,R extends InstructionRuntime<R>> {
|
public interface ValueConsumer<T,R extends InstructionRuntime<R>> {
|
||||||
void consume(T value, R runtime);
|
void consume(T value, R runtime);
|
||||||
|
|
||||||
GuiDisplay getDisplay();
|
|
||||||
|
|
||||||
ValueType<T> getValueType();
|
ValueType<T> getValueType();
|
||||||
|
|
||||||
ValueConsumerType<R> getType();
|
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.InstructionRuntime;
|
||||||
import io.github.skippyall.minions.program.supplier.Parameter;
|
import io.github.skippyall.minions.program.supplier.Parameter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class ValueConsumerList<R extends InstructionRuntime<R>> {
|
public class ValueConsumerList<R extends InstructionRuntime<R>> {
|
||||||
private final Map<String, ValueConsumer<?, R>> valueConsumers;
|
private final Map<String, ValueConsumer<?, R>> valueConsumers;
|
||||||
|
private final List<Consumer<Parameter<?>>> changeListeners = new ArrayList<>();
|
||||||
|
|
||||||
public ValueConsumerList() {
|
public ValueConsumerList() {
|
||||||
valueConsumers = new HashMap<>();
|
valueConsumers = new HashMap<>();
|
||||||
@@ -25,15 +29,30 @@ public class ValueConsumerList<R extends InstructionRuntime<R>> {
|
|||||||
|
|
||||||
public <T> void setValueConsumer(Parameter<T> parameter, ValueConsumer<?,R> consumer) {
|
public <T> void setValueConsumer(Parameter<T> parameter, ValueConsumer<?,R> consumer) {
|
||||||
valueConsumers.put(parameter.name(), 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());
|
ValueConsumer<T,R> consumer = getValueConsumer(parameter).cast(parameter.type());
|
||||||
if (consumer != null) {
|
if (consumer != null) {
|
||||||
consumer.consume(value, runtime);
|
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) {
|
public static <R extends InstructionRuntime<R>> Codec<ValueConsumerList<R>> getCodec(Codec<ValueConsumer<?,R>> valueConsumerCodec) {
|
||||||
return Codec.unboundedMap(Codec.STRING, valueConsumerCodec)
|
return Codec.unboundedMap(Codec.STRING, valueConsumerCodec)
|
||||||
.xmap(ValueConsumerList::new, list -> list.valueConsumers);
|
.xmap(ValueConsumerList::new, list -> list.valueConsumers);
|
||||||
|
|||||||
+46
-6
@@ -1,9 +1,12 @@
|
|||||||
package io.github.skippyall.minions.program.instruction;
|
package io.github.skippyall.minions.program.instruction;
|
||||||
|
|
||||||
|
import io.github.skippyall.minions.MinionRegistries;
|
||||||
import io.github.skippyall.minions.Minions;
|
import io.github.skippyall.minions.Minions;
|
||||||
import io.github.skippyall.minions.program.InstructionRuntime;
|
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.supplier.ValueSupplierList;
|
||||||
import io.github.skippyall.minions.program.consumer.ValueConsumerList;
|
import io.github.skippyall.minions.program.consumer.ValueConsumerList;
|
||||||
|
import io.github.skippyall.minions.util.SerializableListenerManager;
|
||||||
import net.minecraft.storage.ReadView;
|
import net.minecraft.storage.ReadView;
|
||||||
import net.minecraft.storage.WriteView;
|
import net.minecraft.storage.WriteView;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -14,11 +17,21 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
|
|||||||
private final ValueConsumerList<R> valueConsumers;
|
private final ValueConsumerList<R> valueConsumers;
|
||||||
private @Nullable InstructionExecution<R> execution;
|
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) {
|
private ConfiguredInstruction(InstructionType<R> instruction, ValueSupplierList<R> arguments, ValueConsumerList<R> valueConsumers, @Nullable InstructionExecution<R> execution) {
|
||||||
this.instruction = instruction;
|
this.instruction = instruction;
|
||||||
this.arguments = arguments;
|
this.arguments = arguments;
|
||||||
this.valueConsumers = valueConsumers;
|
this.valueConsumers = valueConsumers;
|
||||||
this.execution = execution;
|
this.execution = execution;
|
||||||
|
|
||||||
|
arguments.addListener(this::onSupplierChange);
|
||||||
|
valueConsumers.addListener(this::onConsumerChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfiguredInstruction(InstructionType<R> instruction) {
|
public ConfiguredInstruction(InstructionType<R> instruction) {
|
||||||
@@ -52,13 +65,14 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
|
|||||||
execution.start(minion);
|
execution.start(minion);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Minions.LOGGER.error("An error occurred while executing configured Instruction", e);
|
Minions.LOGGER.error("An error occurred while executing configured Instruction", e);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listeners.forEachListener(listener -> listener.onRun(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick(R minion) {
|
public void tick(R minion) {
|
||||||
if(isRunning()) {
|
if(execution != null) {
|
||||||
if(execution.isDone(minion)) {
|
if(execution.isDone(minion)) {
|
||||||
stop(minion);
|
stop(minion);
|
||||||
} else {
|
} else {
|
||||||
@@ -71,20 +85,43 @@ public class ConfiguredInstruction<R extends InstructionRuntime<R>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void stop(R minion) {
|
public void stop(R minion) {
|
||||||
if(isRunning()) {
|
if(execution != null) {
|
||||||
execution.stop(minion, valueConsumers);
|
execution.stop(minion, valueConsumers);
|
||||||
execution = null;
|
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) {
|
public void save(WriteView view, R minion) {
|
||||||
view.put("instruction", minion.getInstructionTypeRegistry().getCodec(), instruction);
|
view.put("instruction", minion.getInstructionTypeRegistry().getCodec(), instruction);
|
||||||
view.put("arguments", minion.getArgumentListCodec(), arguments);
|
view.put("arguments", minion.getArgumentListCodec(), arguments);
|
||||||
view.put("valueConsumers", minion.getValueConsumerListCodec(), valueConsumers);
|
view.put("valueConsumers", minion.getValueConsumerListCodec(), valueConsumers);
|
||||||
view.putBoolean("running", isRunning());
|
view.putBoolean("running", isRunning());
|
||||||
if(isRunning()) {
|
if(execution != null) {
|
||||||
execution.save(view.get("execution"), minion);
|
execution.save(view.get("execution"), minion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listeners.save(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <R extends InstructionRuntime<R>> ConfiguredInstruction<R> load(ReadView view, R minion) {
|
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);
|
boolean running = view.getBoolean("running", false);
|
||||||
|
|
||||||
|
SerializableListenerManager<ConfiguredInstructionListener> listeners = new SerializableListenerManager<>(MinionRegistries.INSTRUCTION_LISTENER_CODECS);
|
||||||
|
listeners.load(view);
|
||||||
|
|
||||||
if(running) {
|
if(running) {
|
||||||
ReadView executionView = view.getReadView("execution");
|
ReadView executionView = view.getReadView("execution");
|
||||||
try {
|
try {
|
||||||
InstructionExecution<R> execution = instructionType.loadExecution(executionView, minion);
|
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) {
|
} catch (Exception e) {
|
||||||
Minions.LOGGER.error("Error while loading execution", 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.
|
* @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
|
* 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.
|
* Loads the execution, e.g. when the server is started.
|
||||||
*/
|
*/
|
||||||
void load(ReadView view, R runtime);
|
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;
|
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.InstructionRuntime;
|
||||||
import io.github.skippyall.minions.program.supplier.Parameter;
|
import io.github.skippyall.minions.program.supplier.Parameter;
|
||||||
import io.github.skippyall.minions.program.supplier.ValueSupplierList;
|
import io.github.skippyall.minions.program.supplier.ValueSupplierList;
|
||||||
@@ -11,30 +10,24 @@ import java.util.List;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class InstructionType<R extends InstructionRuntime<R>> {
|
public class InstructionType<R extends InstructionRuntime<R>> {
|
||||||
private final GuiDisplay display;
|
private final List<Parameter<?>> parameters;
|
||||||
private final Collection<Parameter<?>> parameters;
|
private final List<Parameter<?>> returnParameters;
|
||||||
private final Collection<Parameter<?>> returnParameters;
|
|
||||||
private final Supplier<InstructionExecution<R>> executionFactory;
|
private final Supplier<InstructionExecution<R>> executionFactory;
|
||||||
|
|
||||||
public InstructionType(GuiDisplay display, Supplier<InstructionExecution<R>> executionFactory, Collection<Parameter<?>> parameters, Collection<Parameter<?>> returnParameters) {
|
public InstructionType(Supplier<InstructionExecution<R>> executionFactory, Collection<Parameter<?>> parameters, Collection<Parameter<?>> returnParameters) {
|
||||||
this.display = display;
|
|
||||||
this.parameters = List.copyOf(parameters);
|
this.parameters = List.copyOf(parameters);
|
||||||
this.returnParameters = List.copyOf(returnParameters);
|
this.returnParameters = List.copyOf(returnParameters);
|
||||||
this.executionFactory = executionFactory;
|
this.executionFactory = executionFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<Parameter<?>> getParameters() {
|
public List<Parameter<?>> getParameters() {
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<Parameter<?>> getReturnParameters() {
|
public List<Parameter<?>> getReturnParameters() {
|
||||||
return returnParameters;
|
return returnParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GuiDisplay getDisplay() {
|
|
||||||
return display;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InstructionExecution<R> createExecution(ValueSupplierList<R> parameters, R minion) {
|
public InstructionExecution<R> createExecution(ValueSupplierList<R> parameters, R minion) {
|
||||||
InstructionExecution<R> execution = executionFactory.get();
|
InstructionExecution<R> execution = executionFactory.get();
|
||||||
execution.readArguments(parameters, minion);
|
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.MinionRegistries;
|
||||||
import io.github.skippyall.minions.Minions;
|
import io.github.skippyall.minions.Minions;
|
||||||
import io.github.skippyall.minions.gui.GuiDisplay;
|
|
||||||
import io.github.skippyall.minions.minion.MinionRuntime;
|
import io.github.skippyall.minions.minion.MinionRuntime;
|
||||||
import io.github.skippyall.minions.minion.fakeplayer.EntityPlayerActionPack;
|
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.ActionExecution;
|
||||||
import io.github.skippyall.minions.program.instruction.execution.TurnExecution;
|
import io.github.skippyall.minions.program.instruction.execution.MineBlockExecution;
|
||||||
import io.github.skippyall.minions.program.instruction.execution.WalkExecution;
|
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 io.github.skippyall.minions.program.supplier.Parameter;
|
||||||
import net.minecraft.item.Items;
|
|
||||||
import net.minecraft.registry.Registry;
|
import net.minecraft.registry.Registry;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class Instructions {
|
public class Instructions {
|
||||||
public static final InstructionType<MinionRuntime> WALK = register(
|
public static final InstructionType<MinionRuntime> WALK = register(
|
||||||
"walk",
|
"walk",
|
||||||
base -> new GuiDisplay.ModelBased(Items.IRON_BOOTS, base, true),
|
|
||||||
WalkExecution::new,
|
WalkExecution::new,
|
||||||
List.of(WalkExecution.blocksToMoveParam)
|
List.of(WalkExecution.blocksToMoveParam)
|
||||||
);
|
);
|
||||||
|
public static final InstructionType<MinionRuntime> WALK_CONTINUOUS = register(
|
||||||
|
"walk_continuous",
|
||||||
|
ContinuousWalkExecution::new
|
||||||
|
);
|
||||||
|
|
||||||
public static final InstructionType<MinionRuntime> TURN = register(
|
public static final InstructionType<MinionRuntime> TURN = register(
|
||||||
"turn",
|
"turn",
|
||||||
base -> new GuiDisplay.ModelBased(Items.STRUCTURE_VOID, base, true),
|
|
||||||
TurnExecution::new,
|
TurnExecution::new,
|
||||||
List.of(TurnExecution.ANGLE, TurnExecution.DIRECTION)
|
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(
|
public static final InstructionType<MinionRuntime> ATTACK = register(
|
||||||
"attack",
|
"attack",
|
||||||
base -> new GuiDisplay.ModelBased(Items.IRON_PICKAXE, base, true),
|
|
||||||
() -> new ActionExecution(EntityPlayerActionPack.ActionType.ATTACK)
|
() -> new ActionExecution(EntityPlayerActionPack.ActionType.ATTACK)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static final InstructionType<MinionRuntime> MINE_BLOCK = register(
|
||||||
|
"mine_block",
|
||||||
|
MineBlockExecution::new
|
||||||
|
);
|
||||||
|
|
||||||
public static final InstructionType<MinionRuntime> USE = register(
|
public static final InstructionType<MinionRuntime> USE = register(
|
||||||
"use",
|
"use",
|
||||||
base -> new GuiDisplay.ModelBased(Items.LEVER, base, true),
|
|
||||||
() -> new ActionExecution(EntityPlayerActionPack.ActionType.USE)
|
() -> 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);
|
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) {
|
private static InstructionType<MinionRuntime> register(String id, Supplier<InstructionExecution<MinionRuntime>> factory, Collection<Parameter<?>> parameters) {
|
||||||
return register(id, displayFunction, factory, parameters, List.of());
|
return register(id, factory, parameters, List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InstructionType<MinionRuntime> register(String id, Function<String, GuiDisplay> displayFunction, Supplier<InstructionExecution<MinionRuntime>> factory) {
|
private static InstructionType<MinionRuntime> register(String id, Supplier<InstructionExecution<MinionRuntime>> factory) {
|
||||||
return register(id, displayFunction, factory, List.of(), List.of());
|
return register(id, factory, List.of(), List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void register() {
|
public static void register() {
|
||||||
|
|||||||
+4
-1
@@ -16,7 +16,10 @@ public class ActionExecution implements ContinuousInstructionExecution<MinionRun
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(MinionRuntime minion) {
|
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
|
@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.minion.MinionRuntime;
|
||||||
import io.github.skippyall.minions.program.consumer.ValueConsumerList;
|
|
||||||
import io.github.skippyall.minions.program.instruction.InstructionExecution;
|
import io.github.skippyall.minions.program.instruction.InstructionExecution;
|
||||||
import io.github.skippyall.minions.program.supplier.Parameter;
|
import io.github.skippyall.minions.program.supplier.Parameter;
|
||||||
import io.github.skippyall.minions.program.supplier.ValueSupplierList;
|
import io.github.skippyall.minions.program.supplier.ValueSupplierList;
|
||||||
@@ -11,15 +10,15 @@ import net.minecraft.storage.ReadView;
|
|||||||
import net.minecraft.storage.WriteView;
|
import net.minecraft.storage.WriteView;
|
||||||
|
|
||||||
public class WalkExecution implements InstructionExecution<MinionRuntime> {
|
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 static final float ACCURACY = 1F / 32F;
|
||||||
|
|
||||||
private float totalBlocksToMove;
|
private double totalBlocksToMove;
|
||||||
private float blocksMoved;
|
private double blocksMoved;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(MinionRuntime minion) {
|
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));
|
minion.getMinion().move(MovementType.SELF, minion.getMinion().getHorizontalFacing().getDoubleVector().normalize().multiply(speed));
|
||||||
blocksMoved += speed;
|
blocksMoved += speed;
|
||||||
}
|
}
|
||||||
@@ -29,26 +28,21 @@ public class WalkExecution implements InstructionExecution<MinionRuntime> {
|
|||||||
return totalBlocksToMove - blocksMoved < ACCURACY;
|
return totalBlocksToMove - blocksMoved < ACCURACY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stop(MinionRuntime minion, ValueConsumerList<MinionRuntime> valueConsumers) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readArguments(ValueSupplierList<MinionRuntime> parameters, MinionRuntime minion) {
|
public void readArguments(ValueSupplierList<MinionRuntime> parameters, MinionRuntime minion) {
|
||||||
totalBlocksToMove = parameters.getValue(blocksToMoveParam, minion);
|
totalBlocksToMove = parameters.getValue(blocksToMoveParam, minion).floatValue();
|
||||||
blocksMoved = 0;
|
blocksMoved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(WriteView view, MinionRuntime minion) {
|
public void save(WriteView view, MinionRuntime minion) {
|
||||||
view.putFloat("totalBlocksToMove", totalBlocksToMove);
|
view.putDouble("totalBlocksToMove", totalBlocksToMove);
|
||||||
view.putFloat("blocksMoved", blocksMoved);
|
view.putDouble("blocksMoved", blocksMoved);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(ReadView view, MinionRuntime minion) {
|
public void load(ReadView view, MinionRuntime minion) {
|
||||||
totalBlocksToMove = view.getFloat("totalBlocksToMove", 0F);
|
totalBlocksToMove = view.getDouble("totalBlocksToMove", 0F);
|
||||||
blocksMoved = view.getFloat("blocksMoved", 0F);
|
blocksMoved = view.getDouble("blocksMoved", 0F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-11
@@ -1,18 +1,17 @@
|
|||||||
package io.github.skippyall.minions.program.supplier;
|
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.InstructionRuntime;
|
||||||
import io.github.skippyall.minions.program.value.ValueType;
|
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> {
|
public class FixedValueSupplier<T, R extends InstructionRuntime<R>> implements ValueSupplier<T, R> {
|
||||||
private final ValueArgumentType<R> type;
|
private final FixedValueSupplierType<R> type;
|
||||||
private final ValueType<T> valueType;
|
private final ValueType<T> valueType;
|
||||||
private final T value;
|
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.type = type;
|
||||||
this.valueType = valueType;
|
this.valueType = valueType;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
@@ -27,18 +26,13 @@ public class ValueArgument<T, R extends InstructionRuntime<R>> implements ValueS
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public GuiDisplay getDisplay() {
|
|
||||||
return getValueType().display();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValueType<T> getValueType() {
|
public ValueType<T> getValueType() {
|
||||||
return valueType;
|
return valueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValueArgumentType<R> getType() {
|
public FixedValueSupplierType<R> getType() {
|
||||||
return type;
|
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 com.mojang.serialization.Codec;
|
||||||
import io.github.skippyall.minions.MinionRegistries;
|
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.InstructionRuntime;
|
||||||
import io.github.skippyall.minions.program.value.ValueType;
|
import io.github.skippyall.minions.program.value.ValueType;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -16,8 +15,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
public interface ValueSupplier<T, R extends InstructionRuntime<R>> {
|
public interface ValueSupplier<T, R extends InstructionRuntime<R>> {
|
||||||
T resolve(R minion);
|
T resolve(R minion);
|
||||||
|
|
||||||
GuiDisplay getDisplay();
|
|
||||||
|
|
||||||
ValueType<T> getValueType();
|
ValueType<T> getValueType();
|
||||||
|
|
||||||
ValueSupplierType<R> getType();
|
ValueSupplierType<R> getType();
|
||||||
|
|||||||
@@ -3,12 +3,16 @@ package io.github.skippyall.minions.program.supplier;
|
|||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import io.github.skippyall.minions.program.InstructionRuntime;
|
import io.github.skippyall.minions.program.InstructionRuntime;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class ValueSupplierList<R extends InstructionRuntime<R>> {
|
public class ValueSupplierList<R extends InstructionRuntime<R>> {
|
||||||
private final Map<String, ValueSupplier<?, R>> arguments;
|
private final Map<String, ValueSupplier<?, R>> arguments;
|
||||||
|
private final List<Consumer<Parameter<?>>> changeListeners = new ArrayList<>();
|
||||||
|
|
||||||
public ValueSupplierList() {
|
public ValueSupplierList() {
|
||||||
arguments = new HashMap<>();
|
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) {
|
public <T> void setArgument(Parameter<T> parameter, ValueSupplier<T,R> valueSupplier) {
|
||||||
arguments.put(parameter.name(), valueSupplier);
|
arguments.put(parameter.name(), valueSupplier);
|
||||||
|
onChange(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasArgumentFor(Parameter<?> parameter) {
|
public boolean hasArgumentFor(Parameter<?> parameter) {
|
||||||
return getArgument(parameter) != null;
|
return arguments.containsKey(parameter.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasArgumentForAll(Collection<Parameter<?>> checkParameters) {
|
public boolean hasArgumentForAll(Collection<Parameter<?>> checkParameters) {
|
||||||
@@ -45,6 +50,21 @@ public class ValueSupplierList<R extends InstructionRuntime<R>> {
|
|||||||
return true;
|
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) {
|
public static <R extends InstructionRuntime<R>> Codec<ValueSupplierList<R>> getCodec(Codec<ValueSupplier<?,R>> argumentCodec) {
|
||||||
return Codec.unboundedMap(Codec.STRING, argumentCodec)
|
return Codec.unboundedMap(Codec.STRING, argumentCodec)
|
||||||
.xmap(ValueSupplierList::new, list -> list.arguments);
|
.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;
|
package io.github.skippyall.minions.program.value;
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
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 net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.BiFunction;
|
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) {
|
public CompletableFuture<T> openValueDialog(ServerPlayerEntity player, T previousValue) {
|
||||||
return valueDialogOpener.apply(player, previousValue);
|
return valueDialogOpener.apply(player, previousValue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,9 @@ package io.github.skippyall.minions.program.value;
|
|||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import io.github.skippyall.minions.MinionRegistries;
|
import io.github.skippyall.minions.MinionRegistries;
|
||||||
import io.github.skippyall.minions.Minions;
|
import io.github.skippyall.minions.Minions;
|
||||||
import io.github.skippyall.minions.gui.GuiDisplay;
|
|
||||||
import io.github.skippyall.minions.gui.input.ChoiceInput;
|
import io.github.skippyall.minions.gui.input.ChoiceInput;
|
||||||
import io.github.skippyall.minions.gui.input.TextInput;
|
import io.github.skippyall.minions.gui.input.TextInput;
|
||||||
import io.github.skippyall.minions.program.instruction.execution.TurnExecution;
|
import io.github.skippyall.minions.program.instruction.execution.move.TurnDirection;
|
||||||
import net.minecraft.item.Items;
|
|
||||||
import net.minecraft.registry.Registry;
|
import net.minecraft.registry.Registry;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
@@ -15,27 +13,24 @@ import net.minecraft.util.Identifier;
|
|||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public class ValueTypes {
|
public class ValueTypes {
|
||||||
public static ValueType<Integer> INTEGER = registerSimple(
|
public static ValueType<Long> LONG = registerSimple(
|
||||||
"integer",
|
"long",
|
||||||
Codec.INT,
|
Codec.LONG,
|
||||||
key -> new GuiDisplay.ModelBased(Items.NETHERITE_SCRAP, key, true),
|
0L,
|
||||||
0,
|
(player, oldValue) -> TextInput.inputLong(
|
||||||
(player, oldValue) -> TextInput.inputInt(
|
|
||||||
player,
|
player,
|
||||||
Text.literal("Integer"),
|
Text.literal("Integer"),
|
||||||
String.valueOf(oldValue)
|
String.valueOf(oldValue)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
public static ValueType<Float> FLOAT = registerSimple(
|
public static ValueType<Double> DOUBLE = registerSimple(
|
||||||
"float",
|
"double",
|
||||||
Codec.FLOAT,
|
Codec.DOUBLE,
|
||||||
key -> new GuiDisplay.ModelBased(Items.BAMBOO_RAFT, key, true),
|
0D,
|
||||||
0F,
|
(player, oldValue) -> TextInput.inputDouble(
|
||||||
(player, oldValue) -> TextInput.inputFloat(
|
|
||||||
player,
|
player,
|
||||||
Text.literal("Number"),
|
Text.literal("Number"),
|
||||||
String.valueOf(oldValue)
|
String.valueOf(oldValue)
|
||||||
@@ -45,7 +40,6 @@ public class ValueTypes {
|
|||||||
public static ValueType<String> STRING = registerSimple(
|
public static ValueType<String> STRING = registerSimple(
|
||||||
"string",
|
"string",
|
||||||
Codec.STRING,
|
Codec.STRING,
|
||||||
key -> new GuiDisplay.ModelBased(Items.STRING, key, true),
|
|
||||||
"",
|
"",
|
||||||
((player, oldValue) -> TextInput.inputString(
|
((player, oldValue) -> TextInput.inputString(
|
||||||
player,
|
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",
|
"turn_direction",
|
||||||
TurnExecution.TurnDirection.CODEC,
|
TurnDirection.CODEC,
|
||||||
base -> new GuiDisplay.ModelBased(Items.STRUCTURE_VOID, base, true),
|
TurnDirection.RIGHT,
|
||||||
TurnExecution.TurnDirection.RIGHT,
|
ChoiceInput.createDialogOpener(TurnDirection.values())
|
||||||
ChoiceInput.createDialogOpener(TurnExecution.TurnDirection.values())
|
|
||||||
);
|
);
|
||||||
|
|
||||||
public static ValueType<Void> VOID = registerSimple(
|
private static <T> ValueType<T> registerSimple(String id, Codec<T> codec, T defaultValue, BiFunction<ServerPlayerEntity, T, CompletableFuture<T>> valueDialogOpener) {
|
||||||
"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) {
|
|
||||||
Identifier identifier = Identifier.of(Minions.MOD_ID, id);
|
Identifier identifier = Identifier.of(Minions.MOD_ID, id);
|
||||||
return Registry.register(
|
return Registry.register(
|
||||||
MinionRegistries.VALUE_TYPES,
|
MinionRegistries.VALUE_TYPES,
|
||||||
identifier,
|
identifier,
|
||||||
new ValueType<>(
|
new ValueType<>(
|
||||||
codec,
|
codec,
|
||||||
displayFunction.apply(identifier.toTranslationKey("value_type")),
|
|
||||||
defaultValue,
|
defaultValue,
|
||||||
valueDialogOpener
|
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.modules": "Modules",
|
||||||
"minions.gui.main.inventory": "Inventory",
|
"minions.gui.main.inventory": "Inventory",
|
||||||
"minions.gui.main.pickup": "Pick up",
|
"minions.gui.main.pickup": "Pick up",
|
||||||
"minions.gui.inventory.title": "%s's Inventory",
|
"minions.gui.inventory.title": "Inventory",
|
||||||
"minions.gui.module_commands.title": "Commands",
|
"minions.gui.modules.title": "Modules",
|
||||||
"minions.gui.commands.title": "%s's Commands",
|
|
||||||
"minions.gui.modules.title": "%s's Modules",
|
|
||||||
"minions.gui.ok": "OK",
|
"minions.gui.ok": "OK",
|
||||||
"minions.gui.confirm": "Confirm",
|
"minions.gui.confirm": "Confirm",
|
||||||
"minions.gui.abort": "Abort",
|
"minions.gui.abort": "Abort",
|
||||||
@@ -19,8 +17,11 @@
|
|||||||
"minions.gui.look.skin.base64.title": "Enter a skin in base64 encoding",
|
"minions.gui.look.skin.base64.title": "Enter a skin in base64 encoding",
|
||||||
"minions.gui.look.rename.title": "Enter a name",
|
"minions.gui.look.rename.title": "Enter a name",
|
||||||
|
|
||||||
|
"minions.gui.instruction.title": "Instructions",
|
||||||
"minions.gui.instruction.list": "Instruction List",
|
"minions.gui.instruction.list": "Instruction List",
|
||||||
"minions.gui.instruction.create": "New Instruction",
|
"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.no_instruction_set": "No instruction set",
|
||||||
"minions.gui.instruction.enter_name": "Enter a name",
|
"minions.gui.instruction.enter_name": "Enter a name",
|
||||||
"minions.gui.instruction.name_already_used": "Name already used",
|
"minions.gui.instruction.name_already_used": "Name already used",
|
||||||
@@ -35,6 +36,7 @@
|
|||||||
"minions.gui.instruction.stop": "Stop",
|
"minions.gui.instruction.stop": "Stop",
|
||||||
"minions.gui.instruction.argument.configure.type": "Type: %s",
|
"minions.gui.instruction.argument.configure.type": "Type: %s",
|
||||||
"minions.gui.instruction.argument.configure.type.unset": "Unset",
|
"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.int.fail": "Not an integer",
|
||||||
"minions.command.input.float.fail": "Not a number",
|
"minions.command.input.float.fail": "Not a number",
|
||||||
@@ -51,6 +53,24 @@
|
|||||||
|
|
||||||
"minions.command.minion.not_present": "This minion does not exist",
|
"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.attack_module": "Attack Module",
|
||||||
"item.minions.interact_module": "Interact Module",
|
"item.minions.interact_module": "Interact Module",
|
||||||
"item.minions.mob_spawning_module": "Mob Spawning Module",
|
"item.minions.mob_spawning_module": "Mob Spawning Module",
|
||||||
@@ -59,6 +79,7 @@
|
|||||||
"item.minions.minion": "Minion",
|
"item.minions.minion": "Minion",
|
||||||
"item.minions.basic_upgrade_base": "Basic Upgrade Base",
|
"item.minions.basic_upgrade_base": "Basic Upgrade Base",
|
||||||
"item.minions.advanced_upgrade_base": "Advanced Upgrade Base",
|
"item.minions.advanced_upgrade_base": "Advanced Upgrade Base",
|
||||||
|
"item.minions.reference": "Reference",
|
||||||
|
|
||||||
"minions.minion_item.tooltip": "Name: %s",
|
"minions.minion_item.tooltip": "Name: %s",
|
||||||
"minions.generic.name.invalid_char": "Name contains invalid character",
|
"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",
|
"icon": "assets/minions/icon.png",
|
||||||
"environment": "*",
|
"environment": "*",
|
||||||
"entrypoints": {
|
"entrypoints": {
|
||||||
|
"client": [
|
||||||
|
"io.github.skippyall.minions.client.MinionsClient"
|
||||||
|
],
|
||||||
"main": [
|
"main": [
|
||||||
"io.github.skippyall.minions.Minions"
|
"io.github.skippyall.minions.Minions"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ accessWidener v2 named
|
|||||||
|
|
||||||
accessible class net/minecraft/server/world/ChunkLevelManager$DistanceFromNearestPlayerTracker
|
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",
|
"EntityAccessor",
|
||||||
"EntityMixin",
|
"EntityMixin",
|
||||||
"EntityViewMixin",
|
"EntityViewMixin",
|
||||||
"GraveCompatMixin",
|
"compat.universal_graves.GraveMixin",
|
||||||
"MinecraftServerMixin",
|
"MinecraftServerMixin",
|
||||||
"MobEntityMixin",
|
"MobEntityMixin",
|
||||||
"PlayerListEntryS2CPacket$EntryMixin",
|
"PlayerListEntryS2CPacket$EntryMixin",
|
||||||
@@ -28,5 +28,6 @@
|
|||||||
"server": [],
|
"server": [],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
}
|
},
|
||||||
|
"plugin": "io.github.skippyall.minions.MinionMixinConfigPlugin"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user