diff --git a/build.gradle b/build.gradle index d91c610..473a5de 100644 --- a/build.gradle +++ b/build.gradle @@ -122,14 +122,14 @@ publishing { // Notice: This block does NOT have the same function as the block in the top level. // The repositories here will be used for publishing your artifact, not for // retrieving dependencies. - maven { - def release = "https://maven.foxgalaxy.de/private-releases" - def snapshot = "https://maven.foxgalaxy.de/private-snapshot" - url = version.endsWith('SNAPSHOT') ? snapshot : release + if(project.hasProperty("foxgalaxy_user_name") && project.hasProperty("foxgalaxy_password")) { + maven { + url = "https://maven.foxgalaxy.de/private" - credentials { - username = "${maven_user}" - password = "${maven_password}" + credentials { + username = project.property("foxgalaxy_user_name") + password = project.property("foxgalaxy_password") + } } } } diff --git a/src/main/java/io/github/skippyall/minions/MinionItems.java b/src/main/java/io/github/skippyall/minions/MinionItems.java index a0d0fe6..da2fd4b 100644 --- a/src/main/java/io/github/skippyall/minions/MinionItems.java +++ b/src/main/java/io/github/skippyall/minions/MinionItems.java @@ -6,6 +6,9 @@ import io.github.skippyall.minions.block.MinionTriggerBlockItem; import io.github.skippyall.minions.minion.MinionItem; import io.github.skippyall.minions.minion.MinionRuntime; import io.github.skippyall.minions.module.MinionModule; +import io.github.skippyall.minions.module.MobSpawningAbility; +import io.github.skippyall.minions.module.SpecialAbilities; +import io.github.skippyall.minions.module.SpecialAbility; import io.github.skippyall.minions.program.instruction.InstructionType; import io.github.skippyall.minions.program.instruction.Instructions; import io.github.skippyall.minions.reference.ReferenceItem; @@ -66,7 +69,7 @@ public class MinionItems { Identifier.of(MOD_ID, "mob_spawning_module"), Items.SPAWNER, List.of(), - List.of("mobSpawning") + List.of(SpecialAbilities.MOB_SPAWNING) ); public static final PolymerBlockItem MINION_TRIGGER_ITEM = @@ -89,11 +92,11 @@ public class MinionItems { return registerItem(identifier, constructor, new Item.Settings()); } - public static SimplePolymerItem registerModule(Identifier identifier, Item vanillaItem, List> instructionTypes, List specialEffects) { + public static SimplePolymerItem registerModule(Identifier identifier, Item vanillaItem, List> instructionTypes, List specialAbilities) { return registerItem( identifier, settings -> new SimplePolymerItem(settings, vanillaItem), - new Item.Settings().component(MinionModule.COMPONENT_TYPE, new MinionModule(instructionTypes, specialEffects)) + new Item.Settings().component(MinionModule.COMPONENT_TYPE, new MinionModule(instructionTypes, specialAbilities)) ); } diff --git a/src/main/java/io/github/skippyall/minions/MinionRegistries.java b/src/main/java/io/github/skippyall/minions/MinionRegistries.java index 528a829..bc260d2 100644 --- a/src/main/java/io/github/skippyall/minions/MinionRegistries.java +++ b/src/main/java/io/github/skippyall/minions/MinionRegistries.java @@ -7,6 +7,7 @@ import io.github.skippyall.minions.gui.GuiDisplay; import io.github.skippyall.minions.minion.MinionListener; import io.github.skippyall.minions.minion.MinionRuntime; import io.github.skippyall.minions.minion.skin.SkinProvider; +import io.github.skippyall.minions.module.SpecialAbility; import io.github.skippyall.minions.program.instruction.ConfiguredInstructionListener; import io.github.skippyall.minions.program.supplier.ValueSupplierType; import io.github.skippyall.minions.program.instruction.InstructionType; @@ -30,6 +31,7 @@ public class MinionRegistries { public static final Registry> INSTRUCTION_LISTENER_CODECS = registry("instruction_listener_codec"); public static final Registry> MINION_LISTENER_CODECS = registry("minion_listener_codec"); public static final Registry> REFERENCE_CODEC = registry("reference_codec"); + public static final Registry SPECIAL_ABILITIES = registry("special_ability"); public static final RegistryKey> GUI_DISPLAY = key("gui_display"); public static final RegistryKey> REFERENCE_ENTRY = key("reference_entry"); diff --git a/src/main/java/io/github/skippyall/minions/Minions.java b/src/main/java/io/github/skippyall/minions/Minions.java index d8f5d72..2d78a73 100644 --- a/src/main/java/io/github/skippyall/minions/Minions.java +++ b/src/main/java/io/github/skippyall/minions/Minions.java @@ -11,6 +11,7 @@ import io.github.skippyall.minions.module.MinionModule; import io.github.skippyall.minions.program.instruction.Instructions; import io.github.skippyall.minions.program.supplier.ValueSuppliers; import io.github.skippyall.minions.program.value.ValueTypes; +import io.github.skippyall.minions.reference.Reference; import io.github.skippyall.minions.util.PolymerUtil; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; @@ -35,6 +36,7 @@ public class Minions implements ModInitializer { MinionData.register(); MinionModule.register(); + Reference.register(); MinionBlocks.register(); MinionItems.register(); diff --git a/src/main/java/io/github/skippyall/minions/block/BlockEntityMinionListener.java b/src/main/java/io/github/skippyall/minions/block/BlockEntityMinionListener.java index 2ba6c67..d335ad6 100644 --- a/src/main/java/io/github/skippyall/minions/block/BlockEntityMinionListener.java +++ b/src/main/java/io/github/skippyall/minions/block/BlockEntityMinionListener.java @@ -3,28 +3,36 @@ 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 io.github.skippyall.minions.minion.MinionPersistentState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; 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; +import java.util.UUID; +import java.util.function.BiFunction; -public class BlockEntityMinionListener implements MinionListener { +public abstract class BlockEntityMinionListener implements MinionListener { protected RegistryKey worldKey; protected BlockPos pos; + protected BlockEntityType type; - public BlockEntityMinionListener(RegistryKey worldKey, BlockPos pos) { + public BlockEntityMinionListener(RegistryKey worldKey, BlockPos pos, BlockEntityType type) { this.worldKey = worldKey; this.pos = pos; + this.type = type; } - public static final Codec 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)); - + public static > Codec getCodec(BiFunction, BlockPos, L> constructor) { + return RecordCodecBuilder.create(instance -> + instance.group( + World.CODEC.fieldOf("world").forGetter(listener -> listener.worldKey), + BlockPos.CODEC.fieldOf("pos").forGetter(listener -> listener.pos) + ).apply(instance, constructor)); + } private BlockEntityState getBlockEntityState(MinecraftServer server) { World world = server.getWorld(worldKey); @@ -32,21 +40,39 @@ public class BlockEntityMinionListener implements MinionListener { return BlockEntityState.UNLOADED; } - if(world.getBlockEntity(pos) instanceof MinionListeningBlockEntity) { + if(world.getBlockEntity(pos, type).isPresent()) { return BlockEntityState.LOADED; } else { return BlockEntityState.REMOVED; } } - public Optional getBlockEntity(MinecraftServer server) { + public Optional getBlockEntity(MinecraftServer server) { World world = server.getWorld(worldKey); - if(world != null && world.isPosLoaded(pos) && world.getBlockEntity(pos) instanceof MinionListeningBlockEntity be) { - return Optional.of(be); + if(world != null && world.isPosLoaded(pos)) { + return world.getBlockEntity(pos, type); } return Optional.empty(); } + public boolean removeIfBeRemoved(MinecraftServer server, UUID minion) { + if(getBlockEntityState(server) == BlockEntityState.REMOVED) { + remove(minion); + return true; + } + return false; + } + + public void add(UUID minion) { + MinionPersistentState.INSTANCE.getMinionData(minion).listeners().addListener(this); + MinionPersistentState.INSTANCE.markDirty(); + } + + public void remove(UUID minion) { + MinionPersistentState.INSTANCE.getMinionData(minion).listeners().removeListener(this); + MinionPersistentState.INSTANCE.markDirty(); + } + public enum BlockEntityState { LOADED, REMOVED, diff --git a/src/main/java/io/github/skippyall/minions/block/MinionListeningBlockEntity.java b/src/main/java/io/github/skippyall/minions/block/MinionListeningBlockEntity.java deleted file mode 100644 index 6235355..0000000 --- a/src/main/java/io/github/skippyall/minions/block/MinionListeningBlockEntity.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.skippyall.minions.block; - -import io.github.skippyall.minions.minion.MinionListener; - -public interface MinionListeningBlockEntity extends MinionListener { - -} diff --git a/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlock.java b/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlock.java index cd60786..8c4264d 100644 --- a/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlock.java +++ b/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlock.java @@ -96,7 +96,12 @@ public class MinionTriggerBlock extends BlockWithEntity implements PolymerBlock, @Override protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { + if(world.isClient()) { + return ActionResult.CONSUME; + } + world.getBlockEntity(pos, MinionBlocks.MINION_TRIGGER_BE_TYPE).ifPresent(be -> { + String name = MinionPersistentState.INSTANCE.getMinionData(be.getMinionUuid()).name(); player.sendMessage(Text.translatable("minions.reference.instruction.tooltip", name, be.getInstructionName()), true); }); diff --git a/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlockEntity.java b/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlockEntity.java index 96abda4..ae283a6 100644 --- a/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlockEntity.java +++ b/src/main/java/io/github/skippyall/minions/block/MinionTriggerBlockEntity.java @@ -1,6 +1,7 @@ package io.github.skippyall.minions.block; import io.github.skippyall.minions.MinionBlocks; +import io.github.skippyall.minions.minion.MinionPersistentState; import io.github.skippyall.minions.minion.MinionRuntime; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.program.instruction.ConfiguredInstruction; diff --git a/src/main/java/io/github/skippyall/minions/block/MinionTriggerMinionListener.java b/src/main/java/io/github/skippyall/minions/block/MinionTriggerMinionListener.java new file mode 100644 index 0000000..1608056 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/block/MinionTriggerMinionListener.java @@ -0,0 +1,32 @@ +package io.github.skippyall.minions.block; + +import io.github.skippyall.minions.MinionBlocks; +import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.program.instruction.ConfiguredInstructionListener; +import net.minecraft.registry.RegistryKey; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.util.UUID; + +public class MinionTriggerMinionListener extends BlockEntityMinionListener implements ConfiguredInstructionListener { + boolean registeredListener; + String instructionName; + + public MinionTriggerMinionListener(RegistryKey worldKey, BlockPos pos, String instructionName, boolean registeredListener) { + super(worldKey, pos, MinionBlocks.MINION_TRIGGER_BE_TYPE); + this.instructionName = instructionName; + this.registeredListener = registeredListener; + } + + @Override + public void onMinionSpawn(MinionFakePlayer minion) { + if(!registeredListener) { + minion.getInstructionManager().getInstruction(instructionName).addListener(this); + } + } + + @Override + public void onMinionRemove(MinionFakePlayer minion) { + } +} diff --git a/src/main/java/io/github/skippyall/minions/gui/GuiDisplay.java b/src/main/java/io/github/skippyall/minions/gui/GuiDisplay.java index f98d39c..a0b3ca6 100644 --- a/src/main/java/io/github/skippyall/minions/gui/GuiDisplay.java +++ b/src/main/java/io/github/skippyall/minions/gui/GuiDisplay.java @@ -15,6 +15,7 @@ import net.minecraft.item.Items; import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKeys; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Rarity; diff --git a/src/main/java/io/github/skippyall/minions/minion/MinionData.java b/src/main/java/io/github/skippyall/minions/minion/MinionData.java index 35235e8..ddcda1f 100644 --- a/src/main/java/io/github/skippyall/minions/minion/MinionData.java +++ b/src/main/java/io/github/skippyall/minions/minion/MinionData.java @@ -5,7 +5,9 @@ import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import eu.pb4.polymer.core.api.other.PolymerComponent; +import io.github.skippyall.minions.MinionRegistries; import io.github.skippyall.minions.Minions; +import io.github.skippyall.minions.util.SerializableListenerManager; import net.minecraft.component.ComponentType; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtOps; @@ -19,36 +21,33 @@ import org.jetbrains.annotations.Nullable; import java.util.Optional; import java.util.UUID; -public record MinionData(UUID uuid, String name, Optional skin, boolean isSpawned) { +public record MinionData(UUID uuid, String name, Optional skin, boolean isSpawned, SerializableListenerManager listeners) { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Uuids.CODEC.fieldOf("uuid").forGetter(MinionData::uuid), Codec.STRING.fieldOf("name").forGetter(MinionData::name), Codecs.GAME_PROFILE_PROPERTY_MAP.optionalFieldOf("skin").forGetter(MinionData::skin), - Codec.BOOL.optionalFieldOf("isSpawned", false).forGetter(MinionData::isSpawned) + Codec.BOOL.optionalFieldOf("isSpawned", false).forGetter(MinionData::isSpawned), + SerializableListenerManager.getCodec(MinionRegistries.MINION_LISTENER_CODECS).optionalFieldOf("listeners", new SerializableListenerManager<>(MinionRegistries.MINION_LISTENER_CODECS)).forGetter(MinionData::listeners) ).apply(instance, MinionData::new) ); public static final ComponentType COMPONENT = Registry.register(Registries.DATA_COMPONENT_TYPE, Identifier.of(Minions.MOD_ID, "minion_data"), ComponentType.builder().codec(Uuids.CODEC).build()); public static MinionData createDefault() { - return new MinionData(UUID.randomUUID(), MinionProfileUtils.newDefaultMinionName(), Optional.empty(), false); - } - - public MinionData withUuid(UUID uuid) { - return new MinionData(uuid, name, skin, isSpawned); + return new MinionData(UUID.randomUUID(), MinionProfileUtils.newDefaultMinionName(), Optional.empty(), false, new SerializableListenerManager<>(MinionRegistries.MINION_LISTENER_CODECS)); } public MinionData withName(String name) { - return new MinionData(uuid, name, skin, isSpawned); + return new MinionData(uuid, name, skin, isSpawned, listeners); } public MinionData withSkin(Optional skin) { - return new MinionData(uuid, name, skin, isSpawned); + return new MinionData(uuid, name, skin, isSpawned, listeners); } public MinionData withSpawned(boolean isSpawned) { - return new MinionData(uuid, name, skin, isSpawned); + return new MinionData(uuid, name, skin, isSpawned, listeners); } public NbtCompound writeNbt() { diff --git a/src/main/java/io/github/skippyall/minions/minion/MinionListener.java b/src/main/java/io/github/skippyall/minions/minion/MinionListener.java index 5548270..5f811e9 100644 --- a/src/main/java/io/github/skippyall/minions/minion/MinionListener.java +++ b/src/main/java/io/github/skippyall/minions/minion/MinionListener.java @@ -3,6 +3,7 @@ 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; +import org.jetbrains.annotations.Nullable; public interface MinionListener extends SerializableListenerManager.SerializableListener { default void onMinionSpawn(MinionFakePlayer minion) {} @@ -12,4 +13,36 @@ public interface MinionListener extends SerializableListenerManager.Serializable default void onInstructionsUpdate(MinionFakePlayer minion) {} default void onInstructionRename(MinionFakePlayer minion, ConfiguredInstruction instruction, String newName) {} + + interface Delegating extends MinionListener { + @Nullable MinionListener getBacking(); + + @Override + default void onMinionSpawn(MinionFakePlayer minion) { + if(getBacking() != null) { + getBacking().onMinionSpawn(minion); + } + } + + @Override + default void onMinionRemove(MinionFakePlayer minion) { + if(getBacking() != null) { + getBacking().onMinionRemove(minion); + } + } + + @Override + default void onInstructionsUpdate(MinionFakePlayer minion) { + if(getBacking() != null) { + getBacking().onMinionSpawn(minion); + } + } + + @Override + default void onInstructionRename(MinionFakePlayer minion, ConfiguredInstruction instruction, String newName) { + if(getBacking() != null) { + getBacking().onInstructionRename(minion, instruction, newName); + } + } + } } diff --git a/src/main/java/io/github/skippyall/minions/minion/MinionRuntime.java b/src/main/java/io/github/skippyall/minions/minion/MinionRuntime.java index df7b21e..de3061f 100644 --- a/src/main/java/io/github/skippyall/minions/minion/MinionRuntime.java +++ b/src/main/java/io/github/skippyall/minions/minion/MinionRuntime.java @@ -35,6 +35,14 @@ public class MinionRuntime implements InstructionRuntime { } } + public void disableInstructionType(InstructionType instructionType) { + + } + + public void enableInstructionType(InstructionType instructionType) { + + } + public Set getInstructionNames() { return configuredInstructions.keySet(); } diff --git a/src/main/java/io/github/skippyall/minions/minion/fakeplayer/MinionFakePlayer.java b/src/main/java/io/github/skippyall/minions/minion/fakeplayer/MinionFakePlayer.java index 4f94dd5..e133c2a 100644 --- a/src/main/java/io/github/skippyall/minions/minion/fakeplayer/MinionFakePlayer.java +++ b/src/main/java/io/github/skippyall/minions/minion/fakeplayer/MinionFakePlayer.java @@ -12,7 +12,9 @@ import io.github.skippyall.minions.minion.MinionRuntime; import io.github.skippyall.minions.minion.MinionItem; import io.github.skippyall.minions.minion.MinionPersistentState; import io.github.skippyall.minions.minion.MinionProfileUtils; +import io.github.skippyall.minions.module.MobSpawningAbility; import io.github.skippyall.minions.module.ModuleInventory; +import io.github.skippyall.minions.module.SpecialAbilities; import io.github.skippyall.minions.util.SerializableListenerManager; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; @@ -56,7 +58,7 @@ public class MinionFakePlayer extends ServerPlayerEntity { private EntityPlayerActionPack actionPack; private final SerializableListenerManager minionListeners = new SerializableListenerManager<>(MinionRegistries.MINION_LISTENER_CODECS); - private final ModuleInventory moduleInventory = new ModuleInventory(); + private final ModuleInventory moduleInventory = new ModuleInventory(this); private final MinionRuntime instructionManager = new MinionRuntime(this); private final MinionData data; @@ -93,8 +95,8 @@ public class MinionFakePlayer extends ServerPlayerEntity { instance.unsetRemoved(); instance.getAttributeInstance(EntityAttributes.STEP_HEIGHT).setBaseValue(0.6F); instance.interactionManager.changeGameMode(GameMode.SURVIVAL); - server.getPlayerManager().sendToDimension(new EntitySetHeadYawS2CPacket(instance, (byte) (instance.headYaw * 256 / 360)), level.getRegistryKey());//instance.dimension); - server.getPlayerManager().sendToDimension(EntityPositionSyncS2CPacket.create(instance), level.getRegistryKey());//instance.dimension); + server.getPlayerManager().sendToDimension(new EntitySetHeadYawS2CPacket(instance, (byte) (instance.headYaw * 256 / 360)), level.getRegistryKey()); + server.getPlayerManager().sendToDimension(EntityPositionSyncS2CPacket.create(instance), level.getRegistryKey()); instance.getWorld().getChunkManager().updatePosition(instance); instance.dataTracker.set(PLAYER_MODEL_PARTS, (byte) 0x7f); // show all model layers (incl. capes) instance.getAbilities().flying = false; @@ -143,11 +145,11 @@ public class MinionFakePlayer extends ServerPlayerEntity { } public boolean canSpawnMobs() { - return moduleInventory.hasAbility("mobSpawning"); + return moduleInventory.hasAbility(SpecialAbilities.MOB_SPAWNING); } public boolean canDespawnMobs() { - return moduleInventory.hasAbility("mobSpawning"); + return moduleInventory.hasAbility(SpecialAbilities.MOB_SPAWNING); } @Override diff --git a/src/main/java/io/github/skippyall/minions/module/MinionModule.java b/src/main/java/io/github/skippyall/minions/module/MinionModule.java index 95b0281..93c9f05 100644 --- a/src/main/java/io/github/skippyall/minions/module/MinionModule.java +++ b/src/main/java/io/github/skippyall/minions/module/MinionModule.java @@ -14,11 +14,11 @@ import net.minecraft.util.Identifier; import java.util.List; -public record MinionModule(List> instructions, List specialBehaviour) { +public record MinionModule(List> instructions, List specialAbilities) { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( MinionRegistries.INSTRUCTION_TYPES.getCodec().listOf().fieldOf("instructions").forGetter(MinionModule::instructions), - Codec.STRING.listOf().fieldOf("specialBehaviour").forGetter(MinionModule::specialBehaviour) + MinionRegistries.SPECIAL_ABILITIES.getCodec().listOf().fieldOf("specialAbilities").forGetter(MinionModule::specialAbilities) ).apply(instance, MinionModule::new) ); @@ -30,9 +30,9 @@ public record MinionModule(List> instructions, Li this(instructions, List.of()); } - public MinionModule(List> instructions, List specialBehaviour) { + public MinionModule(List> instructions, List specialAbilities) { this.instructions = List.copyOf(instructions); - this.specialBehaviour = List.copyOf(specialBehaviour); + this.specialAbilities = List.copyOf(specialAbilities); } public static void register() { diff --git a/src/main/java/io/github/skippyall/minions/module/MobSpawningAbility.java b/src/main/java/io/github/skippyall/minions/module/MobSpawningAbility.java new file mode 100644 index 0000000..2805600 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/module/MobSpawningAbility.java @@ -0,0 +1,15 @@ +package io.github.skippyall.minions.module; + +import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; + +public class MobSpawningAbility implements SpecialAbility { + @Override + public void onAdd(MinionFakePlayer minion) { + SpecialAbility.super.onAdd(minion); + } + + @Override + public void onRemove(MinionFakePlayer minion) { + SpecialAbility.super.onRemove(minion); + } +} diff --git a/src/main/java/io/github/skippyall/minions/module/ModuleInventory.java b/src/main/java/io/github/skippyall/minions/module/ModuleInventory.java index b45184a..8490bea 100644 --- a/src/main/java/io/github/skippyall/minions/module/ModuleInventory.java +++ b/src/main/java/io/github/skippyall/minions/module/ModuleInventory.java @@ -1,5 +1,6 @@ package io.github.skippyall.minions.module; +import io.github.skippyall.minions.minion.MinionRuntime; import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.program.instruction.InstructionType; import net.minecraft.inventory.Inventories; @@ -19,10 +20,14 @@ import java.util.Set; public class ModuleInventory extends SimpleInventory { private final Set modules = new HashSet<>(); - private final Set specialAbilities = new HashSet<>(); + private final Set> instructions = new HashSet<>(); + private final Set specialAbilities = new HashSet<>(); - public ModuleInventory() { + private final MinionFakePlayer minion; + + public ModuleInventory(MinionFakePlayer minion) { super(27); + this.minion = minion; } public static void openModuleInventory(ServerPlayerEntity player, MinionFakePlayer minion) { @@ -46,13 +51,37 @@ public class ModuleInventory extends SimpleInventory { } public void updateModules() { + Set oldModules = Set.copyOf(modules); + Set> oldInstructions = Set.copyOf(instructions); + Set oldAbilities = Set.copyOf(specialAbilities); + modules.clear(); + instructions.clear(); specialAbilities.clear(); for (ItemStack heldStack : heldStacks) { MinionModule module = heldStack.get(MinionModule.COMPONENT_TYPE); if(module != null) { modules.add(module); - specialAbilities.addAll(module.specialBehaviour()); + instructions.addAll(module.instructions()); + specialAbilities.addAll(module.specialAbilities()); + + for(SpecialAbility ability : module.specialAbilities()) { + if(!oldAbilities.contains(ability)) { + ability.onAdd(minion); + } + } + } + } + + for(InstructionType instructionType : oldInstructions) { + if(!instructions.contains(instructionType)) { + minion.getInstructionManager().disableInstructionType(instructionType); + } + } + + for(SpecialAbility ability : oldAbilities) { + if(!specialAbilities.contains(ability)) { + ability.onRemove(minion); } } } @@ -70,7 +99,7 @@ public class ModuleInventory extends SimpleInventory { return modules; } - public boolean hasAbility(String ability) { + public boolean hasAbility(SpecialAbility ability) { return specialAbilities.contains(ability); } diff --git a/src/main/java/io/github/skippyall/minions/module/ModuleInventoryScreenHandler.java b/src/main/java/io/github/skippyall/minions/module/ModuleInventoryScreenHandler.java index 79b5f1d..d9394c0 100644 --- a/src/main/java/io/github/skippyall/minions/module/ModuleInventoryScreenHandler.java +++ b/src/main/java/io/github/skippyall/minions/module/ModuleInventoryScreenHandler.java @@ -12,11 +12,6 @@ public class ModuleInventoryScreenHandler extends ScreenHandler { private final int rows = 3; private final ModuleInventory inventory; - public ModuleInventoryScreenHandler(int syncId, ModuleInventory inventory) { - super(ScreenHandlerType.GENERIC_9X3, syncId); - this.inventory = inventory; - } - public ModuleInventoryScreenHandler(int syncId, PlayerInventory playerInventory, ModuleInventory inventory) { super(ScreenHandlerType.GENERIC_9X3, syncId); diff --git a/src/main/java/io/github/skippyall/minions/module/SpecialAbilities.java b/src/main/java/io/github/skippyall/minions/module/SpecialAbilities.java new file mode 100644 index 0000000..c84d26d --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/module/SpecialAbilities.java @@ -0,0 +1,10 @@ +package io.github.skippyall.minions.module; + +import io.github.skippyall.minions.MinionRegistries; +import io.github.skippyall.minions.Minions; +import net.minecraft.registry.Registry; +import net.minecraft.util.Identifier; + +public class SpecialAbilities { + public static final MobSpawningAbility MOB_SPAWNING = Registry.register(MinionRegistries.SPECIAL_ABILITIES, Identifier.of(Minions.MOD_ID, "mob_spawning"), new MobSpawningAbility()); +} diff --git a/src/main/java/io/github/skippyall/minions/module/SpecialAbility.java b/src/main/java/io/github/skippyall/minions/module/SpecialAbility.java new file mode 100644 index 0000000..ab2784b --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/module/SpecialAbility.java @@ -0,0 +1,11 @@ +package io.github.skippyall.minions.module; + +import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer; + +public interface SpecialAbility { + default void onAdd(MinionFakePlayer minion) {} + + default void onRemove(MinionFakePlayer minion) {} + + default void tick(MinionFakePlayer minion) {} +} diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java b/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java index b638174..8cbe38e 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/ConfiguredInstruction.java @@ -17,7 +17,7 @@ public class ConfiguredInstruction> { private final ValueConsumerList valueConsumers; private @Nullable InstructionExecution execution; - private SerializableListenerManager listeners; + private SerializableListenerManager listeners = new SerializableListenerManager<>(MinionRegistries.INSTRUCTION_LISTENER_CODECS); private ConfiguredInstruction(InstructionType instruction, ValueSupplierList arguments, ValueConsumerList valueConsumers, @Nullable InstructionExecution execution, SerializableListenerManager listeners) { this(instruction, arguments, valueConsumers, execution); @@ -29,7 +29,6 @@ public class ConfiguredInstruction> { this.arguments = arguments; this.valueConsumers = valueConsumers; this.execution = execution; - arguments.addListener(this::onSupplierChange); valueConsumers.addListener(this::onConsumerChange); } diff --git a/src/main/java/io/github/skippyall/minions/program/instruction/execution/MineBlockExecution.java b/src/main/java/io/github/skippyall/minions/program/instruction/execution/MineBlockExecution.java index 27f6b6e..81aba51 100644 --- a/src/main/java/io/github/skippyall/minions/program/instruction/execution/MineBlockExecution.java +++ b/src/main/java/io/github/skippyall/minions/program/instruction/execution/MineBlockExecution.java @@ -114,8 +114,10 @@ public class MineBlockExecution implements InstructionExecution { 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); + if(currentBlock != null) { + player.getWorld().setBlockBreakingInfo(-1, currentBlock, -1); + player.interactionManager.processBlockBreakingAction(currentBlock, PlayerActionC2SPacket.Action.ABORT_DESTROY_BLOCK, Direction.DOWN, player.getWorld().getTopYInclusive(), -1); + } } @Override diff --git a/src/main/java/io/github/skippyall/minions/reference/ReferenceItem.java b/src/main/java/io/github/skippyall/minions/reference/ReferenceItem.java index bbf74c7..212c125 100644 --- a/src/main/java/io/github/skippyall/minions/reference/ReferenceItem.java +++ b/src/main/java/io/github/skippyall/minions/reference/ReferenceItem.java @@ -8,6 +8,8 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.item.tooltip.TooltipType; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; import xyz.nucleoid.packettweaker.PacketContext; public class ReferenceItem extends Item implements PolymerItem { @@ -20,6 +22,11 @@ public class ReferenceItem extends Item implements PolymerItem { return Items.PAPER; } + @Override + public @Nullable Identifier getPolymerItemModel(ItemStack stack, PacketContext context) { + return null; + } + @Override public ItemStack getPolymerItemStack(ItemStack itemStack, TooltipType tooltipType, PacketContext context) { ItemStack stack = PolymerItem.super.getPolymerItemStack(itemStack, tooltipType, context); diff --git a/src/main/java/io/github/skippyall/minions/util/ListenerManager.java b/src/main/java/io/github/skippyall/minions/util/ListenerManager.java index 588a14f..5401fdf 100644 --- a/src/main/java/io/github/skippyall/minions/util/ListenerManager.java +++ b/src/main/java/io/github/skippyall/minions/util/ListenerManager.java @@ -5,7 +5,15 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; public class ListenerManager { - protected final List listeners = new CopyOnWriteArrayList<>(); + protected final List listeners; + + public ListenerManager() { + this(new CopyOnWriteArrayList<>()); + } + + protected ListenerManager(List listeners) { + this.listeners = listeners; + } public void forEachListener(Consumer listenerConsumer) { for(T listener : listeners) { diff --git a/src/main/java/io/github/skippyall/minions/util/SerializableListenerManager.java b/src/main/java/io/github/skippyall/minions/util/SerializableListenerManager.java index a7232a2..e7607d1 100644 --- a/src/main/java/io/github/skippyall/minions/util/SerializableListenerManager.java +++ b/src/main/java/io/github/skippyall/minions/util/SerializableListenerManager.java @@ -6,7 +6,10 @@ import net.minecraft.storage.ReadView; import net.minecraft.storage.WriteView; import net.minecraft.util.Identifier; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.concurrent.CopyOnWriteArrayList; public class SerializableListenerManager extends ListenerManager { private final Registry> registry; @@ -15,6 +18,29 @@ public class SerializableListenerManager> registry, List listeners) { + super(listeners); + this.registry = registry; + } + + public static Codec> getCodec(Registry> registry) { + return registry.getCodec().dispatch( + listener -> listener.getCodecId().map(registry::get).orElse(Codec.unit(null)), + codec -> codec.fieldOf("data") + ).listOf().xmap( + list -> new SerializableListenerManager<>(registry, new CopyOnWriteArrayList<>(list)), + manager -> { + List serializableListeners = new ArrayList<>(); + for(T listener : manager.listeners) { + if(listener.getCodecId().isPresent()) { + serializableListeners.add(listener); + } + } + return serializableListeners; + } + ); + } + public void save(WriteView view) { WriteView.ListView listView = view.getList("listeners"); for (T listener : listeners) { diff --git a/src/main/resources/data/minions/minions/gui_display/instruction_type/attack.json b/src/main/resources/data/minions/minions/gui_display/instruction_type/attack.json index 0680a52..9aa4499 100644 --- a/src/main/resources/data/minions/minions/gui_display/instruction_type/attack.json +++ b/src/main/resources/data/minions/minions/gui_display/instruction_type/attack.json @@ -1,4 +1,4 @@ { "type": "minions:item", - "data": "minecraft:iron_pickaxe" + "data": "minecraft:iron_sword" } \ No newline at end of file diff --git a/src/main/resources/data/minions/minions/gui_display/instruction_type/mine_block.json b/src/main/resources/data/minions/minions/gui_display/instruction_type/mine_block.json new file mode 100644 index 0000000..0680a52 --- /dev/null +++ b/src/main/resources/data/minions/minions/gui_display/instruction_type/mine_block.json @@ -0,0 +1,4 @@ +{ + "type": "minions:item", + "data": "minecraft:iron_pickaxe" +} \ No newline at end of file diff --git a/src/main/resources/data/minions/minions/gui_display/instruction_type/turn_vector.json b/src/main/resources/data/minions/minions/gui_display/instruction_type/turn_vector.json new file mode 100644 index 0000000..22d6b5e --- /dev/null +++ b/src/main/resources/data/minions/minions/gui_display/instruction_type/turn_vector.json @@ -0,0 +1,4 @@ +{ + "type": "minions:item", + "data": "minecraft:structure_void" +} \ No newline at end of file diff --git a/src/main/resources/data/minions/minions/gui_display/instruction_type/walk_continuous.json b/src/main/resources/data/minions/minions/gui_display/instruction_type/walk_continuous.json new file mode 100644 index 0000000..2e7fa4a --- /dev/null +++ b/src/main/resources/data/minions/minions/gui_display/instruction_type/walk_continuous.json @@ -0,0 +1,4 @@ +{ + "type": "minions:item", + "data": "minecraft:iron_boots" +} \ No newline at end of file