From bed859c8c4a95f79c581cba77e3225bd10f1549e Mon Sep 17 00:00:00 2001 From: Ziggy Date: Sun, 15 Nov 2020 18:45:38 +0100 Subject: [PATCH] /createNPC command #37 --- .../world/spawn/CreateSpawnIntent.java | 47 ++++ .../loader/npc/NpcStaticSpawnLoader.java | 67 +++-- .../callbacks/admin/CmdCreateNpc.java | 117 ++++++++ .../support/npc/spawn/SimpleSpawnInfo.java | 264 ++++++++++++++++++ .../support/npc/spawn/SpawnInfo.java | 79 ++++++ .../resources/support/npc/spawn/Spawner.kt | 4 +- .../support/objects/radial/RadialHandler.java | 1 + .../objects/radial/object/SpawnerRadial.java | 58 ++++ .../commands/CommandExecutionService.java | 1 + .../support/npc/spawn/SpawnerService.kt | 56 +++- 10 files changed, 661 insertions(+), 33 deletions(-) create mode 100644 src/main/java/com/projectswg/holocore/intents/gameplay/world/spawn/CreateSpawnIntent.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/admin/CmdCreateNpc.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/npc/spawn/SimpleSpawnInfo.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/npc/spawn/SpawnInfo.java create mode 100644 src/main/java/com/projectswg/holocore/resources/support/objects/radial/object/SpawnerRadial.java diff --git a/src/main/java/com/projectswg/holocore/intents/gameplay/world/spawn/CreateSpawnIntent.java b/src/main/java/com/projectswg/holocore/intents/gameplay/world/spawn/CreateSpawnIntent.java new file mode 100644 index 000000000..cddbceb55 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/intents/gameplay/world/spawn/CreateSpawnIntent.java @@ -0,0 +1,47 @@ +/*********************************************************************************** + * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.intents.gameplay.world.spawn; + +import com.projectswg.holocore.resources.support.npc.spawn.SpawnInfo; +import me.joshlarson.jlcommon.control.Intent; +import org.jetbrains.annotations.NotNull; + +public class CreateSpawnIntent extends Intent { + private final SpawnInfo spawnInfo; + + private CreateSpawnIntent(@NotNull SpawnInfo spawnInfo) { + this.spawnInfo = spawnInfo; + } + + public SpawnInfo getSpawnInfo() { + return spawnInfo; + } + + public static void broadcast(@NotNull SpawnInfo spawnInfo) { + new CreateSpawnIntent(spawnInfo).broadcast(); + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/npc/NpcStaticSpawnLoader.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/npc/NpcStaticSpawnLoader.java index 647ab2514..d125a27cb 100644 --- a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/npc/NpcStaticSpawnLoader.java +++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/npc/NpcStaticSpawnLoader.java @@ -30,6 +30,7 @@ import com.projectswg.common.data.location.Terrain; import com.projectswg.holocore.resources.support.data.server_info.SdbLoader; import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet; import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader; +import com.projectswg.holocore.resources.support.npc.spawn.SpawnInfo; import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureDifficulty; import com.projectswg.holocore.resources.support.objects.swg.custom.AIBehavior; import me.joshlarson.jlcommon.log.Log; @@ -71,7 +72,7 @@ public final class NpcStaticSpawnLoader extends DataLoader { INVULNERABLE } - public static class StaticSpawnInfo { + public static class StaticSpawnInfo implements SpawnInfo { private final String id; private final Terrain terrain; @@ -146,90 +147,112 @@ public final class NpcStaticSpawnLoader extends DataLoader { } } + @Override public String getId() { return id; } - + + @Override public Terrain getTerrain() { return terrain; } - + + @Override public double getX() { return x; } - + + @Override public double getY() { return y; } - + + @Override public double getZ() { return z; } - + + @Override public int getHeading() { return heading; } - + + @Override public int getCellId() { return cellId; } - + + @Override public String getSpawnerType() { return spawnerType; } - + + @Override public String getNpcId() { return npcId; } - + + @Override public SpawnerFlag getSpawnerFlag() { return spawnerFlag; } - + + @Override public CreatureDifficulty getDifficulty() { return difficulty; } - + + @Override public int getMinLevel() { return minLevel; } - + + @Override public int getMaxLevel() { return maxLevel; } - + + @Override public String getBuildingId() { return buildingId; } - + + @Override public String getMood() { return mood; } - + + @Override public AIBehavior getBehavior() { return behavior; } - + + @Override public String getPatrolId() { return patrolId; } - + + @Override public PatrolFormation getPatrolFormation() { return patrolFormation; } - + + @Override public int getLoiterRadius() { return loiterRadius; } - + + @Override public int getMinSpawnTime() { return minSpawnTime; } - + + @Override public int getMaxSpawnTime() { return maxSpawnTime; } - + + @Override public int getAmount() { return amount; } diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/admin/CmdCreateNpc.java b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/admin/CmdCreateNpc.java new file mode 100644 index 000000000..7d8ae2509 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/admin/CmdCreateNpc.java @@ -0,0 +1,117 @@ +/*********************************************************************************** + * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.global.commands.callbacks.admin; + +import com.projectswg.holocore.intents.gameplay.world.spawn.CreateSpawnIntent; +import com.projectswg.holocore.intents.support.global.chat.SystemMessageIntent; +import com.projectswg.holocore.resources.support.data.server_info.loader.npc.NpcStaticSpawnLoader; +import com.projectswg.holocore.resources.support.global.commands.ICmdCallback; +import com.projectswg.holocore.resources.support.global.player.AccessLevel; +import com.projectswg.holocore.resources.support.global.player.Player; +import com.projectswg.holocore.resources.support.npc.spawn.SimpleSpawnInfo; +import com.projectswg.holocore.resources.support.npc.spawn.SpawnerType; +import com.projectswg.holocore.resources.support.objects.swg.SWGObject; +import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject; +import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureDifficulty; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class CmdCreateNpc implements ICmdCallback { + @Override + public void execute(@NotNull Player player, @Nullable SWGObject target, @NotNull String args) { + if (player.getAccessLevel() == AccessLevel.PLAYER) { + SystemMessageIntent.broadcastPersonal(player, "Players cannot use this command :("); + return; + } + + String[] commandArgs = args.split(" "); + String npcId = determineNpcId(commandArgs); + CreatureDifficulty difficulty = determineDifficulty(commandArgs); + int combatLevel = determineCombatLevel(commandArgs); + + spawnNPC(player, npcId, difficulty, combatLevel); + } + + private String determineNpcId(String[] commandArgs) { + return commandArgs[0]; + } + + private CreatureDifficulty determineDifficulty(String[] commandArgs) { + String arg = commandArgs[1]; + + switch (arg) { + case "b": return CreatureDifficulty.BOSS; + case "e": return CreatureDifficulty.ELITE; + default: + case "n": return CreatureDifficulty.NORMAL; + } + } + + private int determineCombatLevel(String[] commandArgs) { + return Integer.parseInt(commandArgs[2]); + } + + private void spawnNPC(Player player, String npcId, CreatureDifficulty difficulty, int combatLevel) { + CellObject cell = (CellObject) player.getCreatureObject().getParent(); + SimpleSpawnInfo spawnInfo = SimpleSpawnInfo.builder() + .withNpcId(npcId) + .withDifficulty(difficulty) + .withMinLevel(combatLevel) + .withMaxLevel(combatLevel) + .withLocation(player.getCreatureObject().getLocation()) + .withSpawnerFlag(NpcStaticSpawnLoader.SpawnerFlag.ATTACKABLE) + .withSpawnerType(SpawnerType.EGG) + .withBuildingId(determineBuildoutTag(cell)) + .withCellId(determineCellId(cell)) + .build(); + + CreateSpawnIntent.broadcast(spawnInfo); + } + + private String determineBuildoutTag(CellObject cell) { + if (cell == null) { + return ""; + } + + SWGObject building = cell.getParent(); + + if (building == null) { + return ""; + } + + return building.getBuildoutTag(); + } + + private int determineCellId(CellObject cell) { + if (cell == null) { + return 0; + } + + + return cell.getNumber(); + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/npc/spawn/SimpleSpawnInfo.java b/src/main/java/com/projectswg/holocore/resources/support/npc/spawn/SimpleSpawnInfo.java new file mode 100644 index 000000000..172e100ad --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/npc/spawn/SimpleSpawnInfo.java @@ -0,0 +1,264 @@ +/*********************************************************************************** + * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.npc.spawn; + +import com.projectswg.common.data.location.Location; +import com.projectswg.common.data.location.Terrain; +import com.projectswg.holocore.resources.support.data.server_info.loader.npc.NpcStaticSpawnLoader; +import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureDifficulty; +import com.projectswg.holocore.resources.support.objects.swg.custom.AIBehavior; + +import java.util.concurrent.TimeUnit; + +public class SimpleSpawnInfo implements SpawnInfo { + + private String id; + private Terrain terrain; + private double x; + private double y; + private double z; + private int heading; + private int cellId; + private String spawnerType; + private String npcId; + private NpcStaticSpawnLoader.SpawnerFlag spawnerFlag; + private CreatureDifficulty difficulty; + private int minLevel; + private int maxLevel; + private String buildingId; + private String mood; + private AIBehavior behavior; + private String patrolId; + private NpcStaticSpawnLoader.PatrolFormation patrolFormation; + private int loiterRadius; + private int minSpawnTime; + private int maxSpawnTime; + private int amount; + + private SimpleSpawnInfo() { + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public String getId() { + return id; + } + + @Override + public Terrain getTerrain() { + return terrain; + } + + @Override + public double getX() { + return x; + } + + @Override + public double getY() { + return y; + } + + @Override + public double getZ() { + return z; + } + + @Override + public int getHeading() { + return heading; + } + + @Override + public int getCellId() { + return cellId; + } + + @Override + public String getSpawnerType() { + return spawnerType; + } + + @Override + public String getNpcId() { + return npcId; + } + + @Override + public NpcStaticSpawnLoader.SpawnerFlag getSpawnerFlag() { + return spawnerFlag; + } + + @Override + public CreatureDifficulty getDifficulty() { + return difficulty; + } + + @Override + public int getMinLevel() { + return minLevel; + } + + @Override + public int getMaxLevel() { + return maxLevel; + } + + @Override + public String getBuildingId() { + return buildingId; + } + + @Override + public String getMood() { + return mood; + } + + @Override + public AIBehavior getBehavior() { + return behavior; + } + + @Override + public String getPatrolId() { + return patrolId; + } + + @Override + public NpcStaticSpawnLoader.PatrolFormation getPatrolFormation() { + return patrolFormation; + } + + @Override + public int getLoiterRadius() { + return loiterRadius; + } + + @Override + public int getMinSpawnTime() { + return minSpawnTime; + } + + @Override + public int getMaxSpawnTime() { + return maxSpawnTime; + } + + @Override + public int getAmount() { + return amount; + } + + public static class Builder { + + private final SimpleSpawnInfo info; + + private Builder() { + info = new SimpleSpawnInfo(); + info.id = "simple"; + info.behavior = AIBehavior.IDLE; + info.mood = ""; + info.spawnerFlag = NpcStaticSpawnLoader.SpawnerFlag.INVULNERABLE; + info.buildingId = ""; + info.amount = 1; + info.minSpawnTime = (int) TimeUnit.SECONDS.convert(8, TimeUnit.MINUTES); + info.maxSpawnTime = (int) TimeUnit.SECONDS.convert(12, TimeUnit.MINUTES); + } + + public Builder withNpcId(String npcId) { + info.npcId = npcId; + info.patrolId = ""; + + return this; + } + + public Builder withLocation(Location location) { + info.x = location.getX(); + info.y = location.getY(); + info.z = location.getZ(); + info.terrain = location.getTerrain(); + info.heading = (int) location.getYaw(); + + return this; + } + + public Builder withBuildingId(String buildingId) { + info.buildingId = buildingId; + + return this; + } + + public Builder withCellId(int cellId) { + info.cellId = cellId; + + return this; + } + + public Builder withDifficulty(CreatureDifficulty difficulty) { + info.difficulty = difficulty; + + return this; + } + + public Builder withMinLevel(int minLevel) { + info.minLevel = minLevel; + + return this; + } + + public Builder withMaxLevel(int maxLevel) { + info.maxLevel = maxLevel; + + return this; + } + + public Builder withSpawnerFlag(NpcStaticSpawnLoader.SpawnerFlag spawnerFlag) { + info.spawnerFlag = spawnerFlag; + + return this; + } + + public Builder withSpawnerType(SpawnerType spawnerType) { + info.spawnerType = spawnerType.name(); + + return this; + } + + public Builder withAmount(int amount) { + info.amount = amount; + + return this; + } + + public SimpleSpawnInfo build() { + return info; + } + } +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/npc/spawn/SpawnInfo.java b/src/main/java/com/projectswg/holocore/resources/support/npc/spawn/SpawnInfo.java new file mode 100644 index 000000000..a76c79f26 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/npc/spawn/SpawnInfo.java @@ -0,0 +1,79 @@ +/*********************************************************************************** + * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.npc.spawn; + +import com.projectswg.common.data.location.Terrain; +import com.projectswg.holocore.resources.support.data.server_info.loader.npc.NpcStaticSpawnLoader; +import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureDifficulty; +import com.projectswg.holocore.resources.support.objects.swg.custom.AIBehavior; + +public interface SpawnInfo { + String getId(); + + Terrain getTerrain(); + + double getX(); + + double getY(); + + double getZ(); + + int getHeading(); + + int getCellId(); + + String getSpawnerType(); + + String getNpcId(); + + NpcStaticSpawnLoader.SpawnerFlag getSpawnerFlag(); + + CreatureDifficulty getDifficulty(); + + int getMinLevel(); + + int getMaxLevel(); + + String getBuildingId(); + + String getMood(); + + AIBehavior getBehavior(); + + String getPatrolId(); + + NpcStaticSpawnLoader.PatrolFormation getPatrolFormation(); + + int getLoiterRadius(); + + int getMinSpawnTime(); + + int getMaxSpawnTime(); + + int getAmount(); + +} diff --git a/src/main/java/com/projectswg/holocore/resources/support/npc/spawn/Spawner.kt b/src/main/java/com/projectswg/holocore/resources/support/npc/spawn/Spawner.kt index 349965df8..dfb2e0f82 100644 --- a/src/main/java/com/projectswg/holocore/resources/support/npc/spawn/Spawner.kt +++ b/src/main/java/com/projectswg/holocore/resources/support/npc/spawn/Spawner.kt @@ -44,9 +44,9 @@ import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.ThreadLocalRandom import java.util.stream.Collectors -class Spawner(spawn: StaticSpawnInfo, egg: SWGObject) { +class Spawner(spawn: SpawnInfo, egg: SWGObject) { - private val spawn: StaticSpawnInfo = Objects.requireNonNull(spawn, "spawn") + private val spawn: SpawnInfo = Objects.requireNonNull(spawn, "spawn") private val npc: NpcInfo = Objects.requireNonNull(DataLoader.npcs().getNpc(spawn.npcId), "Invalid npc id: " + spawn.npcId) private val npcsInternal = CopyOnWriteArrayList() diff --git a/src/main/java/com/projectswg/holocore/resources/support/objects/radial/RadialHandler.java b/src/main/java/com/projectswg/holocore/resources/support/objects/radial/RadialHandler.java index 13f0e6f0d..65a6a8b2a 100644 --- a/src/main/java/com/projectswg/holocore/resources/support/objects/radial/RadialHandler.java +++ b/src/main/java/com/projectswg/holocore/resources/support/objects/radial/RadialHandler.java @@ -112,6 +112,7 @@ public enum RadialHandler { registerHandler(RareLootService.EXCEPTIONAL_CHEST, new RareLootRadial()); registerHandler(RareLootService.LEGENDARY_CHEST, new RareLootRadial()); registerHandler(GameObjectType.GOT_COMPONENT_SABER_CRYSTAL, new TuneCrystalRadial()); + registerHandler("object/tangible/spawning/shared_spawn_egg.iff", new SpawnerRadial()); } private void initializeContainerRadials() { diff --git a/src/main/java/com/projectswg/holocore/resources/support/objects/radial/object/SpawnerRadial.java b/src/main/java/com/projectswg/holocore/resources/support/objects/radial/object/SpawnerRadial.java new file mode 100644 index 000000000..01791af78 --- /dev/null +++ b/src/main/java/com/projectswg/holocore/resources/support/objects/radial/object/SpawnerRadial.java @@ -0,0 +1,58 @@ +/*********************************************************************************** + * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * --------------------------------------------------------------------------------* + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + ***********************************************************************************/ +package com.projectswg.holocore.resources.support.objects.radial.object; + +import com.projectswg.common.data.radial.RadialItem; +import com.projectswg.common.data.radial.RadialOption; +import com.projectswg.holocore.resources.support.global.player.AccessLevel; +import com.projectswg.holocore.resources.support.global.player.Player; +import com.projectswg.holocore.resources.support.objects.radial.RadialHandlerInterface; +import com.projectswg.holocore.resources.support.objects.swg.SWGObject; + +import java.util.Collection; + +public class SpawnerRadial implements RadialHandlerInterface { + @Override + public void getOptions(Collection options, Player player, SWGObject target) { + if (isAllowedToDestroy(player)) { + options.add(RadialOption.create(RadialItem.ITEM_DESTROY)); + } + } + + @Override + public void handleSelection(Player player, SWGObject target, RadialItem selection) { + // The ITEM_DESTROY radial will cause the generic item destruction flow to be invoked + } + + private boolean isAllowedToDestroy(Player player) { + AccessLevel accessLevel = player.getAccessLevel(); + + // Players have no access + return accessLevel != AccessLevel.PLAYER; + } + +} diff --git a/src/main/java/com/projectswg/holocore/services/support/global/commands/CommandExecutionService.java b/src/main/java/com/projectswg/holocore/services/support/global/commands/CommandExecutionService.java index f4b5012fe..2659805e4 100644 --- a/src/main/java/com/projectswg/holocore/services/support/global/commands/CommandExecutionService.java +++ b/src/main/java/com/projectswg/holocore/services/support/global/commands/CommandExecutionService.java @@ -99,6 +99,7 @@ public class CommandExecutionService extends Service { registerCallback("dumpZoneInformation", CmdDumpZoneInformation::new); registerCallback("goto", CmdGoto::new); registerCallback("console_npc", CmdNpc::new); + registerCallback("createNPC", CmdCreateNpc::new); registerCallback("qatool", CmdQaTool::new); registerCallback("revertPlayerAppearance", CmdRevertPlayerAppearance::new); registerCallback("setGodMode", CmdSetGodMode::new); diff --git a/src/main/java/com/projectswg/holocore/services/support/npc/spawn/SpawnerService.kt b/src/main/java/com/projectswg/holocore/services/support/npc/spawn/SpawnerService.kt index 09bb85948..0121d60a2 100644 --- a/src/main/java/com/projectswg/holocore/services/support/npc/spawn/SpawnerService.kt +++ b/src/main/java/com/projectswg/holocore/services/support/npc/spawn/SpawnerService.kt @@ -31,16 +31,17 @@ import com.projectswg.common.data.location.Point3D import com.projectswg.common.network.packets.swg.zone.CreateClientPathMessage import com.projectswg.common.network.packets.swg.zone.DestroyClientPathMessage import com.projectswg.common.network.packets.swg.zone.object_controller.IntendedTarget +import com.projectswg.holocore.intents.gameplay.world.spawn.CreateSpawnIntent import com.projectswg.holocore.intents.support.global.network.InboundPacketIntent import com.projectswg.holocore.intents.support.global.zone.PlayerEventIntent import com.projectswg.holocore.intents.support.objects.swg.DestroyObjectIntent import com.projectswg.holocore.intents.support.objects.swg.ObjectCreatedIntent import com.projectswg.holocore.resources.support.data.server_info.StandardLog import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader -import com.projectswg.holocore.resources.support.data.server_info.loader.npc.NpcStaticSpawnLoader.StaticSpawnInfo import com.projectswg.holocore.resources.support.data.server_info.mongodb.PswgDatabase import com.projectswg.holocore.resources.support.global.player.PlayerEvent import com.projectswg.holocore.resources.support.npc.spawn.NPCCreator +import com.projectswg.holocore.resources.support.npc.spawn.SpawnInfo import com.projectswg.holocore.resources.support.npc.spawn.Spawner import com.projectswg.holocore.resources.support.npc.spawn.SpawnerType import com.projectswg.holocore.resources.support.objects.ObjectCreator @@ -112,20 +113,57 @@ class SpawnerService : Service() { @IntentHandler private fun handleDestroyObjectIntent(doi: DestroyObjectIntent) { - val destroyedObject = doi.getObject() as? AIObject ?: return - + val obj = doi.`object` + + if (isNPC(obj)) { + handleNPCDestroyed(obj) + } + + if (isSpawner(obj)) { + handleSpawnerDestroyed(obj) + } + } + + @IntentHandler + private fun handleCreateSpawnIntent(csi: CreateSpawnIntent) { + spawn(csi.spawnInfo) + } + + private fun isNPC(obj: SWGObject): Boolean { + return obj is AIObject + } + + private fun isSpawner(obj: SWGObject): Boolean { + return obj.getServerAttribute(ServerAttribute.EGG_SPAWNER) != null + } + + private fun handleNPCDestroyed(obj: SWGObject) { + val destroyedObject = obj as? AIObject ?: return + val spawner = destroyedObject.spawner - + if (spawner == null) { - Log.e("Killed AI object %s has no linked Spawner - it cannot respawn!", destroyedObject) + Log.i("Killed AI object %s has no linked Spawner - it will not respawn", destroyedObject) return } - + spawner.removeNPC(destroyedObject) + if (spawner.behavior != AIBehavior.PATROL || spawner.npcs.isEmpty()) executor.execute((spawner.respawnDelay * 1000).toLong()) { respawn(spawner) } } - + + private fun handleSpawnerDestroyed(obj: SWGObject) { + val spawner = obj.getServerAttribute(ServerAttribute.EGG_SPAWNER) as Spawner + + val npcs = spawner.npcs.toList() + + for (npc in npcs) { + npc.spawner = null // Prevents the NPC from respawning + DestroyObjectIntent.broadcast(npc) + } + } + private fun loadSpawners() { val startTime = StandardLog.onStartLoad("spawners") @@ -143,7 +181,7 @@ class SpawnerService : Service() { StandardLog.onEndLoad(count, "spawners", startTime) } - private fun spawn(spawn: StaticSpawnInfo) { + private fun spawn(spawn: SpawnInfo) { val egg = createEgg(spawn) val spawner = Spawner(spawn, egg) egg.setServerAttribute(ServerAttribute.EGG_SPAWNER, spawner) @@ -172,7 +210,7 @@ class SpawnerService : Service() { } } - private fun createEgg(spawn: StaticSpawnInfo): SWGObject { + private fun createEgg(spawn: SpawnInfo): SWGObject { val spawnerType = SpawnerType.valueOf(spawn.spawnerType) val egg = ObjectCreator.createObjectFromTemplate(spawnerType.objectTemplate) egg.containerPermissions = AdminPermissions.getPermissions()