Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions plugin.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
name: SimpleNPC
main: brokiem\snpc\SimpleNPC
version: 4.0.1-dev
version: 4.1.0-dev
api: 4.0.0
author: brokiem
authors:
- brokiem
- supercrafter333 # I hope that's okay :)

website: https://github.com/brokiem/SimpleNPC

Expand Down
5 changes: 4 additions & 1 deletion resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ max-look-distance: 8
enable-command-cooldown: true
# Coldown executing command when hit the NPC
# Default: 1.0 (float)
command-execute-cooldown: 1.0
command-execute-cooldown: 1.0

# Here you can choose the emote interval. 6-7 seconds are recommended.
emote-interval-seconds: 7
5 changes: 5 additions & 0 deletions src/brokiem/snpc/EventHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,9 @@ public function onMove(PlayerMoveEvent $event): void {
}
}
}

/*public function onWorldLoad(WorldLoadEvent $ev): void //TODO: not working!!
{
NPCManager::getInstance()->updateOldNPCs($ev->getWorld());
}*/
}
7 changes: 5 additions & 2 deletions src/brokiem/snpc/SimpleNPC.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use brokiem\snpc\entity\CustomHuman;
use brokiem\snpc\entity\WalkingHuman;
use brokiem\snpc\manager\NPCManager;
use brokiem\snpc\task\DoEmoteTask;
use brokiem\updatechecker\Promise;
use brokiem\updatechecker\UpdateChecker;
use EasyUI\Form;
Expand All @@ -41,7 +42,7 @@ class SimpleNPC extends PluginBase {
public array $lastHit = [];
public array $cachedUpdate = [];
public array $idPlayers = [];
private bool $isDev = true;
public const IS_DEV = true;

protected function onEnable(): void {
if (!class_exists(Form::class)) {
Expand All @@ -50,7 +51,7 @@ protected function onEnable(): void {
return;
}

if ($this->isDev) {
if (self::IS_DEV) {
$this->getLogger()->warning("You are using the Development version of SimpleNPC. The plugin will experience errors, crashes, or bugs. Only use this version if you are testing. Don't use the Dev version in production!");
}

Expand All @@ -63,6 +64,8 @@ protected function onEnable(): void {
$this->getServer()->getCommandMap()->registerAll("SimpleNPC", [new Commands("snpc", $this), new RcaCommand("rca", $this)]);
$this->getServer()->getPluginManager()->registerEvents(new EventHandler($this), $this);

$this->getScheduler()->scheduleRepeatingTask(new DoEmoteTask(), $this->getConfig()->get("emote-interval-seconds", 7) * 20);

$this->getScheduler()->scheduleRepeatingTask(new ClosureTask(function(): void {
UpdateChecker::checkUpdate($this->getDescription()->getName(), $promise = new Promise());

Expand Down
58 changes: 58 additions & 0 deletions src/brokiem/snpc/entity/CustomHuman.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,25 @@
use pocketmine\console\ConsoleCommandSender;
use pocketmine\entity\Human;
use pocketmine\nbt\NBT;
use pocketmine\nbt\NoSuchTagException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\protocol\EmotePacket;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;
use function in_array;

class CustomHuman extends Human {
protected $gravity = 0.0;

protected bool $canWalk = false;
protected bool $lookToPlayers;

protected string|null $clickEmoteId = null;

protected string|null $emoteId = null;

protected CommandManager $commandManager;

protected function initEntity(CompoundTag $nbt): void {
Expand All @@ -44,13 +51,21 @@ protected function initEntity(CompoundTag $nbt): void {
$this->setNameTagAlwaysVisible((bool)$nbt->getByte("ShowNametag", 1));
$this->setNameTagVisible((bool)$nbt->getByte("ShowNametag", 1));
$this->setScale($nbt->getFloat("Scale", 1));
try {
$this->setClickEmoteId($nbt->getString("ClickEmote") === "NULL" ? null : $nbt->getString("ClickEmote"));
} catch (NoSuchTagException) {}
try {
$this->setEmoteId($nbt->getString("Emote") === "NULL" ? null : $nbt->getString("Emote"));
} catch (NoSuchTagException) {}
}

public function saveNBT(): CompoundTag {
$nbt = parent::saveNBT();
$nbt->setFloat("Scale", $this->getScale()); //pm doesn't save this to the nbt
$nbt->setByte("EnableRotation", (int)$this->lookToPlayers);
$nbt->setByte("ShowNametag", (int)$this->isNameTagAlwaysVisible());
$nbt->setString("ClickEmote", $this->getClickEmoteId() === null ? "NULL" : $this->getClickEmoteId());
$nbt->setString("Emote", $this->getEmoteId() === null ? "NULL" : $this->getEmoteId());

$listTag = new ListTag([], NBT::TAG_String); //commands
foreach ($this->commandManager->getAll() as $command) {
Expand All @@ -60,6 +75,40 @@ public function saveNBT(): CompoundTag {
return $nbt;
}

/**
* @param string|null $clickEmoteId
*/
public function setClickEmoteId(?string $clickEmoteId): void
{
$this->clickEmoteId = $clickEmoteId;
$this->saveNBT();
}

/**
* @return string|null
*/
public function getClickEmoteId(): ?string
{
return $this->clickEmoteId === "NULL" ? null : $this->clickEmoteId;
}

/**
* @param string|null $emoteId
*/
public function setEmoteId(?string $emoteId): void
{
$this->emoteId = $emoteId;
$this->saveNBT();
}

/**
* @return string|null
*/
public function getEmoteId(): ?string
{
return $this->emoteId === "NULL" ? null : $this->emoteId;
}

public function despawn(Player $deletor = null): bool {
(new SNPCDeletionEvent($this, $deletor))->call();

Expand Down Expand Up @@ -104,6 +153,8 @@ public function interact(Player $player): void {
}

execute:
if ($this->getClickEmoteId() !== null)
$this->broadcastEmote($this->getClickEmoteId(), [$player]);
if (!empty($commands = $this->getCommandManager()->getAll())) {
foreach ($commands as $command) {
$plugin->getServer()->getCommandMap()->dispatch(new ConsoleCommandSender($player->getServer(), $plugin->getServer()->getLanguage()), str_replace("{player}", '"' . $player->getName() . '"', $command));
Expand Down Expand Up @@ -134,4 +185,11 @@ public function canLookToPlayers(): bool {
public function getCommandManager(): CommandManager {
return $this->commandManager;
}

public function broadcastEmote(string $emoteId, array|null $targets = null): void
{
if (!in_array($emoteId, EmoteIds::EMOTES)) return;

$this->server->broadcastPackets($targets ?? $this->getViewers(), [EmotePacket::create($this->getId(), $emoteId, EmotePacket::FLAG_SERVER)]);
}
}
110 changes: 110 additions & 0 deletions src/brokiem/snpc/entity/EmoteIds.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php

namespace brokiem\snpc\entity;

class EmoteIds
{

public const EMOTES = [
"Abduction?" => '18891e6c-bb3d-47f6-bc15-265605d86525',
"Acting Like a Dragon" => 'c2a47805-c792-4882-a56d-17c80b6c57a8',
"Ahh Choo!" => 'f9345ebb-4ba3-40e6-ad9b-6bfb10c92890',
"Airplane" => 'e7bb3d8c-811d-442a-bfc5-775556d05d7a',
"Anger Management" => 'a0b1a9f2-0ea4-48d0-8641-ada998beee4d',
"Ballerina Twirl" => '79452f7e-ffa0-470f-8283-f5063348471d',
"Big Chuckles" => '819f2f36-2a16-440c-8e46-94c6b003a2e0',
"Bored" => '7a314ecf-f94c-42c0-945f-76903c923808',
"Bow" => 'ddfa6f0e-88ca-46de-b189-2bd5b18e96a0',
"Breakdance" => '1dbaa006-0ec6-42c3-9440-a3bfa0c6fdbe',
"Calling a Dragon" => '9f5d4732-0513-4a0a-8ea2-b6b8d7587e74',
"Cartwheel" => '5cf9d5a3-6fa0-424e-8ae4-d1f877b836da',
"Chatting" => '59d9e78c-f0bb-4f14-9e9b-7ab4f58ffbf5',
"Cheer Routine" => '3d10a8c7-213c-4fbe-a208-a0f7990d5bbb',
"Chun-Li Spinning Kick" => 'af61c759-6252-431d-a7de-94d477cfb54c',
"Clicking Heels" => '495d686a-4cb3-4f0b-beb5-bebdcb95eed9',
"Cowpoke Dancin'" => 'f99ccd35-ebda-4122-b458-ff8c9f9a432f',
"DJing" => 'beb74219-e90c-46aa-8a4b-a1c175f6cab5',
"Dancing Like Rapunzel" => 'f15ceb56-6651-41c0-8bd5-087951204d81',
"Dancing Like Toothless" => 'a12252fa-4ec8-42e0-a7d0-d44fbc90d753',
"Diamonds To You!" => '86b34976-8f41-475b-a386-385080dc6e83',
"Disappointed" => 'a98ea25e-4e6a-477f-8fc2-9e8a18ab7004',
"Doing Aerobics" => '2647f538-6fc6-4775-85ae-7f6f2a8065b2',
"Doing Hakuna Matata" => '71afa8ed-03b6-4808-b537-330daf9dbf50',
"Doing the Conga" => '5e1ef7ed-efdf-44a9-8ace-6cca6275d80d',
"Enamoured" => 'c4d87a21-d4c4-498b-8bc1-5dd78c895e9f',
"Excitedly Dancing" => 'd9d1192d-1262-470d-bc0c-5ba46bedab72',
"Exhausted" => '2391b018-3b8a-4bb0-9596-8edfc502d302',
"Facepalm" => '402efb2d-6607-47f2-b8e5-bc422bcd8304',
"Faceplant" => '6d9f24c0-6246-4c92-8169-4648d1981cbb',
"Fake Death" => 'efc2f0f5-af00-4d9e-a4b1-78f18d63be79',
"Feeling Sick" => ' bb6f1764-2b0b-4a3a-adfd-3334627cdee4',
"Flight" => 'b310ea06-0485-4ad1-8424-df271ca6ec37',
"Fluttering" => '9c939344-f9d6-4a3a-95a5-f64dd3d94e45',
"Flying Like Peter Pan" => '949c4f24-6aa6-4f2a-bad5-1b3de7e12749',
"Foot Stomp!" => '13334afa-bd66-4285-b3d9-d974046db479',
"Found Inspiration" => 'b690c36b-bd02-45df-a60b-00c0dbbf265f',
"Ghast Dance" => '5a5b2c0c-a924-4e13-a99b-4c12e3f02e1e',
"Giddy" => '738497ce-539f-4e06-9a03-dc528506a468',
"Giving R2-D2 a Message" => 'e1090020-cbe0-4b64-9c41-a3b9619da029',
"Going Hero" => 'f14d652f-18ed-42dc-831f-7f6a2eab1246',
"Golf Clap" => '434489fd-ed42-4814-961a-df14161d67e0',
"Got Chills" => 'af6ad96c-5754-4cf9-a463-49a8190e6b0e',
"Groovin'" => 'd863b9cc-9f8c-498b-a8a3-7ebd542cb08e',
"Hadoken!" => '6453480a-54ac-435d-899d-4e6f7fe57591',
"Hand Stand" => '5dd129f9-cfc3-4fc1-b464-c66a03061545',
"Hard Landing" => 'c2b9dd03-7258-4813-b6f5-37ef9b4a3326',
"Hitting the Omnitrix" => '1e30e8f4-2991-4aac-a58a-a6bf90a080c5',
"Hooray!" => 'c4b5b251-24d3-43eb-9c05-46be246aeefb',
"Hoppin'" => 'fb9b884a-b217-46a2-85fd-d3ab0f2f33e6',
"Hugging Themselves" => '54e2209a-41ec-4502-8500-dd51e569ab69',
"Intercom and Attack" => '87c039b7-7bdc-45d1-8684-e940a131ec0a',
"Jumping Jacks" => 'b13966b3-1f7c-4f07-8ab8-9d85170203f5',
"Kneeling" => '24444aea-cb6e-451f-90fc-b74e57cc7c5d',
"Laughing Out Loud" => '310b41de-1c7a-4098-928d-addcd905bf65',
"Mad Falling" => '63cb3c45-b3b3-4c02-a4f3-fb4b9853dbe9',
"Meditating Like Luke" => '85957448-e7bb-4bb4-9182-510b4428e52c',
"Minion Cheering" => '6174a111-19ac-41d1-a483-0e0b37f9d049',
"Minion Panicking" => '79e93b59-38f0-4796-8033-f99d7aa9334e',
"Minion Taunting" => 'a51f8e7c-a4dd-4ce1-9fc9-2c3cad66cede',
"Offering" => '21e0054a-5bf4-468d-bfc4-fc4b49bd44ac',
"Over Here!" => '71721c51-b7d1-46b1-b7ea-eb4c4126c3db',
"Pekaboo" => '2ecc0fd1-312b-4664-9bfa-a06429838706',
"Playing Dead" => '9d4019d0-db3f-4859-a579-f6c37532d2a6',
"Playing Zombie" => '5d644007-3cdf-4246-b4ca-cfd7a4318a1c',
"Posing Like a Hero" => '7102c0f7-6113-44f5-b37c-4e94841b0e81',
"ROLF" => '6f82688e-e549-408c-946d-f8e99b91808d',
"Rebooting" => 'a602063f-1ded-4959-b978-b5ae7f353536',
"Pouting" => '34259925-44dd-46f0-98e5-80ccebc086d0',
"Ryu Guarding" => '0c141653-1166-448b-87a2-38d0679bb549',
"Sad Sigh" => '98a68056-e025-4c0f-a959-d6e330ccb5f5',
"Salsa Dancing" => '6bcf44bd-ff8a-48a5-9254-3983a0b0f702',
"Saluting" => '1ea5f771-827d-408d-ae8e-1af00d7aa416',
"Shrug" => '4ff73ed2-3c2f-4d74-9055-5fa24e59dc7a',
"Shy Higgling" => 'f1e18201-729d-472d-9e4f-5cdd7f6bba0c',
"Sid Dance" => '946f04ea-8ff0-416e-a66d-8b0d0751e8bf',
"Simple Clap" => '9a469a61-c83b-4ba9-b507-bdbe64430582',
"Slimin'" => '70831936-d97d-48fe-a7e7-d8894e7c5507',
"Sonic-Finger-Wagging" => 'e8a91ad4-6f7a-479e-9556-e1a7c058351b',
"Sonic-Running" => 'b8e54924-ec3f-409c-8914-bca61fbe9242',
"Sonic-Victory-Spinning" => 'cd8c3bc6-f455-43d2-836e-62c1a19474c7',
"Surrendering" => 'daeaaa6f-db91-4461-8617-400c5d1b8646',
"Swinging Energy Sword" => 'd7680c67-8e54-482a-903d-622ddb43485f',
"Sword Flourish" => 'a57277d5-0693-4c8a-9b5c-45c33fdf7c26',
"The Elytra" => '7393aa53-9145-4e66-b23b-ec86def6c6f2',
"The Hammer" => '7cec98d8-55cc-44fe-b0ae-2672b0b2bd37',
"The Master Chief" => '88dc7deb-21bb-48c3-8b5a-00757a06aef9',
"The Pickaxe" => 'd7519b5a-45ec-4d27-997c-89d402c6b57f',
"The Splits" => '51871829-e9ef-40aa-939c-b8952295d50e',
"The Woodpunch" => '42fde774-37d4-4422-b374-89ff13a6535a',
"Thinking" => '20bcb500-af82-4c2f-9239-e78191c61375',
"To Infinity and Beyond" => '79e8cb30-c1b4-4e41-8aa8-96492c6f390c',
"Underwater Dancing" => '05af18ca-920f-4232-83cb-133b2d913dd6',
"Using Jedi Mind Trick" => '4b9b9f17-3722-4d38-a6a9-9ba0e8cf5044',
"Victorious" => '77053f59-c79b-4d5c-8dc5-539ed28002e9',
"Victory Cheer" => 'd0c60245-538e-4ea2-bdd4-33477db5aa89',
"Warm Up Drills" => '6b9c7731-7422-4333-950f-cf3d147ffa47',
"Wave" => '4c8ae710-df2e-47cd-814d-cc7bf21a3d67',
"Waving Like C-3PO" => 'c2d6091d-9f91-4a9e-badd-ef8481353cb0',
"Yoga" => '3f1bdf46-80b0-4a64-b631-4ac2f2491165'
];
}
40 changes: 40 additions & 0 deletions src/brokiem/snpc/manager/NPCManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,18 @@
use pocketmine\entity\Human;
use pocketmine\entity\Location;
use pocketmine\math\Vector3;
use pocketmine\nbt\NoSuchTagException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\player\Player;
use pocketmine\utils\Config;
use pocketmine\utils\SingletonTrait;
use pocketmine\utils\TextFormat;
use pocketmine\world\World;
use function is_string;
use function unlink;

class NPCManager {
use SingletonTrait;
Expand Down Expand Up @@ -178,4 +183,39 @@ public function getAllNPCs(): ?array {

return $npcs;
}

public function getOldNPCData(string $identifier): array
{
$path = SimpleNPC::getInstance()->getDataFolder() . "npcs/$identifier.json";
return file_exists($path)
? (new Config($path, Config::JSON))->getAll()
: [];
}

public function updateOldNPCs(World $world): void
{
foreach ($world->getEntities() as $entity)
if ($entity instanceof BaseNPC) {
$ident = null;
try {
$ident = $entity->saveNBT()->getString("Identifier");
} catch (NoSuchTagException $e) {}

if (is_string($ident)) {
$data = $this->getOldNPCData($ident);
if (isset($data["nametag"]))
$entity->setNameTag($data["nametag"]);
if (isset($data["showNametag"]))
$entity->setNameTagVisible($data["showNametag"]);
if (isset($data["scale"]))
$entity->setScale($data["scale"]);
if (isset($data["commands"]))
foreach ($data["commands"] as $command)
$entity->getCommandManager()->add($command);

unlink(SimpleNPC::getInstance()->getDataFolder() . "npcs/$ident.json");
$entity->respawnToAll();
}
}
}
}
8 changes: 1 addition & 7 deletions src/brokiem/snpc/manager/command/CommandManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,7 @@ public function __construct(CompoundTag $nbt) {
}

public function add($command): bool {
if (!$this->exists($command)) {
$this->commands[] = $command;

return true;
}

return false;
return in_array($command, $this->commands, true);
}

public function exists(string $command): bool {
Expand Down
Loading