2017-10-28 23:06:47 +00:00
|
|
|
|
<?php
|
|
|
|
|
namespace Ad5001\Spooky;
|
|
|
|
|
use pocketmine\command\CommandSender;
|
|
|
|
|
use pocketmine\command\Command;
|
|
|
|
|
use pocketmine\plugin\PluginBase;
|
|
|
|
|
use pocketmine\Server;
|
|
|
|
|
use pocketmine\Player;
|
2017-10-30 23:03:54 +00:00
|
|
|
|
use pocketmine\entity\Entity;
|
2017-10-29 17:27:35 +00:00
|
|
|
|
use pocketmine\event\Listener;
|
2017-10-28 23:06:47 +00:00
|
|
|
|
use pocketmine\item\enchantment\Enchantment;
|
2017-10-29 17:27:35 +00:00
|
|
|
|
use pocketmine\event\block\BlockPlaceEvent;
|
2017-10-30 23:03:54 +00:00
|
|
|
|
use pocketmine\network\mcpe\protocol\PlaySoundPacket;
|
2017-10-29 17:27:35 +00:00
|
|
|
|
use pocketmine\block\Block;
|
2017-10-30 23:03:54 +00:00
|
|
|
|
use pocketmine\resourcepacks\ZippedResourcePack;
|
2017-10-31 16:10:33 +00:00
|
|
|
|
use pocketmine\utils\Utils;
|
|
|
|
|
use pocketmine\utils\TextFormat;
|
2017-10-28 23:06:47 +00:00
|
|
|
|
|
|
|
|
|
use pocketmine\nbt\tag\ListTag;
|
|
|
|
|
use pocketmine\nbt\tag\CompoundTag;
|
|
|
|
|
use pocketmine\nbt\tag\StringTag;
|
|
|
|
|
use pocketmine\nbt\tag\FloatTag;
|
2017-10-30 23:03:54 +00:00
|
|
|
|
use pocketmine\nbt\tag\DoubleTag;
|
|
|
|
|
use pocketmine\nbt\tag\ShortTag;
|
2017-10-28 23:06:47 +00:00
|
|
|
|
use pocketmine\nbt\NBT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use Ad5001\Spooky\entity\Ghost;
|
|
|
|
|
use Ad5001\Spooky\tasks\TickTask;
|
|
|
|
|
|
|
|
|
|
|
2017-10-29 17:27:35 +00:00
|
|
|
|
class Main extends PluginBase implements Listener{
|
2017-10-28 23:06:47 +00:00
|
|
|
|
|
|
|
|
|
public $ghosts = [];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* When the plugin enables
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function onEnable(){
|
|
|
|
|
// Registering some enchants
|
2017-10-29 17:27:35 +00:00
|
|
|
|
Enchantment::registerEnchantment(new Enchantment(Enchantment::SHARPNESS, "%enchantment.attack.sharpness", Enchantment::ACTIVATION_HELD, Enchantment::RARITY_COMMON, Enchantment::SLOT_SWORD));
|
2017-10-30 23:03:54 +00:00
|
|
|
|
Entity::registerEntity(Ghost::class, true, ['Ghost', 'minecraft:ghost']);
|
2017-10-29 17:27:35 +00:00
|
|
|
|
$this->getServer()->getScheduler()->scheduleRepeatingTask(new TickTask($this), 2);
|
|
|
|
|
$this->getServer()->getPluginManager()->registerEvents($this, $this);
|
2017-10-30 23:03:54 +00:00
|
|
|
|
// Resource pack
|
2017-10-31 17:56:38 +00:00
|
|
|
|
if(!file_exists($this->getDataFolder())){
|
|
|
|
|
mkdir($this->getDataFolder());
|
|
|
|
|
}
|
2017-10-31 16:10:33 +00:00
|
|
|
|
$downRP = false;
|
|
|
|
|
if(!file_exists($this->getDataFolder() . "Spooky.mcpack")) {
|
|
|
|
|
$downRP = true;
|
|
|
|
|
echo TextFormat::toANSI("§f[Spooky] ⚪ Downloading resource pack...");
|
2017-10-31 16:35:09 +00:00
|
|
|
|
file_put_contents($this->getDataFolder() . "Spooky.mcpack", Utils::getURL("https://github.com/Ad5001/Spooky/releases/download/1.0/Spooky.mcpack"));
|
2017-10-31 16:10:33 +00:00
|
|
|
|
}
|
|
|
|
|
echo str_repeat("\010", $downRP ? strlen(TextFormat::toANSI("§f[Spooky] ⚪ Downloading resource pack...")) : 0) . TextFormat::toANSI("§f[Spooky] ⚪ Applying resource pack... "); // Replacing latest message
|
2017-10-30 23:03:54 +00:00
|
|
|
|
$pack = new ZippedResourcePack($this->getDataFolder() . "Spooky.mcpack");
|
|
|
|
|
$r = new \ReflectionClass("pocketmine\\resourcepacks\\ResourcePackManager");
|
2017-10-31 17:22:11 +00:00
|
|
|
|
// Reflection because devs thought it was a great idea to not let plugins manage resource packs :/
|
|
|
|
|
$resourcePacks = $r->getProperty("resourcePacks");
|
|
|
|
|
$resourcePacks->setAccessible(true);
|
|
|
|
|
$rps = $resourcePacks->getValue($this->getServer()->getResourceManager());
|
|
|
|
|
$rps[] = $pack;
|
|
|
|
|
$resourcePacks->setValue($this->getServer()->getResourceManager(), $rps);
|
|
|
|
|
$resourceUuids = $r->getProperty("uuidList");
|
|
|
|
|
$resourceUuids->setAccessible(true);
|
|
|
|
|
$uuids = $resourceUuids->getValue($this->getServer()->getResourceManager());
|
|
|
|
|
$uuids[$pack->getPackId()] = $pack;
|
|
|
|
|
$resourceUuids->setValue($this->getServer()->getResourceManager(), $uuids);
|
|
|
|
|
// Forcing resource packs. We want the client to hear the music!
|
|
|
|
|
$forceResources = $r->getProperty("serverForceResources");
|
|
|
|
|
$forceResources->setAccessible(true);
|
|
|
|
|
$forceResources->setValue($this->getServer()->getResourceManager(), true);
|
2017-10-31 16:10:33 +00:00
|
|
|
|
echo str_repeat("\010", strlen("⚪ Applying resource pack... ")) . TextFormat::toANSI("§a✔️ Done! Spooky enabled! \n");
|
2017-10-28 23:06:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* WHen a command is executed
|
|
|
|
|
*
|
|
|
|
|
* @param CommandSender $sender
|
|
|
|
|
* @param Command $cmd
|
|
|
|
|
* @param string $label
|
|
|
|
|
* @param array $args
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function onCommand(CommandSender $sender, Command $cmd, string $label, array $args): bool{
|
|
|
|
|
switch($cmd->getName()){
|
|
|
|
|
case "default":
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-10-29 17:27:35 +00:00
|
|
|
|
public function onBlockPlace(BlockPlaceEvent $event) {
|
|
|
|
|
// Checking the pumpkin at the top
|
|
|
|
|
$found = false;
|
|
|
|
|
if($event->getBlock()->getId() == Block::PUMPKIN){
|
|
|
|
|
$under = $event->getBlock()->asVector3();
|
|
|
|
|
$under->y--;
|
|
|
|
|
// Hay bale for the body
|
|
|
|
|
if($event->getBlock()->getLevel()->getBlock($under)->getId() == Block::HAY_BALE) {
|
2017-10-30 23:03:54 +00:00
|
|
|
|
$under2 = $under->asVector3();
|
2017-10-29 17:27:35 +00:00
|
|
|
|
$under2->y--;
|
|
|
|
|
// Fence for the bottom
|
|
|
|
|
if($event->getBlock()->getLevel()->getBlock($under2)->getId() == Block::FENCE){
|
|
|
|
|
// Fences for the sides.
|
|
|
|
|
$side1 = $under->asVector3();
|
|
|
|
|
$side1->x++;
|
|
|
|
|
$side2 = $under->asVector3();
|
|
|
|
|
$side2->x--;
|
|
|
|
|
if($event->getBlock()->getLevel()->getBlock($side1)->getId() == Block::FENCE && $event->getBlock()->getLevel()->getBlock($side1)->getId() == Block::FENCE) {
|
|
|
|
|
$found = true;
|
|
|
|
|
} else {
|
|
|
|
|
$side1 = $under->asVector3();
|
|
|
|
|
$side1->z++;
|
|
|
|
|
$side2 = $under->asVector3();
|
|
|
|
|
$side2->z--;
|
|
|
|
|
if($event->getBlock()->getLevel()->getBlock($side1)->getId() == Block::FENCE && $event->getBlock()->getLevel()->getBlock($side1)->getId() == Block::FENCE) {
|
|
|
|
|
$found = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// If everything's right, we can destroy the structure & generate the ghost
|
|
|
|
|
if($found){
|
|
|
|
|
$event->setCancelled();
|
|
|
|
|
$event->getBlock()->getLevel()->setBlock($under, Block::get(Block::AIR));
|
|
|
|
|
$event->getBlock()->getLevel()->setBlock($under2, Block::get(Block::AIR));
|
|
|
|
|
$event->getBlock()->getLevel()->setBlock($side1, Block::get(Block::AIR));
|
|
|
|
|
$event->getBlock()->getLevel()->setBlock($side2, Block::get(Block::AIR));
|
2017-10-30 23:03:54 +00:00
|
|
|
|
if($event->getPlayer() !== null){
|
2017-10-29 17:27:35 +00:00
|
|
|
|
$this->spawnGhost($event->getPlayer());
|
2017-10-30 23:03:54 +00:00
|
|
|
|
// Spawning an another ghost for the surround players. It's more challenging :p
|
|
|
|
|
foreach($this->getServer()->getOnlinePlayers() as $p) {
|
|
|
|
|
if($p->getLevel()->getName() == $event->getPlayer()->getLevel()->getName() && $p->getName() !== $event->getPlayer()->getName()) {
|
|
|
|
|
if($p->distance($event->getPlayer()) <= 10) {
|
|
|
|
|
$this->spawnGhost($p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-10-29 17:27:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-28 23:06:47 +00:00
|
|
|
|
|
2017-10-29 17:27:35 +00:00
|
|
|
|
/**
|
|
|
|
|
* Spawns a ghost
|
|
|
|
|
*
|
|
|
|
|
* @param Player $p
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
2017-10-28 23:06:47 +00:00
|
|
|
|
public function spawnGhost(Player $p){
|
|
|
|
|
// Getting the skin
|
|
|
|
|
$nbtSkin = new NBT(NBT::BIG_ENDIAN);
|
2017-10-30 23:03:54 +00:00
|
|
|
|
$nbtSkin->readCompressed(file_get_contents($this->getFile() . "resources/ghost_player_data.dat"));
|
2017-10-28 23:06:47 +00:00
|
|
|
|
$nbt = new CompoundTag();
|
|
|
|
|
$nbt->Pos = new ListTag("Pos", [
|
2017-10-30 23:03:54 +00:00
|
|
|
|
new DoubleTag("", $p->getX()),
|
|
|
|
|
new DoubleTag("", $p->getY()),
|
|
|
|
|
new DoubleTag("", $p->getZ())
|
2017-10-28 23:06:47 +00:00
|
|
|
|
]);
|
|
|
|
|
$nbt->Motion = new ListTag("Motion", [
|
|
|
|
|
new DoubleTag("", 0),
|
|
|
|
|
new DoubleTag("", 0),
|
|
|
|
|
new DoubleTag("", 0)
|
|
|
|
|
]);
|
|
|
|
|
$nbt->Rotation = new ListTag("Rotation", [
|
2017-10-30 23:03:54 +00:00
|
|
|
|
new FloatTag("", $p->getYaw()),
|
|
|
|
|
new FloatTag("", $p->getPitch())
|
|
|
|
|
]);
|
|
|
|
|
// var_dump($nbtSkin);
|
2017-10-28 23:06:47 +00:00
|
|
|
|
$nbt->Health = new ShortTag("Health", 20);
|
2017-10-30 23:03:54 +00:00
|
|
|
|
$nbt->Skin = clone $nbtSkin->getData()->Skin;
|
|
|
|
|
$nbt->Inventory = clone $nbtSkin->getData()->Inventory;
|
|
|
|
|
$g = Entity::createEntity("Ghost", $p->getLevel(), $nbt);
|
2017-10-28 23:06:47 +00:00
|
|
|
|
$g->startFight($p);
|
|
|
|
|
$this->ghosts[$p->getName()] = $g;
|
|
|
|
|
}
|
2017-10-30 23:03:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function onEntityDamage(\pocketmine\event\entity\EntityDamageEvent $event){
|
|
|
|
|
if($event instanceof \pocketmine\event\entity\EntityDamageByEntityEvent && $event->getDamager() instanceof Player){
|
|
|
|
|
if(isset($event->getDamager()->getInventory()->getItemInHand()->getNamedTag()->customDamage)) {
|
|
|
|
|
$event->setDamage($event->getDamager()->getInventory()->getItemInHand()->namedtag->customDamage->getValue());
|
|
|
|
|
}
|
|
|
|
|
if(isset($event->getDamager()->getInventory()->getItemInHand()->getNamedTag()->sneakInvisible) && $event->getEntity() instanceof Player) {
|
|
|
|
|
$pk = new PlaySoundPacket();
|
|
|
|
|
$pk->soundName = "mob.wither.death";
|
|
|
|
|
$pk->x = (int)$event->getEntity()->x;
|
|
|
|
|
$pk->y = (int)$event->getEntity()->y;
|
|
|
|
|
$pk->z = (int)$event->getEntity()->z;
|
|
|
|
|
$pk->volume = 3;
|
|
|
|
|
$pk->pitch = 1;
|
|
|
|
|
$event->getEntity()->dataPacket($pk);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-10-31 17:22:11 +00:00
|
|
|
|
}
|