package com.hypixel.hytale.server.npc.commands; import com.hypixel.hytale.component.Component; import com.hypixel.hytale.component.ComponentType; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.component.RemoveReason; import com.hypixel.hytale.component.Store; import com.hypixel.hytale.math.vector.Vector3d; import com.hypixel.hytale.math.vector.Vector3f; import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.command.system.CommandContext; import com.hypixel.hytale.server.core.command.system.arguments.system.FlagArg; import com.hypixel.hytale.server.core.command.system.arguments.system.OptionalArg; import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes; import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand; import com.hypixel.hytale.server.core.entity.UUIDComponent; import com.hypixel.hytale.server.core.entity.group.EntityGroup; import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; import com.hypixel.hytale.server.core.universe.PlayerRef; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.flock.FlockPlugin; import com.hypixel.hytale.server.npc.NPCPlugin; import com.hypixel.hytale.server.npc.entities.NPCEntity; import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectListIterator; import java.util.UUID; import java.util.logging.Level; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class NPCRunTestsCommand extends AbstractPlayerCommand { @Nonnull private static final Message MESSAGE_COMMANDS_NPC_RUN_TESTS_SPECIFY_ROLES = Message.translation("server.commands.npc.runtests.specifyroles"); @Nonnull private final OptionalArg rolesArg = this.withOptionalArg("roles", "server.commands.npc.runtests.roles.desc", ArgTypes.STRING); @Nonnull private final FlagArg presetArg = this.withFlagArg("preset", "server.commands.npc.runtests.preset.desc"); @Nonnull private final FlagArg passArg = this.withFlagArg("pass", "server.commands.npc.runtests.pass.desc"); @Nonnull private final FlagArg failArg = this.withFlagArg("fail", "server.commands.npc.runtests.fail.desc"); @Nonnull private final FlagArg abortArg = this.withFlagArg("abort", "server.commands.npc.runtests.abort.desc"); public NPCRunTestsCommand() { super("runtests", "server.commands.npc.runtests.desc"); } @Override protected void execute( @Nonnull CommandContext context, @Nonnull Store store, @Nonnull Ref ref, @Nonnull PlayerRef playerRef, @Nonnull World world ) { NPCRunTestsCommand.NPCTestData testDataComponent = store.ensureAndGetComponent(ref, NPCRunTestsCommand.NPCTestData.getComponentType()); TransformComponent playerTransformComponent = store.getComponent(ref, TransformComponent.getComponentType()); assert playerTransformComponent != null; if (!testDataComponent.npcRoles.isEmpty()) { if (this.passArg.get(context)) { setNextRole(testDataComponent, ref, store, world); return; } if (this.failArg.get(context)) { testDataComponent.failedRoles.add(testDataComponent.npcRoles.getInt(testDataComponent.index)); setNextRole(testDataComponent, ref, store, world); return; } if (this.abortArg.get(context)) { reportResults(ref, testDataComponent, store); Ref npcRef = world.getEntityRef(testDataComponent.targetUUID); if (npcRef != null) { cleanupNPC(npcRef, store); } store.removeComponent(ref, NPCRunTestsCommand.NPCTestData.getComponentType()); return; } } String[] roles; if (this.presetArg.get(context)) { roles = NPCPlugin.get().getPresetCoverageTestNPCs(); } else { if (!this.rolesArg.provided(context)) { context.sendMessage(MESSAGE_COMMANDS_NPC_RUN_TESTS_SPECIFY_ROLES); store.removeComponent(ref, NPCRunTestsCommand.NPCTestData.getComponentType()); return; } String roleString = this.rolesArg.get(context); if (roleString == null || roleString.isEmpty()) { context.sendMessage(MESSAGE_COMMANDS_NPC_RUN_TESTS_SPECIFY_ROLES); store.removeComponent(ref, NPCRunTestsCommand.NPCTestData.getComponentType()); return; } roles = roleString.split(","); } for (String role : roles) { int flockSize; try { int idx = role.indexOf(35); flockSize = idx < 0 ? 1 : Integer.parseInt(role.substring(idx + 1)); if (idx > 0) { role = role.substring(0, idx); } } catch (NumberFormatException var15) { context.sendMessage(Message.translation("server.commands.npc.runtests.invalidflocksize").param("role", role)); continue; } int builderIndex = NPCPlugin.get().getIndex(role); if (builderIndex == Integer.MIN_VALUE) { context.sendMessage(Message.translation("server.commands.npc.spawn.templateNotFound").param("template", role)); } else { testDataComponent.npcRoles.add(builderIndex); testDataComponent.flockSizes.add(flockSize); } } if (testDataComponent.targetUUID == null) { spawnNPC(ref, testDataComponent, 0, playerTransformComponent.getPosition(), playerTransformComponent.getRotation(), store); } } private static void setNextRole( @Nonnull NPCRunTestsCommand.NPCTestData testData, @Nonnull Ref reference, @Nonnull Store store, @Nonnull World world ) { Ref npcReference = world.getEntityRef(testData.targetUUID); testData.index++; if (testData.index >= testData.npcRoles.size()) { reportResults(reference, testData, store); if (npcReference != null) { cleanupNPC(npcReference, store); } store.removeComponent(reference, NPCRunTestsCommand.NPCTestData.getComponentType()); } else { Vector3d position; Vector3f rotation; if (npcReference != null) { TransformComponent npcTransformComponent = store.getComponent(npcReference, TransformComponent.getComponentType()); assert npcTransformComponent != null; position = npcTransformComponent.getPosition(); rotation = npcTransformComponent.getRotation(); cleanupNPC(npcReference, store); } else { TransformComponent transformComponent = store.getComponent(reference, TransformComponent.getComponentType()); assert transformComponent != null; position = transformComponent.getPosition(); rotation = transformComponent.getRotation(); } spawnNPC(reference, testData, testData.index, position, rotation, store); } } private static void cleanupNPC(@Nonnull Ref ref, @Nonnull Store store) { Ref flockReference = FlockPlugin.getFlockReference(ref, store); if (flockReference != null) { ObjectArrayList> members = new ObjectArrayList(); EntityGroup entityGroupComponent = store.getComponent(flockReference, EntityGroup.getComponentType()); assert entityGroupComponent != null; entityGroupComponent.forEachMember((index, memberx, list) -> list.add(memberx), members); ObjectListIterator var5 = members.iterator(); while (var5.hasNext()) { Ref member = (Ref)var5.next(); store.removeEntity(member, RemoveReason.REMOVE); } } store.removeEntity(ref, RemoveReason.REMOVE); } private static void spawnNPC( @Nonnull Ref playerReference, @Nonnull NPCRunTestsCommand.NPCTestData testData, int index, @Nonnull Vector3d position, @Nullable Vector3f rotation, @Nonnull Store store ) { Pair, NPCEntity> npcPair = NPCPlugin.get().spawnEntity(store, testData.npcRoles.getInt(index), position, rotation, null, null); Ref npcRef = (Ref)npcPair.first(); NPCEntity npcComponent = (NPCEntity)npcPair.second(); int flockSize = testData.flockSizes.getInt(index); if (flockSize > 1) { TransformComponent npcTransformComponent = store.getComponent(npcRef, TransformComponent.getComponentType()); assert npcTransformComponent != null; FlockPlugin.trySpawnFlock( npcRef, npcComponent, store, npcComponent.getRoleIndex(), npcTransformComponent.getPosition(), npcTransformComponent.getRotation(), flockSize, null ); } String roleName = npcComponent.getRoleName(); PlayerRef playerRefComponent = store.getComponent(playerReference, PlayerRef.getComponentType()); assert playerRefComponent != null; playerRefComponent.sendMessage( Message.translation("server.commands.npc.runtests.testing") .param("role", roleName) .insert("\n") .insert(Message.translation("server.npc.tests." + roleName)) ); UUIDComponent npcUUIDComponent = store.getComponent(npcRef, UUIDComponent.getComponentType()); assert npcUUIDComponent != null; testData.targetUUID = npcUUIDComponent.getUuid(); } private static void reportResults( @Nonnull Ref playerReference, @Nonnull NPCRunTestsCommand.NPCTestData testData, @Nonnull Store store ) { NPCPlugin npcPlugin = NPCPlugin.get(); Message msg = Message.translation("server.commands.npc.runtests.results"); for (int i = 0; i < testData.npcRoles.size(); i++) { int index = testData.npcRoles.getInt(i); msg.insert(" " + npcPlugin.getName(index) + ": "); String result = i >= testData.index ? "server.commands.npc.runtests.notrun" : (testData.failedRoles.contains(index) ? "server.commands.npc.runtests.fail" : "server.commands.npc.runtests.pass"); msg.insert(Message.translation(result)); msg.insert("\n"); } PlayerRef playerRef = store.getComponent(playerReference, PlayerRef.getComponentType()); assert playerRef != null; playerRef.sendMessage(msg); npcPlugin.getLogger().at(Level.INFO).log(msg.getRawText()); } public static class NPCTestData implements Component { private final IntList npcRoles = new IntArrayList(); private final IntList flockSizes = new IntArrayList(); private final IntSet failedRoles = new IntOpenHashSet(); private int index; private UUID targetUUID; public static ComponentType getComponentType() { return NPCPlugin.get().getNpcTestDataComponentType(); } @Nonnull @Override public Component clone() { NPCRunTestsCommand.NPCTestData data = new NPCRunTestsCommand.NPCTestData(); data.npcRoles.addAll(this.npcRoles); data.index = this.index; data.failedRoles.addAll(this.failedRoles); return data; } } }