diff --git a/build.gradle b/build.gradle index 3148fc6..de2194f 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ dependencies { // Fabric API. This is technically optional, but you probably want it anyway. modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - modImplementation include("eu.pb4:polymer-core:${project.polymer_version}") + modImplementation "eu.pb4:polymer-core:${project.polymer_version}" modImplementation include("eu.pb4:sgui:${project.sgui_version}") } @@ -76,7 +76,7 @@ jar { // configure the maven publication publishing { publications { - mavenJava(MavenPublication) { + minions (MavenPublication) { from components.java } } @@ -87,5 +87,15 @@ 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 + + credentials { + username = "${maven_user}" + password = "${maven_password}" + } + } } } diff --git a/gradle.properties b/gradle.properties index 9a411d4..43547c9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G yarn_mappings=1.21.1+build.3 # Mod Properties - mod_version = 0.0.1 + mod_version = 0.0.1-SNAPSHOT maven_group = io.github.skippyall archives_base_name = Minions diff --git a/src/main/java/io/github/skippyall/minions/Minions.java b/src/main/java/io/github/skippyall/minions/Minions.java index 57aa27f..7522d34 100644 --- a/src/main/java/io/github/skippyall/minions/Minions.java +++ b/src/main/java/io/github/skippyall/minions/Minions.java @@ -1,12 +1,16 @@ package io.github.skippyall.minions; import eu.pb4.polymer.core.api.entity.PolymerEntityUtils; +import eu.pb4.polymer.core.api.item.SimplePolymerItem; import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; import io.github.skippyall.minions.minion.MinionItem; import io.github.skippyall.minions.minion.MinionPersistentState; +import io.github.skippyall.minions.module.Modules; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.minecraft.item.Item; +import net.minecraft.item.Items; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.server.MinecraftServer; @@ -20,6 +24,7 @@ import java.util.List; public class Minions implements ModInitializer { public static final String MOD_ID = "minions"; public static final MinionItem MINION_ITEM = Registry.register(Registries.ITEM, Identifier.of(MOD_ID, "minion"), new MinionItem(false)); + public static final SimplePolymerItem BASIC_UPGRADE_BASE = Registry.register(Registries.ITEM, Identifier.of(MOD_ID, "basic_upgrade_base"), new SimplePolymerItem(new Item.Settings(), Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE)); public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); @@ -44,6 +49,8 @@ public class Minions implements ModInitializer { executeOnNextTick.clear(); }); }); + + Modules.register(); } private static synchronized void exec(Runnable run) { diff --git a/src/main/java/io/github/skippyall/minions/command/Command.java b/src/main/java/io/github/skippyall/minions/command/Command.java new file mode 100644 index 0000000..1c5bd06 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/command/Command.java @@ -0,0 +1,15 @@ +package io.github.skippyall.minions.command; + +import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; +import net.minecraft.item.Item; +import net.minecraft.network.packet.LoginPackets; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; + +public interface Command { + Text getName(); + Text getDescription(); + Item getItemRepresentation(); + + void onRun(ServerPlayerEntity player, MinionFakePlayer minion); +} diff --git a/src/main/java/io/github/skippyall/minions/command/SimpleCommand.java b/src/main/java/io/github/skippyall/minions/command/SimpleCommand.java new file mode 100644 index 0000000..bd01683 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/command/SimpleCommand.java @@ -0,0 +1,43 @@ +package io.github.skippyall.minions.command; + +import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; +import net.minecraft.item.Item; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; + +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +public class SimpleCommand implements Command { + private final Text name; + private final Text description; + private final Item itemRepresentation; + private final BiConsumer onRun; + + public SimpleCommand(Text name, Text description, Item itemRepresentation, BiConsumer onRun) { + this.name = name; + this.description = description; + this.itemRepresentation = itemRepresentation; + this.onRun = onRun; + } + + @Override + public Text getName() { + return name; + } + + @Override + public Text getDescription() { + return description; + } + + @Override + public Item getItemRepresentation() { + return itemRepresentation; + } + + @Override + public void onRun(ServerPlayerEntity player, MinionFakePlayer minion) { + onRun.accept(player, minion); + } +} diff --git a/src/main/java/io/github/skippyall/minions/fakeplayer/EntityPlayerActionPack.java b/src/main/java/io/github/skippyall/minions/fakeplayer/EntityPlayerActionPack.java index 3794471..2188faa 100644 --- a/src/main/java/io/github/skippyall/minions/fakeplayer/EntityPlayerActionPack.java +++ b/src/main/java/io/github/skippyall/minions/fakeplayer/EntityPlayerActionPack.java @@ -5,6 +5,8 @@ import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; + +import io.github.skippyall.minions.mixins.EntityAccessor; import net.minecraft.block.BlockState; import net.minecraft.command.argument.EntityAnchorArgumentType; import net.minecraft.entity.Entity; @@ -167,12 +169,13 @@ public class EntityPlayerActionPack public EntityPlayerActionPack mount(boolean onlyRideables) { + //test what happens List entities; if (onlyRideables) { entities = player.getWorld().getOtherEntities(player, player.getBoundingBox().expand(3.0D, 1.0D, 3.0D), - e -> e instanceof MinecartEntity || e instanceof BoatEntity || e instanceof AbstractHorseEntity); + e -> (e instanceof MinecartEntity || e instanceof BoatEntity || e instanceof AbstractHorseEntity) && ((EntityAccessor)e).invokeCanAddPassenger(player)); } else { @@ -198,7 +201,7 @@ public class EntityPlayerActionPack if (closest instanceof AbstractHorseEntity && onlyRideables) ((AbstractHorseEntity) closest).interactMob(player, Hand.MAIN_HAND); else - player.startRiding(closest,true); + player.startRiding(closest, !onlyRideables); return this; } public EntityPlayerActionPack dismount() diff --git a/src/main/java/io/github/skippyall/minions/fakeplayer/MinionFakePlayer.java b/src/main/java/io/github/skippyall/minions/fakeplayer/MinionFakePlayer.java index 1292383..dc41f04 100644 --- a/src/main/java/io/github/skippyall/minions/fakeplayer/MinionFakePlayer.java +++ b/src/main/java/io/github/skippyall/minions/fakeplayer/MinionFakePlayer.java @@ -7,6 +7,9 @@ import io.github.skippyall.minions.minion.*; import io.github.skippyall.minions.mixins.GameProfileMixin; import io.github.skippyall.minions.program.runtime.MinionRuntime; import net.minecraft.block.BlockState; +import net.minecraft.block.PistonBlock; +import net.minecraft.command.EntitySelector; +import net.minecraft.command.argument.EntityArgumentType; import net.minecraft.component.DataComponentTypes; import net.minecraft.entity.Entity; import net.minecraft.entity.EquipmentSlot; @@ -23,11 +26,13 @@ import net.minecraft.network.packet.c2s.common.SyncedClientOptions; import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket; import net.minecraft.network.packet.s2c.play.EntityPositionS2CPacket; import net.minecraft.network.packet.s2c.play.EntitySetHeadYawS2CPacket; +import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerTask; import net.minecraft.server.network.ConnectedClientData; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Decoration; import net.minecraft.text.Text; import net.minecraft.text.TranslatableTextContent; import net.minecraft.util.ActionResult; @@ -319,7 +324,7 @@ public class MinionFakePlayer extends ServerPlayerEntity { @Override protected void drop(ServerWorld world, DamageSource damageSource) { super.drop(world, damageSource); - dropItem(toItemStack(), true, false); + dropStack(toItemStack()); } private ItemStack toItemStack() { diff --git a/src/main/java/io/github/skippyall/minions/input/TextInput.java b/src/main/java/io/github/skippyall/minions/input/TextInput.java new file mode 100644 index 0000000..235f0d6 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/input/TextInput.java @@ -0,0 +1,27 @@ +package io.github.skippyall.minions.input; + +import eu.pb4.sgui.api.elements.GuiElementBuilder; +import eu.pb4.sgui.api.gui.AnvilInputGui; +import net.minecraft.item.Items; +import net.minecraft.screen.AnvilScreenHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; + +import java.util.concurrent.CompletableFuture; + +public class TextInput { + public static CompletableFuture inputText(ServerPlayerEntity player, Text title, String defaultText) { + CompletableFuture future = new CompletableFuture<>(); + + AnvilInputGui gui = new AnvilInputGui(player, false); + gui.setSlot(AnvilScreenHandler.OUTPUT_ID, new GuiElementBuilder() + .setItem(Items.EMERALD_BLOCK) + .setName(Text.literal("OK")) + .setCallback(() -> future.complete(gui.getInput())) + ); + gui.setTitle(title); + gui.setDefaultInputValue(defaultText); + gui.open(); + return future; + } +} diff --git a/src/main/java/io/github/skippyall/minions/minion/CommandsInventory.java b/src/main/java/io/github/skippyall/minions/minion/CommandsInventory.java index 2db0845..e4414c8 100644 --- a/src/main/java/io/github/skippyall/minions/minion/CommandsInventory.java +++ b/src/main/java/io/github/skippyall/minions/minion/CommandsInventory.java @@ -2,24 +2,46 @@ package io.github.skippyall.minions.minion; import eu.pb4.sgui.api.elements.GuiElementBuilder; import eu.pb4.sgui.api.gui.SimpleGui; +import io.github.skippyall.minions.command.Command; import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; -import net.minecraft.item.Items; +import net.minecraft.screen.GenericContainerScreenHandler; import net.minecraft.screen.ScreenHandlerType; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; + +import java.util.List; public class CommandsInventory { public static void openServerCommandsInventory(ServerPlayerEntity player, MinionFakePlayer minion) { - SimpleGui gui = new SimpleGui(ScreenHandlerType.GENERIC_9X3, player, false); + List commands = minion.getModuleInventory().getAllCommands(); + int rows = (int) Math.ceil((double) commands.size() / 9.0); - gui.setSlot(0, new GuiElementBuilder() - .setItem(Items.MINECART) - .setName(Text.literal("Get into minecart")) - .setCallback(() -> { - minion.getMinionActionPack().mount(true); - }) - ); + if(rows != 0) { + boolean paged = false; + SimpleGui gui = new SimpleGui(getTypeForRows(rows), player, false); - gui.open(); + for (int i = 0; i < commands.size() && i < 54; i++) { + Command command = commands.get(i); + gui.setSlot(i, new GuiElementBuilder() + .setItem(command.getItemRepresentation()) + .setName(command.getName()) + .addLoreLine(command.getDescription()) + .setCallback(() -> command.onRun(player, minion)) + ); + } + + gui.open(); + } + } + + public static ScreenHandlerType getTypeForRows(int rows) { + return switch (rows) { + case 1 -> ScreenHandlerType.GENERIC_9X1; + case 2 -> ScreenHandlerType.GENERIC_9X2; + case 3 -> ScreenHandlerType.GENERIC_9X3; + case 4 -> ScreenHandlerType.GENERIC_9X4; + case 5 -> ScreenHandlerType.GENERIC_9X5; + case 6 -> ScreenHandlerType.GENERIC_9X6; + default -> throw new IllegalStateException("Unexpected value: " + rows); + }; } } diff --git a/src/main/java/io/github/skippyall/minions/minion/MinionItem.java b/src/main/java/io/github/skippyall/minions/minion/MinionItem.java index e5c1c31..03f6087 100644 --- a/src/main/java/io/github/skippyall/minions/minion/MinionItem.java +++ b/src/main/java/io/github/skippyall/minions/minion/MinionItem.java @@ -10,6 +10,7 @@ import net.minecraft.item.tooltip.TooltipType; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.registry.RegistryWrapper; +import net.minecraft.server.command.DebugMobSpawningCommand; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.ActionResult; @@ -17,10 +18,12 @@ import net.minecraft.util.math.Vec2f; import org.jetbrains.annotations.Nullable; public class MinionItem extends Item implements PolymerItem { + private final boolean canProgram; public MinionItem(boolean canProgram) { super(new Item.Settings()); this.canProgram = canProgram; + } @Override @@ -39,7 +42,7 @@ public class MinionItem extends Item implements PolymerItem { public ActionResult useOnBlock(ItemUsageContext context) { String contents = context.getStack().getName().getLiteralString(); String name; - if(contents != null) { + if(contents != null && contents.length() <= 16) { name = contents; } else { name = "Minion"; diff --git a/src/main/java/io/github/skippyall/minions/minion/ModuleInventory.java b/src/main/java/io/github/skippyall/minions/minion/ModuleInventory.java index 6e3b634..c276ffb 100644 --- a/src/main/java/io/github/skippyall/minions/minion/ModuleInventory.java +++ b/src/main/java/io/github/skippyall/minions/minion/ModuleInventory.java @@ -1,6 +1,10 @@ package io.github.skippyall.minions.minion; import io.github.skippyall.minions.Minions; +import io.github.skippyall.minions.command.Command; +import io.github.skippyall.minions.module.ModuleItem; +import io.github.skippyall.minions.module.Modules; +import io.github.skippyall.minions.program.block.CodeBlock; import net.minecraft.inventory.Inventories; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -11,8 +15,10 @@ import net.minecraft.registry.tag.TagKey; import net.minecraft.util.Identifier; import net.minecraft.util.collection.DefaultedList; +import java.util.ArrayList; +import java.util.List; + public class ModuleInventory implements ImplementedInventory { - private static final TagKey MODULES = TagKey.of(RegistryKeys.ITEM, Identifier.of(Minions.MOD_ID,"modules")); private DefaultedList stacks = DefaultedList.ofSize(27, ItemStack.EMPTY); public ModuleInventory() { @@ -25,7 +31,7 @@ public class ModuleInventory implements ImplementedInventory { @Override public boolean isValid(int slot, ItemStack stack) { - return (stack.getCount() <= getMaxCountPerStack()) && stack.isIn(MODULES); + return (stack.getCount() <= getMaxCountPerStack()) && stack.getItem() instanceof ModuleItem; } @Override @@ -40,4 +46,34 @@ public class ModuleInventory implements ImplementedInventory { public NbtCompound writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup lookup) { return Inventories.writeNbt(nbt, stacks, lookup); } + + public List getModuleItems() { + ArrayList modules = new ArrayList<>(); + for(ItemStack stack : stacks) { + if(stack.getItem() instanceof ModuleItem module) { + modules.add(module); + } + } + return modules; + } + + public List getAllCommands() { + ArrayList commands = new ArrayList<>(); + for(ItemStack stack : stacks) { + if(stack.getItem() instanceof ModuleItem module) { + commands.addAll(module.getCommands()); + } + } + return commands; + } + + public List> getAllCodeBlocks() { + ArrayList> commands = new ArrayList<>(); + for(ItemStack stack : stacks) { + if(stack.getItem() instanceof ModuleItem module) { + commands.addAll(module.getCodeBlocks()); + } + } + return commands; + } } diff --git a/src/main/java/io/github/skippyall/minions/mixins/ChunkTicketManagerFixMixin.java b/src/main/java/io/github/skippyall/minions/mixins/ChunkTicketManagerFixMixin.java index a7b3b43..a3005dd 100644 --- a/src/main/java/io/github/skippyall/minions/mixins/ChunkTicketManagerFixMixin.java +++ b/src/main/java/io/github/skippyall/minions/mixins/ChunkTicketManagerFixMixin.java @@ -7,9 +7,9 @@ import net.minecraft.server.world.ChunkTicketManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -@Mixin(value = ChunkTicketManager.class, remap = false) +@Mixin(value = ChunkTicketManager.class) public class ChunkTicketManagerFixMixin { - @WrapOperation(method = "handleChunkLeave", at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/objects/ObjectSet;remove(Ljava/lang/Object;)Z")) + @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 original) { if (instance != null) { return original.call(instance, o); @@ -18,7 +18,7 @@ public class ChunkTicketManagerFixMixin { return false;//Unused } - @WrapOperation(method = "handleChunkLeave", at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/objects/ObjectSet;isEmpty()Z")) + @WrapOperation(method = "handleChunkLeave", at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/objects/ObjectSet;isEmpty()Z", remap = false)) public boolean filterIfNull(ObjectSet instance, Operation original) { if (instance != null) { return original.call(instance); diff --git a/src/main/java/io/github/skippyall/minions/mixins/DebugMixin.java b/src/main/java/io/github/skippyall/minions/mixins/DebugMixin.java index 7512276..6acd469 100644 --- a/src/main/java/io/github/skippyall/minions/mixins/DebugMixin.java +++ b/src/main/java/io/github/skippyall/minions/mixins/DebugMixin.java @@ -26,7 +26,7 @@ public class DebugMixin { @Inject(method = "setPos", at = @At("HEAD")) public void debug(double x, double y, double z, CallbackInfo ci) { if ((Object) this instanceof MinionFakePlayer) { - System.out.println("Set Minion Pos to " + x + " " + y + " " + z); + //System.out.println("Set Minion Pos to " + x + " " + y + " " + z); } } } diff --git a/src/main/java/io/github/skippyall/minions/mixins/EntityAccessor.java b/src/main/java/io/github/skippyall/minions/mixins/EntityAccessor.java new file mode 100644 index 0000000..6746f5f --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/mixins/EntityAccessor.java @@ -0,0 +1,11 @@ +package io.github.skippyall.minions.mixins; + +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Entity.class) +public interface EntityAccessor { + @Invoker("canAddPassenger") + boolean invokeCanAddPassenger(Entity other); +} diff --git a/src/main/java/io/github/skippyall/minions/mixins/MobEntityMixin.java b/src/main/java/io/github/skippyall/minions/mixins/MobEntityMixin.java new file mode 100644 index 0000000..9ebd36d --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/mixins/MobEntityMixin.java @@ -0,0 +1,29 @@ +package io.github.skippyall.minions.mixins; + +import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.module.MobSpawningModule; +import net.minecraft.entity.Entity; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.predicate.entity.EntityPredicates; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(MobEntity.class) +public abstract class MobEntityMixin { + @Redirect(method = "checkDespawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;getClosestPlayer(Lnet/minecraft/entity/Entity;D)Lnet/minecraft/entity/player/PlayerEntity;")) + public PlayerEntity checkMobDespawningMinion(World instance, Entity entity, double maxDistance) { + return instance.getClosestPlayer(entity.getX(), entity.getY(), entity.getZ(), maxDistance, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(entity1 -> { + if(entity1 instanceof ServerPlayerEntity player) { + if(player instanceof MinionFakePlayer minion) { + return MobSpawningModule.canMinionDespawnMobs(minion); + } + return true; + } + return false; + })); + } +} diff --git a/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java b/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java index 37baf7f..0bce7b7 100644 --- a/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java +++ b/src/main/java/io/github/skippyall/minions/mixins/PlayerListMixin.java @@ -1,5 +1,6 @@ package io.github.skippyall.minions.mixins; +import com.llamalad7.mixinextras.injector.ModifyReceiver; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; @@ -21,6 +22,10 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + @Mixin(PlayerManager.class) public class PlayerListMixin { @@ -57,4 +62,11 @@ public class PlayerListMixin { original.call(instance, message, overlay); } } + + @ModifyReceiver(method = "checkCanJoin", at = @At(value = "INVOKE", target = "Ljava/util/List;size()I")) + public List noMinionCounting(List instance) { + return instance.stream() + .filter(player -> !(player instanceof MinionFakePlayer)) + .collect(Collectors.toCollection(ArrayList::new)); + } } diff --git a/src/main/java/io/github/skippyall/minions/mixins/SpawnHelperMixin.java b/src/main/java/io/github/skippyall/minions/mixins/SpawnHelperMixin.java new file mode 100644 index 0000000..650d0da --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/mixins/SpawnHelperMixin.java @@ -0,0 +1,28 @@ +package io.github.skippyall.minions.mixins; + +import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; +import io.github.skippyall.minions.module.MobSpawningModule; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.predicate.entity.EntityPredicates; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.SpawnHelper; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(SpawnHelper.class) +public class SpawnHelperMixin { + @Redirect(method = "spawnEntitiesInChunk(Lnet/minecraft/entity/SpawnGroup;Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/Chunk;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/SpawnHelper$Checker;Lnet/minecraft/world/SpawnHelper$Runner;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;getClosestPlayer(DDDDZ)Lnet/minecraft/entity/player/PlayerEntity;")) + private static PlayerEntity checkMobSpawningMinion(ServerWorld instance, double x, double y, double z, double maxDistance, boolean b) { + return instance.getClosestPlayer(x, y, z, maxDistance, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(entity -> { + if(entity instanceof ServerPlayerEntity player) { + if(player instanceof MinionFakePlayer minion) { + return MobSpawningModule.canMinionSpawnMobs(minion); + } + return true; + } + return false; + })); + } +} diff --git a/src/main/java/io/github/skippyall/minions/module/ChatModule.java b/src/main/java/io/github/skippyall/minions/module/ChatModule.java new file mode 100644 index 0000000..8946db5 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/module/ChatModule.java @@ -0,0 +1,23 @@ +package io.github.skippyall.minions.module; + +import io.github.skippyall.minions.Minions; +import io.github.skippyall.minions.command.SimpleCommand; +import net.minecraft.item.Items; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static io.github.skippyall.minions.module.Modules.register; + +public class ChatModule { + public static final SimpleModuleItem CHAT_MODULE = register(Identifier.of(Minions.MOD_ID, "chat_module"), + new SimpleModuleItem(new ArrayList<>(), Arrays.asList( + new SimpleCommand(Text.of("Message"), Text.of("Send Message in Public Chat"), Items.PAPER, (player, minion) -> minion.getServer().getPlayerManager().broadcast(Text.of("message"), true)), + new SimpleCommand(Text.of("Prvt-Message"), Text.of("Send Message to one Person"), Items.TRIAL_KEY, (player, minion) -> {}) + ), Items.PAPER)); + + public static void registerMe() {} +} diff --git a/src/main/java/io/github/skippyall/minions/module/MobSpawningModule.java b/src/main/java/io/github/skippyall/minions/module/MobSpawningModule.java new file mode 100644 index 0000000..ff79fb7 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/module/MobSpawningModule.java @@ -0,0 +1,15 @@ +package io.github.skippyall.minions.module; + +import io.github.skippyall.minions.fakeplayer.MinionFakePlayer; + +public class MobSpawningModule { + + + public static boolean canMinionSpawnMobs(MinionFakePlayer minion) { + return false; + } + + public static boolean canMinionDespawnMobs(MinionFakePlayer minion) { + return false; + } +} diff --git a/src/main/java/io/github/skippyall/minions/module/ModuleItem.java b/src/main/java/io/github/skippyall/minions/module/ModuleItem.java new file mode 100644 index 0000000..070a65f --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/module/ModuleItem.java @@ -0,0 +1,14 @@ +package io.github.skippyall.minions.module; + +import io.github.skippyall.minions.command.Command; +import io.github.skippyall.minions.program.block.CodeBlock; +import net.minecraft.text.Text; + +import java.util.List; + +public interface ModuleItem { + + List> getCodeBlocks(); + + List getCommands(); +} diff --git a/src/main/java/io/github/skippyall/minions/module/Modules.java b/src/main/java/io/github/skippyall/minions/module/Modules.java new file mode 100644 index 0000000..56bad67 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/module/Modules.java @@ -0,0 +1,20 @@ +package io.github.skippyall.minions.module; + +import net.minecraft.item.Item; +import net.minecraft.registry.Registries; +import net.minecraft.registry.Registry; +import net.minecraft.util.Identifier; + +public class Modules { + MoveModule MOVE = new MoveModule(); + + public static void register() { + ChatModule.registerMe(); + MountModule.registerMe(); + MoveModule.registerMe(); + } + + public static T register(Identifier id, T item) { + return Registry.register(Registries.ITEM, id, item); + } +} diff --git a/src/main/java/io/github/skippyall/minions/module/MountModule.java b/src/main/java/io/github/skippyall/minions/module/MountModule.java new file mode 100644 index 0000000..dfd4de4 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/module/MountModule.java @@ -0,0 +1,24 @@ +package io.github.skippyall.minions.module; + +import io.github.skippyall.minions.Minions; +import io.github.skippyall.minions.command.SimpleCommand; +import net.minecraft.item.Items; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +import java.util.ArrayList; +import java.util.Arrays; + +import static io.github.skippyall.minions.module.Modules.register; + +public class MountModule { + public static final SimpleModuleItem MOUNT_MODULE = register(Identifier.of(Minions.MOD_ID, "mount_module"), + new SimpleModuleItem(new ArrayList<>(), Arrays.asList( + new SimpleCommand(Text.of("Mount"), Text.of("Mount the minion to the nearest mountable Entity"), Items.MINECART, (player, minion) -> minion.getMinionActionPack().mount(true)), + new SimpleCommand(Text.of("Dismount"), Text.of("Dismount the minion"), Items.BARRIER, (player, minion) -> minion.getMinionActionPack().dismount()) + ), Items.MINECART) + ); + + public static void registerMe() {} + +} diff --git a/src/main/java/io/github/skippyall/minions/module/MoveModule.java b/src/main/java/io/github/skippyall/minions/module/MoveModule.java new file mode 100644 index 0000000..53dbe65 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/module/MoveModule.java @@ -0,0 +1,54 @@ +package io.github.skippyall.minions.module; + +import io.github.skippyall.minions.Minions; +import io.github.skippyall.minions.command.SimpleCommand; +import io.github.skippyall.minions.input.TextInput; +import net.minecraft.item.Items; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +import java.util.List; + +import static io.github.skippyall.minions.module.Modules.register; + +public class MoveModule { + public static final SimpleCommand WALK_COMMAND = new SimpleCommand(Text.literal("Walk"), Text.literal("Walk a specific amount of blocks forward"), Items.IRON_BOOTS, (player, minion) -> { + TextInput.inputText(player, Text.literal("Amount of Blocks"), "1") + .thenAccept(string -> { + try { + float blocks = Float.parseFloat(string); + minion.moveForward(blocks); + } catch (NumberFormatException e) { + player.sendMessage(Text.literal("No valid number")); + } + }); + }); + + public static final SimpleCommand TURN_RIGHT_COMMAND = new SimpleCommand(Text.literal("Turn Right"), Text.literal("Turn a specific amount of degrees right"), Items.COMPASS, ((player, minion) -> { + TextInput.inputText(player, Text.literal("Degrees"), "90") + .thenAccept(string -> { + try { + float degrees = Float.parseFloat(string); + minion.getMinionActionPack().turn(degrees, 0); + } catch (NumberFormatException e) { + player.sendMessage(Text.literal("No valid number")); + } + }); + })); + + public static final SimpleCommand TURN_LEFT_COMMAND = new SimpleCommand(Text.literal("Turn Left"), Text.literal("Turn a specific amount of degrees left"), Items.COMPASS, ((player, minion) -> { + TextInput.inputText(player, Text.literal("Degrees"), "90") + .thenAccept(string -> { + try { + float degrees = Float.parseFloat(string); + minion.getMinionActionPack().turn(-degrees, 0); + } catch (NumberFormatException e) { + player.sendMessage(Text.literal("No valid number")); + } + }); + })); + + public static final SimpleModuleItem MOVE_MODULE = register(Identifier.of(Minions.MOD_ID, "move_module"), new SimpleModuleItem(List.of(), List.of(WALK_COMMAND, TURN_RIGHT_COMMAND, TURN_LEFT_COMMAND), Items.IRON_BOOTS)); + + public static void registerMe() {} +} diff --git a/src/main/java/io/github/skippyall/minions/module/SimpleModuleItem.java b/src/main/java/io/github/skippyall/minions/module/SimpleModuleItem.java new file mode 100644 index 0000000..b815fe4 --- /dev/null +++ b/src/main/java/io/github/skippyall/minions/module/SimpleModuleItem.java @@ -0,0 +1,39 @@ +package io.github.skippyall.minions.module; + +import eu.pb4.polymer.core.api.item.PolymerItem; +import io.github.skippyall.minions.command.Command; +import io.github.skippyall.minions.program.block.CodeBlock; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.server.network.ServerPlayerEntity; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class SimpleModuleItem extends Item implements PolymerItem, ModuleItem { + private final List> codeBlocks; + private final List commands; + private final Item vanillaItem; + + public SimpleModuleItem(List> codeBlocks, List commands, Item vanillaItem) { + super(new Item.Settings().maxCount(1)); + this.codeBlocks = codeBlocks; + this.commands = commands; + this.vanillaItem = vanillaItem; + } + + @Override + public List> getCodeBlocks() { + return codeBlocks; + } + + @Override + public List getCommands() { + return commands; + } + + @Override + public Item getPolymerItem(ItemStack itemStack, @Nullable ServerPlayerEntity player) { + return vanillaItem; + } +} diff --git a/src/main/java/io/github/skippyall/minions/program/module/Module.java b/src/main/java/io/github/skippyall/minions/program/module/Module.java deleted file mode 100644 index 4168af8..0000000 --- a/src/main/java/io/github/skippyall/minions/program/module/Module.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.github.skippyall.minions.program.module; - -import eu.pb4.polymer.core.api.item.PolymerItem; -import io.github.skippyall.minions.program.block.CodeBlock; -import net.minecraft.item.Item; - -import java.util.List; - -public abstract class Module extends Item implements PolymerItem { - private final String name; - public Module(String name) { - super(new Item.Settings().maxCount(1)); - this.name = name; - } - - public String getModuleName() { - return name; - } - - public abstract List> getCodeBlocks(); -} diff --git a/src/main/java/io/github/skippyall/minions/program/module/Modules.java b/src/main/java/io/github/skippyall/minions/program/module/Modules.java deleted file mode 100644 index ba21ef3..0000000 --- a/src/main/java/io/github/skippyall/minions/program/module/Modules.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.github.skippyall.minions.program.module; - -public class Modules { - MoveModule MOVE = new MoveModule(); -} diff --git a/src/main/java/io/github/skippyall/minions/program/module/MoveModule.java b/src/main/java/io/github/skippyall/minions/program/module/MoveModule.java deleted file mode 100644 index 3ff8e2f..0000000 --- a/src/main/java/io/github/skippyall/minions/program/module/MoveModule.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.skippyall.minions.program.module; - -import io.github.skippyall.minions.program.block.CodeBlock; -import io.github.skippyall.minions.program.block.CodeBlocks; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.server.network.ServerPlayerEntity; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -public class MoveModule extends Module { - MoveModule() { - super("Movement"); - } - - public List> getCodeBlocks() { - List> codeBlocks = new ArrayList<>(); - codeBlocks.add(CodeBlocks.GO); - return codeBlocks; - } - - @Override - public Item getPolymerItem(ItemStack itemStack, @Nullable ServerPlayerEntity player) { - return Items.PURPLE_GLAZED_TERRACOTTA; - } -} diff --git a/src/main/resources/data/minions/recipe/basic_upgrade.json b/src/main/resources/data/minions/recipe/basic_upgrade.json new file mode 100644 index 0000000..adf3a53 --- /dev/null +++ b/src/main/resources/data/minions/recipe/basic_upgrade.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "RGR", + "GDG", + "RGR" + ], + "key": { + "R": { + "item":"minecraft:redstone_block" + }, + "G": { + "item": "minecraft:gold_ingot" + }, + "D": { + "item": "minecraft:diamond_block" + } + }, + "result": { + "id": "minions:basic_upgrade_base", + "count": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/data/minions/recipe/minion.json b/src/main/resources/data/minions/recipe/minion.json index 4db1b12..8cd6552 100644 --- a/src/main/resources/data/minions/recipe/minion.json +++ b/src/main/resources/data/minions/recipe/minion.json @@ -2,14 +2,22 @@ "type": "minecraft:crafting_shaped", "pattern": [ " H ", - "SAS", + "RAR", " L " ], "key": { - "H": "#minions:heads", - "S": "minecraft:stick", - "A": "minecraft:armor_stand", - "L": "minecraft:lodestone" + "H": { + "tag": "minions:heads" + }, + "R": { + "item": "minecraft:redstone_torch" + }, + "A": { + "item": "minecraft:armor_stand" + }, + "L": { + "item":"minecraft:lodestone" + } }, "result": { "id": "minions:minion", diff --git a/src/main/resources/data/minions/recipe/mount_upgrade.json b/src/main/resources/data/minions/recipe/mount_upgrade.json new file mode 100644 index 0000000..d3c5327 --- /dev/null +++ b/src/main/resources/data/minions/recipe/mount_upgrade.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:smithing_transform", + "base": { + "item": "minions:basic_upgrade_base" + }, + "addition": { + "item": "minecraft:minecart" + }, + "template": { + "item": "minecraft:netherite_upgrade_smithing_template" + }, + "result": { + "id": "minions:mount_module" + } +} \ No newline at end of file diff --git a/src/main/resources/data/minions/recipe/move_upgrade.json b/src/main/resources/data/minions/recipe/move_upgrade.json new file mode 100644 index 0000000..94d10b1 --- /dev/null +++ b/src/main/resources/data/minions/recipe/move_upgrade.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:smithing_transform", + "base": { + "item": "minions:basic_upgrade_base" + }, + "addition": { + "item": "minecraft:iron_boots" + }, + "template": { + "item": "minecraft:netherite_upgrade_smithing_template" + }, + "result": { + "id": "minions:move_module" + } +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 1802e31..5bef44e 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -26,8 +26,9 @@ "minions.mixins.json" ], "depends": { - "fabricloader": ">=${loader_version}", + "fabricloader": "*", "fabric": "*", - "minecraft": "${minecraft_version}" + "minecraft": "~1.21", + "polymer-core": "*" } } diff --git a/src/main/resources/minions.mixins.json b/src/main/resources/minions.mixins.json index ee4de1e..fbe4f6e 100644 --- a/src/main/resources/minions.mixins.json +++ b/src/main/resources/minions.mixins.json @@ -8,12 +8,15 @@ "ConnectionMixin", "Debug2Mixin", "DebugMixin", + "EntityAccessor", "GameProfileMixin", "MinecraftServerMixin", + "MobEntityMixin", "PlayerListEntryS2CPacket$EntryMixin", "PlayerListMixin", "ServerPlayerMixin", - "ServerPlayNetworkHandlerMixin" + "ServerPlayNetworkHandlerMixin", + "SpawnHelperMixin" ], "client": [], "server": [], diff --git a/src/main/resources/r.0.-1.mca b/src/main/resources/r.0.-1.mca deleted file mode 100644 index 3db6a5a..0000000 Binary files a/src/main/resources/r.0.-1.mca and /dev/null differ