Skip to content

Instantly share code, notes, and snippets.

@BEcraft
Created March 9, 2019 15:25
Show Gist options
  • Save BEcraft/579990c7ffa02bd27e51e0b9481b1a64 to your computer and use it in GitHub Desktop.
Save BEcraft/579990c7ffa02bd27e51e0b9481b1a64 to your computer and use it in GitHub Desktop.
Prueba de entidades
<?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