Created
March 9, 2019 15:25
-
-
Save BEcraft/579990c7ffa02bd27e51e0b9481b1a64 to your computer and use it in GitHub Desktop.
Prueba de entidades
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @name Vista | |
* @author BEcraft | |
* @main BEcraft\Vista\Cargador | |
* @api 3.0.0 | |
* @version 1.0.0 | |
*/ | |
namespace BEcraft\Vista; | |
use pocketmine\entity\Entity; | |
use pocketmine\plugin\PluginBase; | |
use pocketmine\event\Listener; | |
use pocketmine\Player; | |
use pocketmine\level\Level; | |
use pocketmine\event\player\PlayerQuitEvent; | |
use pocketmine\event\server\DataPacketReceiveEvent; | |
use pocketmine\event\player\PlayerToggleSneakEvent; | |
use pocketmine\network\mcpe\protocol\InteractPacket; | |
use pocketmine\entity\Villager; | |
use pocketmine\nbt\tag\CompoundTag; | |
use pocketmine\level\particle\HeartParticle; | |
use pocketmine\event\entity\EntityDamageEvent; | |
/** | |
* Muestra de como se implementaria | |
* este menú, lo pueden tomar como | |
* orientación. | |
* | |
*/ | |
class Cargador extends PluginBase implements Listener { | |
/** | |
* Arreglo donde se almacenarán los datos. | |
* @var array | |
*/ | |
public static $USUARIOS = array(); | |
public function onEnable(): void { | |
Entity::registerEntity(Entidad::class, true, [Entidad::class]); | |
$this->getServer()->getPluginManager()->registerEvents($this, $this); | |
} | |
/** | |
* Ejemplo de como verificar si el jugador esta mirando a una entidad. | |
*/ | |
public function recivir(DataPacketReceiveEvent $evento): void { | |
$nombre = $evento->getPlayer()->getName(); | |
if (!isset(self::$USUARIOS[$nombre])) { | |
return; | |
} | |
$usuario = $evento->getPlayer(); | |
if ($evento->getPacket() instanceof InteractPacket) { | |
$entidad = (self::$USUARIOS[$nombre]["entidades"][$evento->getPacket()->target] ?? null); | |
if ($entidad) { | |
if (!($entidad instanceof Entidad)) { | |
return; | |
} | |
if (self::$USUARIOS[$nombre]["seleccion"] === null) { | |
self::$USUARIOS[$nombre]["seleccion"] = $entidad; | |
} | |
$objetivo = self::$USUARIOS[$nombre]["seleccion"]; | |
if ($entidad !== $objetivo) { | |
if ($objetivo->seleccionado) { | |
$objetivo->retroceder(); | |
} | |
$entidad->setTargetEntity($usuario); | |
if (!($entidad->seleccionado)) { | |
$entidad->acercarse(); | |
} | |
self::$USUARIOS[$nombre]["seleccion"] = $entidad; | |
} else { | |
if (!($entidad->seleccionado)) { | |
$entidad->acercarse(); | |
} | |
} | |
} | |
} | |
} | |
/** | |
* Ejemplo de las posiciones de | |
* los aldeanos. | |
* | |
* · = Aldeano | |
* © = Jugador | |
* | |
* · · · | |
* \ | / | |
* ·-- © --· | |
* / | \ | |
* · · · | |
*/ | |
public function entidades(Player $usuario): array { | |
$entidades = array( | |
new Entidad($usuario->getLevel(), Entity::createBaseNBT($usuario->add(2.5))), | |
new Entidad($usuario->getLevel(), Entity::createBaseNBT($usuario->add(2, 0, 2))), | |
new Entidad($usuario->getLevel(), Entity::createBaseNBT($usuario->add(0, 0, 2.5))), | |
new Entidad($usuario->getLevel(), Entity::createBaseNBT($usuario->add(0, 0, -2.5))), | |
new Entidad($usuario->getLevel(), Entity::createBaseNBT($usuario->subtract(2)->add(0, 0, 2))),//== | |
new Entidad($usuario->getLevel(), Entity::createBaseNBT($usuario->subtract(2, 0, 2))), | |
new Entidad($usuario->getLevel(), Entity::createBaseNBT($usuario->subtract(2.5))), | |
new Entidad($usuario->getLevel(), Entity::createBaseNBT($usuario->subtract(0, 0, 2)->add(2))) | |
); | |
foreach ($entidades as $entidad) { | |
$entidad->lookAt($usuario); | |
} | |
return $entidades; | |
} | |
/** | |
* Solo de prueba. | |
* Son solo mensajes pero podrián ser mas que eso, hagan eso de otra manera. | |
*/ | |
private static $funciones; | |
private function funciones(int $index, Player $usuario): callable { | |
if (self::$funciones === null) { | |
self::$funciones = array( | |
function ($entidad) use ($usuario) { | |
$usuario->sendMessage("La fecha de hoy es: " . gmdate("h : i s, d / m / y", time())); | |
}, | |
function ($entidad) use ($usuario) { | |
$usuario->sendMessage("BEcraft es mi mejor amigo"); | |
}, | |
function ($entidad) use ($usuario) { | |
$usuario->sendMessage("¿Tienes hambre?"); | |
}, | |
function ($entidad) use ($usuario) { | |
$usuario->sendMessage("Cuanto es 5 * 5?"); | |
}, | |
function ($entidad) use ($usuario) { | |
$usuario->sendMessage("Muuu, soy una rana, o quizás una oveja?"); | |
}, | |
function ($entidad) use ($usuario) { | |
$usuario->sendMessage("Recuerda siempre comer saludable"); | |
}, | |
function ($entidad) use ($usuario) { | |
$usuario->sendMessage("Si tienes alguna duda contacta a BEcraft en twitter (aunque no siempre esta en linea XD): @BEcraft_MCPE"); | |
}, | |
function ($entidad) use ($usuario) { | |
$usuario->sendMessage("Hola amig@."); | |
} | |
); | |
} | |
return self::$funciones[$index] ?? function($entidad){}; | |
} | |
/** | |
* Ejemplo: | |
*/ | |
public function sneak(PlayerToggleSneakEvent $evento): void { | |
$nombre = $evento->getPlayer()->getName(); | |
if (!isset(self::$USUARIOS[$nombre])) { | |
self::$USUARIOS[$nombre] = array("entidades" => [], "seleccion" => null); | |
} | |
$usuario = $evento->getPlayer(); | |
if ($evento->isSneaking()) { | |
foreach ($this->entidades($usuario) as $funcion => $entidad) { | |
$entidad->spawnTo($usuario); | |
$entidad->agregar($this->funciones($funcion, $usuario)); | |
self::$USUARIOS[$nombre]["entidades"][$entidad->getId()] = $entidad; | |
} | |
$usuario->setImmobile(true); | |
} else { | |
if ($this->remover(self::$USUARIOS[$nombre]["entidades"])) { | |
$usuario->setImmobile(false); | |
} | |
self::$USUARIOS[$nombre]["seleccion"] = null; | |
self::$USUARIOS[$nombre]["entidades"] = array(); | |
} | |
} | |
/** | |
* Revueve las entidades. | |
*/ | |
private function remover(array $lista): bool { | |
foreach ($lista as $entidad) { | |
if (!($entidad->isClosed()) and ($entidad->getLevel()->getEntity($entidad->getId()) instanceof Entidad)) { | |
$entidad->flagForDespawn(); | |
} | |
} | |
return true; | |
} | |
/** | |
* Remover las entidades al salir del servidor. | |
*/ | |
public function salir(PlayerQuitEvent $evento): void { | |
$nombre = $evento->getPlayer()->getName(); | |
if (isset(self::$USUARIOS[$nombre]) and !empty(self::$USUARIOS[$nombre]["entidades"])) { | |
$this->remover(self::$USUARIOS[$nombre]["entidades"]); | |
} | |
unset(self::$USUARIOS[$nombre]); | |
} | |
} | |
/** | |
* Clase del aldeano, pueden usar un Humano (Human) y así le pueden poner alguna | |
* geometria interesante. | |
*/ | |
class Entidad extends Villager { | |
/** | |
* Verifica si la entidad esta seleccionada. | |
* @val bool | |
*/ | |
public $seleccionado = false; | |
/** | |
* Gravedad. | |
* @var float | |
*/ | |
protected $gravity = 0.00; | |
/** | |
* Prueba. | |
*/ | |
protected $aEjecutar; | |
/** | |
* Impide que se guarde con el mundo. | |
* @var bool | |
*/ | |
public function canSaveWithChunk(): bool { | |
return false; | |
} | |
/** | |
* La funcion es de prueba | |
* tambien puede ser en el constructor. | |
*/ | |
public function spawnTo(Player $usuario): void { | |
parent::spawnTo($usuario); | |
$this->setTargetEntity($usuario); | |
$this->setGenericFlag(self::DATA_FLAG_AFFECTED_BY_GRAVITY, false); | |
} | |
public function agregar(callable $funcion): void { | |
if (!($this->aEjecutar)) { | |
$this->aEjecutar = $funcion; | |
} | |
} | |
/** | |
* Evita que el usuario lastime a la entidad y ejecuta la funcion. | |
*/ | |
public function attack(EntityDamageEvent $evento): void { | |
$evento->setCancelled(); | |
if (($usuario = ($evento->getDamager() ?? null)) !== null and $usuario === $this->getTargetEntity()) { | |
($this->aEjecutar)($this); //llamada de función | |
} | |
} | |
/** | |
* Para evitar que la entidad se cierre cuando muera, pero solo si usan el evento PlayerToggleSneakEvent | |
* de otra manera pueden manejarlo ustedes mismos. | |
* | |
* Nota: No he probado esta función, si tiene un error lo pueden corregir. | |
*/ | |
public function onDeath(): void { | |
if ($this->seleccionado and ($usuario = $this->getTargetEntity()) instanceof Player) { | |
$this->getLevel()->getServer()->getPluginManager()->callEvent($evento = new PlayerToggleSneakEvent($usuario, false)); | |
if (!($evento->isCancelled())) { | |
$usuario->setSneaking(false); | |
} | |
} | |
} | |
/** | |
* La posicion de movida de podria guardar en el constructor | |
* directamente y así no tener que acceder cada vez a su | |
* posicion para evitar bugs (por ejemplo que se mueva de mas). | |
* | |
* Nota: lo digo para esta función y la siguiente. | |
*/ | |
public function acercarse(): void { | |
$this->seleccionado = true; | |
$this->setNameTagVisible(true); | |
$movida = $this->getDirectionVector()->multiply(1); | |
$this->move((float) $movida->getX(), (float) $movida->getY(), (float) $movida->getZ()); | |
} | |
public function retroceder(): void { | |
$this->seleccionado = false; | |
$this->setNameTagVisible(false); | |
$movida = $this->getDirectionVector()->multiply(-1); | |
$this->move((float) $movida->getX(), (float) $movida->getY(), (float) $movida->getZ()); | |
} | |
/** | |
* Solo de decoración, claro está que se podria poner muchas mas funciones. | |
*/ | |
public function entityBaseTick(int $tickDiff = 1): bool { | |
if ($this->seleccionado) { | |
if (($this->ticksLived % (20 * 30)) === 0) { | |
$this->getLevel()->addParticle(new HeartParticle($this->add(0, 2))); | |
} | |
} | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment