Implemented health, events, damage, motion push

This commit is contained in:
Shoghi Cervantes 2014-07-06 23:10:11 +02:00
parent 25ecdcf6e2
commit 65523972c2
15 changed files with 701 additions and 122 deletions

View File

@ -24,13 +24,18 @@ namespace pocketmine;
use pocketmine\block\Block;
use pocketmine\command\CommandSender;
use pocketmine\entity\DroppedItem;
use pocketmine\entity\Entity;
use pocketmine\entity\Human;
use pocketmine\entity\Living;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\inventory\InventoryCloseEvent;
use pocketmine\event\inventory\InventoryPickupItemEvent;
use pocketmine\event\player\PlayerAchievementAwardedEvent;
use pocketmine\event\player\PlayerAnimationEvent;
use pocketmine\event\player\PlayerChatEvent;
use pocketmine\event\player\PlayerCommandPreprocessEvent;
use pocketmine\event\player\PlayerDeathEvent;
use pocketmine\event\player\PlayerDropItemEvent;
use pocketmine\event\player\PlayerGameModeChangeEvent;
use pocketmine\event\player\PlayerItemConsumeEvent;
@ -69,6 +74,7 @@ use pocketmine\network\protocol\Info as ProtocolInfo;
use pocketmine\network\protocol\LoginStatusPacket;
use pocketmine\network\protocol\MessagePacket;
use pocketmine\network\protocol\MovePlayerPacket;
use pocketmine\network\protocol\SetHealthPacket;
use pocketmine\network\protocol\SetSpawnPositionPacket;
use pocketmine\network\protocol\SetTimePacket;
use pocketmine\network\protocol\StartGamePacket;
@ -1062,7 +1068,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$pk = new TakeItemEntityPacket;
$pk->eid = $this->getID();
$pk->target = $entity->getID();
$this->server->broadcastPacket($entity->getViewers(), $pk);
Server::broadcastPacket($entity->getViewers(), $pk);
$this->inventory->addItem(clone $item);
$entity->kill();
}
@ -1219,7 +1225,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$pk = new LoginStatusPacket;
$pk->status = 0;
$this->directDataPacket($pk);
$this->dataPacket($pk);
if(($level = $this->server->getLevelByName($this->namedtag["SpawnLevel"])) instanceof Level){
$this->spawnPosition = new Position($this->namedtag["SpawnX"], $this->namedtag["SpawnY"], $this->namedtag["SpawnZ"], $level);
@ -1236,17 +1242,21 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$pk->generator = 1; //0 old, 1 infinite, 2 flat
$pk->gamemode = $this->gamemode & 0x01;
$pk->eid = 0; //Always use EntityID as zero for the actual player
$this->directDataPacket($pk);
$this->dataPacket($pk);
$pk = new SetTimePacket();
$pk->time = $this->getLevel()->getTime();
$this->directDataPacket($pk);
$this->dataPacket($pk);
$pk = new SetSpawnPositionPacket;
$pk->x = (int) $this->spawnPosition->x;
$pk->y = (int) $this->spawnPosition->y;
$pk->z = (int) $this->spawnPosition->z;
$this->directDataPacket($pk);
$this->dataPacket($pk);
$pk = new SetHealthPacket();
$pk->health = $this->getHealth();
$this->dataPacket($pk);
$this->server->getLogger()->info(TextFormat::AQUA . $this->username . TextFormat::WHITE . "[/" . $this->ip . ":" . $this->port . "] logged in with entity id " . $this->id . " at (" . $this->getLevel()->getName() . ", " . round($this->x, 4) . ", " . round($this->y, 4) . ", " . round($this->z, 4) . ")");
@ -1345,7 +1355,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->craftingType = 0;
if(($this->spawned === false or $this->blocked === true) and $packet->face >= 0 and $packet->face <= 5){
if(($this->spawned === false or $this->blocked === true or $this->dead === true) and $packet->face >= 0 and $packet->face <= 5){
$target = $this->getLevel()->getBlock($blockVector);
$block = $target->getSide($packet->face);
@ -1420,7 +1430,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
break;
case ProtocolInfo::PLAYER_ACTION_PACKET:
if($this->spawned === false or $this->blocked === true){
if($this->spawned === false or $this->blocked === true or $this->dead === true){
break;
}
@ -1498,7 +1508,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
break;
case ProtocolInfo::REMOVE_BLOCK_PACKET:
if($this->spawned === false or $this->blocked === true){
if($this->spawned === false or $this->blocked === true or $this->dead === true){
break;
}
$this->craftingType = 0;
@ -1537,7 +1547,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
break;
case ProtocolInfo::PLAYER_ARMOR_EQUIPMENT_PACKET:
if($this->spawned === false or $this->blocked === true){
if($this->spawned === false or $this->blocked === true or $this->dead === true){
break;
}
@ -1571,95 +1581,112 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
//$this->entity->updateMetadata();
}
break;
/*case ProtocolInfo::INTERACT_PACKET:
case ProtocolInfo::INTERACT_PACKET:
if($this->spawned === false){
break;
}
$this->craftingType = 0;
$packet->eid = $this->id;
$data = [];
$data["target"] = $packet->target;
$data["eid"] = $packet->eid;
$data["action"] = $packet->action;
$target = Entity::get($packet->target);
if($target instanceof Entity and $this->gamemode !== VIEW and $this->blocked === false and ($target instanceof Entity) and $this->entity->distance($target) <= 8){
$data["targetentity"] = $target;
$data["entity"] = $this->entity;
if($target instanceof Player and ($this->server->api->getProperty("pvp") == false or $this->server->difficulty <= 0 or ($target->player->gamemode & 0x01) === 0x01)){
break;
}elseif($this->server->handle("player.interact", $data) !== false){
$slot = $this->getSlot($this->getCurrentEquipment());
switch($slot->getID()){
case WOODEN_SWORD:
case GOLD_SWORD:
$damage = 4;
break;
case STONE_SWORD:
$damage = 5;
break;
case IRON_SWORD:
$damage = 6;
break;
case DIAMOND_SWORD:
$damage = 7;
break;
case WOODEN_AXE:
case GOLD_AXE:
$damage = 3;
break;
case STONE_AXE:
$damage = 4;
break;
case IRON_AXE:
$damage = 5;
break;
case DIAMOND_AXE:
$damage = 6;
break;
$target = $this->getLevel()->getEntity($packet->target);
case WOODEN_PICKAXE:
case GOLD_PICKAXE:
$damage = 2;
break;
case STONE_PICKAXE:
$damage = 3;
break;
case IRON_PICKAXE:
$damage = 4;
break;
case DIAMOND_PICKAXE:
$damage = 5;
break;
if($target instanceof Entity and $this->getGamemode() !== Player::VIEW and $this->blocked === false and $this->dead !== true and $target->dead !== true){
$cancelled = false;
$item = $this->inventory->getItemInHand();
$damageTable = [
Item::WOODEN_SWORD => 4,
Item::GOLD_SWORD => 4,
Item::STONE_SWORD => 5,
Item::IRON_SWORD => 6,
Item::DIAMOND_SWORD => 7,
case WOODEN_SHOVEL:
case GOLD_SHOVEL:
$damage = 1;
break;
case STONE_SHOVEL:
$damage = 2;
break;
case IRON_SHOVEL:
$damage = 3;
break;
case DIAMOND_SHOVEL:
$damage = 4;
break;
Item::WOODEN_AXE => 3,
Item::GOLD_AXE => 3,
Item::STONE_AXE => 3,
Item::IRON_AXE => 5,
Item::DIAMOND_AXE => 6,
default:
$damage = 1;//$this->server->difficulty;
Item::WOODEN_PICKAXE => 2,
Item::GOLD_PICKAXE => 2,
Item::STONE_PICKAXE => 3,
Item::IRON_PICKAXE => 4,
Item::DIAMOND_PICKAXE => 5,
Item::WOODEN_SHOVEL => 1,
Item::GOLD_SHOVEL => 1,
Item::STONE_SHOVEL => 2,
Item::IRON_SHOVEL => 3,
Item::DIAMOND_SHOVEL => 4,
];
$damage = [
EntityDamageByEntityEvent::MODIFIER_BASE => isset($damageTable[$item->getID()]) ? $damageTable[$item->getID()] : 1,
];
if($this->distance($target) > 8){
$cancelled = true;
}elseif($target instanceof Player){
if(($target->getGamemode() & 0x01) > 0){
break;
}elseif($this->server->getConfigBoolean("pvp") === false or $this->server->getDifficulty() === 0){
$cancelled = true;
}
$target->harm($damage, $this->id);
if($slot->isTool() === true and ($this->gamemode & 0x01) === 0){
if($slot->useOn($target) and $slot->getDamage() >= $slot->getMaxDurability()){
$this->setSlot($this->getCurrentEquipment(), new Item(AIR, 0, 1));
$armorValues = [
Item::LEATHER_CAP => 1,
Item::LEATHER_TUNIC => 3,
Item::LEATHER_PANTS => 2,
Item::LEATHER_BOOTS => 1,
Item::CHAIN_HELMET => 1,
Item::CHAIN_CHESTPLATE => 5,
Item::CHAIN_LEGGINGS => 4,
Item::CHAIN_BOOTS => 1,
Item::GOLD_HELMET => 1,
Item::GOLD_CHESTPLATE => 5,
Item::GOLD_LEGGINGS => 3,
Item::GOLD_BOOTS => 1,
Item::IRON_HELMET => 2,
Item::IRON_CHESTPLATE => 6,
Item::IRON_LEGGINGS => 5,
Item::IRON_BOOTS => 2,
Item::DIAMOND_HELMET => 3,
Item::DIAMOND_CHESTPLATE => 8,
Item::DIAMOND_LEGGINGS => 6,
Item::DIAMOND_BOOTS => 3,
];
$points = 0;
foreach($target->getInventory()->getArmorContents() as $index => $i){
if(isset($armorValues[$i->getID()])){
$points += $armorValues[$i->getID()];
}
}
$damage[EntityDamageEvent::MODIFIER_ARMOR] = -intval($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
}
$ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $damage);
if($cancelled){
$ev->setCancelled();
}
$this->server->getPluginManager()->callEvent($ev);
if($ev->isCancelled()){
if($item->isTool() and ($this->gamemode & 0x01) === 0){
$this->inventory->sendContents($this);
}
break;
}
$target->attack($ev->getFinalDamage(), $ev);
if($item->isTool() and ($this->gamemode & 0x01) === 0){
if($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()){
$this->inventory->setItemInHand(Item::get(Item::AIR, 0 ,1));
}
}
}
break;*/
break;
case ProtocolInfo::ANIMATE_PACKET:
if($this->spawned === false){
break;
@ -1673,10 +1700,10 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$pk = new AnimatePacket();
$pk->eid = $this->getID();
$pk->action = $ev->getAnimationType();
$this->server->broadcastPacket($this->getViewers(), $pk);
Server::broadcastPacket($this->getViewers(), $pk);
break;
case ProtocolInfo::RESPAWN_PACKET:
if($this->spawned === false or $this->dead === false){
if($this->spawned === false or $this->dead !== true){
break;
}
$this->craftingType = 0;
@ -1686,19 +1713,22 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->teleport($ev->getRespawnPosition());
//$this->entity->fire = 0;
//$this->entity->air = 300;
//$this->entity->setHealth(20, "respawn", true);
$this->setHealth(20);
$this->dead = false;
//$this->entity->updateMetadata();
$this->sendSettings();
$this->inventory->sendContents($this);
$this->inventory->sendArmorContents($this);
$this->spawnToAll();
$this->blocked = false;
break;
case ProtocolInfo::SET_HEALTH_PACKET: //Not used
break;
case ProtocolInfo::ENTITY_EVENT_PACKET:
if($this->spawned === false or $this->blocked === true){
if($this->spawned === false or $this->blocked === true or $this->dead === true){
break;
}
$this->craftingType = 0;
@ -1743,9 +1773,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$pk->event = 9;
$this->dataPacket($pk);
$pk->eid = $this->getID();
$this->server->broadcastPacket($this->getViewers(), $pk);
Server::broadcastPacket($this->getViewers(), $pk);
$this->heal($items[$slot->getID()], "eating");
$this->heal($items[$slot->getID()]);
--$slot->count;
$this->inventory->setItemInHand($slot);
if($slot->getID() === Item::MUSHROOM_STEW or $slot->getID() === Item::BEETROOT_SOUP){
@ -1756,15 +1786,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
break;
case ProtocolInfo::DROP_ITEM_PACKET:
if($this->spawned === false or $this->blocked === true){
if($this->spawned === false or $this->blocked === true or $this->dead === true){
break;
}
$packet->eid = $this->id;
$item = $this->inventory->getItemInHand();
$ev = new PlayerDropItemEvent($this, $item);
if($this->blocked === true){
$ev->setCancelled(true);
}
$this->server->getPluginManager()->callEvent($ev);
if($ev->isCancelled()){
$this->inventory->sendContents($this);
@ -1817,7 +1844,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
break;
case ProtocolInfo::CONTAINER_SET_SLOT_PACKET:
if($this->spawned === false or $this->blocked === true){
if($this->spawned === false or $this->blocked === true or $this->dead === true){
break;
}
@ -1937,7 +1964,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
break;
case ProtocolInfo::ENTITY_DATA_PACKET:
if($this->spawned === false or $this->blocked === true){
if($this->spawned === false or $this->blocked === true or $this->dead === true){
break;
}
$this->craftingType = 0;
@ -2091,6 +2118,72 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
return $this->username;
}
public function kill(){
parent::kill();
$message = $this->getName() ." died";
$cause = $this->getLastDamageCause();
$ev = null;
if($cause instanceof EntityDamageEvent){
$ev = $cause;
$cause = $ev->getCause();
}
switch($cause){
case EntityDamageEvent::CAUSE_ENTITY_ATTACK:
if($ev instanceof EntityDamageByEntityEvent){
$e = $ev->getDamager();
if($e instanceof Player){
$message = $this->getName() ." was killed by ".$e->getName();
break;
}elseif($e instanceof Living){
$message = $this->getName() ." was slain by ".$e->getName();
break;
}
}
$message = $this->getName() ." was killed";
break;
case EntityDamageEvent::CAUSE_SUICIDE:
break;
case EntityDamageEvent::CAUSE_CONTACT:
case EntityDamageEvent::CAUSE_PROJECTILE:
case EntityDamageEvent::CAUSE_SUFFOCATION:
case EntityDamageEvent::CAUSE_FALL:
case EntityDamageEvent::CAUSE_FIRE:
case EntityDamageEvent::CAUSE_FIRE_TICK:
case EntityDamageEvent::CAUSE_LAVA:
case EntityDamageEvent::CAUSE_DROWNING:
case EntityDamageEvent::CAUSE_BLOCK_EXPLOSION:
case EntityDamageEvent::CAUSE_ENTITY_EXPLOSION:
case EntityDamageEvent::CAUSE_VOID:
case EntityDamageEvent::CAUSE_MAGIC:
case EntityDamageEvent::CAUSE_CUSTOM:
default:
}
$this->server->getPluginManager()->callEvent($ev = new PlayerDeathEvent($this, $this->getDrops(), $message));
$this->server->broadcast($ev->getDeathMessage(), Server::BROADCAST_CHANNEL_USERS);
}
public function setHealth($amount){
parent::setHealth($amount);
$pk = new SetHealthPacket();
$pk->health = $this->getHealth();
$this->dataPacket($pk);
}
public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){
$pk = new EntityEventPacket();
$pk->eid = 0;
$pk->event = 2;
$this->dataPacket($pk);
parent::attack($damage, $source);
}
/**
* @param Inventory $inventory

View File

@ -1379,11 +1379,17 @@ class Server{
$version = new VersionString($this->getPocketMineVersion());
$this->logger->info("Starting Minecraft: PE server version " . TextFormat::AQUA . $this->getVersion());
$this->logger->info("Loading properties...");
$this->logger->info("Loading pocketmine.yml...");
if(!file_exists($this->dataPath . "pocketmine.yml")){
@file_put_contents($this->dataPath . "pocketmine.yml", file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml"));
$content = file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml");
if($version->isDev()){
$content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content);
}
@file_put_contents($this->dataPath . "pocketmine.yml", $content);
}
$this->config = new Config($this->dataPath . "pocketmine.yml", Config::YAML, []);
$this->logger->info("Loading server properties...");
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, array(
"motd" => "Minecraft: PE Server",
"server-port" => 19132,
@ -1555,7 +1561,7 @@ class Server{
* @param Player[] $players
* @param DataPacket $packet
*/
public function broadcastPacket(array $players, DataPacket $packet){
public static function broadcastPacket(array $players, DataPacket $packet){
foreach($players as $player){
$player->dataPacket(clone $packet);
}

View File

@ -112,7 +112,7 @@ abstract class Door extends Transparent{
$pk->z = $this->z;
$pk->evid = 1003;
$pk->data = 0;
Server::getInstance()->broadcastPacket($players, $pk);
Server::broadcastPacket($players, $pk);
return true;
}
@ -131,7 +131,7 @@ abstract class Door extends Transparent{
$pk->z = $this->z;
$pk->evid = 1003;
$pk->data = 0;
Server::getInstance()->broadcastPacket($players, $pk);
Server::broadcastPacket($players, $pk);
}
return true;

View File

@ -22,7 +22,9 @@
namespace pocketmine\command\defaults;
use pocketmine\command\CommandSender;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\utils\TextFormat;
class KillCommand extends VanillaCommand{
@ -45,9 +47,14 @@ class KillCommand extends VanillaCommand{
if($sender instanceof Player){
//TODO: EntityDamageEvent
//$ev->setLastDamageCause()
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityDamageEvent($sender, EntityDamageEvent::CAUSE_SUICIDE, 1000));
if($ev->isCancelled()){
return true;
}
$sender->setLastDamageCause($ev);
$sender->setHealth(0);
//TODO: set update
$sender->sendMessage("Ouch. That look like it hurt.");
}else{
$sender->sendMessage(TextFormat::RED . "You can only perform this command as a player");

View File

@ -21,6 +21,7 @@
namespace pocketmine\entity;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\Byte;
@ -106,11 +107,11 @@ class DroppedItem extends Entity{
return true;
}
public function attack($damage, $source = "generic"){
public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){
}
public function heal($amount, $source = "generic"){
public function heal($amount){
}

View File

@ -25,6 +25,8 @@
namespace pocketmine\entity;
use pocketmine\block\Block;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityDeathEvent;
use pocketmine\event\entity\EntityDespawnEvent;
use pocketmine\event\entity\EntityLevelChangeEvent;
use pocketmine\event\entity\EntityMotionEvent;
@ -79,6 +81,8 @@ abstract class Entity extends Position implements Metadatable{
/** @var Chunk */
public $chunk;
protected $lastDamageCause = null;
public $lastX;
public $lastY;
public $lastZ;
@ -242,9 +246,15 @@ abstract class Entity extends Position implements Metadatable{
}
}
abstract function attack($damage, $source = "generic");
/**
* @param float $damage
* @param int|EntityDamageEvent $source
*
* @return mixed
*/
abstract function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC);
abstract function heal($amount, $source = "generic");
abstract function heal($amount);
/**
* @return int
@ -259,9 +269,15 @@ abstract class Entity extends Position implements Metadatable{
* @param int $amount
*/
public function setHealth($amount){
if($amount < 0){
if($amount === $this->health){
return;
}
if($amount <= 0){
$this->health = 0;
$this->dead = true;
if($this->dead !== true){
$this->kill();
}
}elseif($amount > $this->getMaxHealth()){
$this->health = $this->getMaxHealth();
}else{
@ -269,6 +285,20 @@ abstract class Entity extends Position implements Metadatable{
}
}
/**
* @param int|EntityDamageEvent $type
*/
public function setLastDamageCause($type){
$this->lastDamageCause = $type;
}
/**
* @return int|EntityDamageEvent|null
*/
public function getLastDamageCause(){
return $this->lastDamageCause;
}
/**
* @return int
*/
@ -379,6 +409,8 @@ abstract class Entity extends Position implements Metadatable{
$this->close();
return false;
}elseif($this->dead === true){
$this->despawnFromAll();
}
$hasUpdate = false;
@ -447,7 +479,7 @@ abstract class Entity extends Position implements Metadatable{
[$this->id, $this->x, $this->y, $this->z, $this->yaw, $this->pitch]
];
}
$this->server->broadcastPacket($this->hasSpawned, $pk);
Server::broadcastPacket($this->hasSpawned, $pk);
}
if(!($this instanceof Player) and ($this->lastMotionX != $this->motionX or $this->lastMotionY != $this->motionY or $this->lastMotionZ != $this->motionZ)){
@ -459,7 +491,7 @@ abstract class Entity extends Position implements Metadatable{
$pk->entities = [
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
];
$this->server->broadcastPacket($this->hasSpawned, $pk);
Server::broadcastPacket($this->hasSpawned, $pk);
}
}
@ -909,7 +941,14 @@ abstract class Entity extends Position implements Metadatable{
$this->motionY = $motion->y;
$this->motionZ = $motion->z;
if(!$this->justCreated){
$this->scheduleUpdate();
if($this instanceof Player){
$pk = new SetEntityMotionPacket;
$pk->entities = [
[0, $this->motionX, $this->motionY, $this->motionZ]
];
$this->dataPacket($pk);
}
$this->updateMovement();
}
}
@ -918,6 +957,7 @@ abstract class Entity extends Position implements Metadatable{
}
public function kill(){
$this->setHealth(0);
$this->dead = true;
$this->scheduleUpdate();
}

View File

@ -75,6 +75,10 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
parent::initEntity();
}
public function getName(){
return $this->nameTag;
}
public function saveNBT(){
parent::saveNBT();
$this->namedtag->Inventory = new Enum("Inventory", []);
@ -204,12 +208,4 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
return $d;
}
public function attack($damage, $source = "generic"){
}
public function heal($amount, $source = "generic"){
}
}

View File

@ -22,6 +22,15 @@
namespace pocketmine\entity;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityDeathEvent;
use pocketmine\event\entity\EntityRegainHealthEvent;
use pocketmine\math\Vector3;
use pocketmine\network\protocol\EntityEventPacket;
use pocketmine\Server;
use pocketmine\item\Item;
abstract class Living extends Entity implements Damageable{
protected $gravity = 0.08;
@ -30,4 +39,47 @@ abstract class Living extends Entity implements Damageable{
protected function initEntity(){
}
public abstract function getName();
public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){
//TODO: attack tick limit
$pk = new EntityEventPacket();
$pk->eid = $this->getID();
$pk->event = 2; //Ouch!
Server::broadcastPacket($this->hasSpawned, $pk);
$this->setLastDamageCause($source);
$motion = new Vector3(0, 0.25, 0);
if($source instanceof EntityDamageByEntityEvent){
$e = $source->getDamager();
$motion->x = -cos(deg2rad($e->pitch)) * sin(deg2rad($e->yaw)) * 0.5;
$motion->z = cos(deg2rad($e->pitch)) * sin(deg2rad($e->yaw)) * 0.5;
}
$this->setMotion($motion);
$this->setHealth($this->getHealth() - $damage);
}
public function heal($amount){
$this->server->getPluginManager()->callEvent($ev = new EntityRegainHealthEvent($this, $amount));
if($ev->isCancelled()){
return;
}
$this->setHealth($this->getHealth() + $amount);
}
public function kill(){
parent::kill();
$this->server->getPluginManager()->callEvent($ev = new EntityDeathEvent($this, $this->getDrops()));
foreach($ev->getDrops() as $item){
$this->getLevel()->dropItem($this, $item);
}
}
/**
* @return Item[]
*/
public function getDrops(){
return [];
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\event\entity;
use pocketmine\entity\Entity;
use pocketmine\event\Cancellable;
class EntityDamageByEntityEvent extends EntityDamageEvent{
public static $handlerList = null;
/** @var Entity */
private $damager;
/**
* @param Entity $damager
* @param Entity $entity
* @param int $cause
* @param int|int[] $damage
*/
public function __construct(Entity $damager, Entity $entity, $cause, $damage){
$this->damager = $damager;
parent::__construct($entity, $cause, $damage);
}
/**
* @return Entity
*/
public function getDamager(){
return $this->damager;
}
}

View File

@ -0,0 +1,147 @@
<?php
/**
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\event\entity;
use pocketmine\entity\Entity;
use pocketmine\event\Cancellable;
class EntityDamageEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
const MODIFIER_BASE = 0;
const MODIFIER_ARMOR = 1;
const CAUSE_CONTACT = 0;
const CAUSE_ENTITY_ATTACK = 1;
const CAUSE_PROJECTILE = 2;
const CAUSE_SUFFOCATION = 3;
const CAUSE_FALL = 4;
const CAUSE_FIRE = 5;
const CAUSE_FIRE_TICK = 6;
const CAUSE_LAVA = 7;
const CAUSE_DROWNING = 8;
const CAUSE_BLOCK_EXPLOSION = 9;
const CAUSE_ENTITY_EXPLOSION = 10;
const CAUSE_VOID = 11;
const CAUSE_SUICIDE = 12;
const CAUSE_MAGIC = 13;
const CAUSE_CUSTOM = 14;
private $cause;
/** @var array */
private $modifiers;
private $originals;
/**
* @param Entity $entity
* @param int $cause
* @param int|int[] $damage
*
* @throws \Exception
*/
public function __construct(Entity $entity, $cause, $damage){
$this->entity = $entity;
$this->cause = $cause;
if(is_array($damage)){
$this->modifiers = $damage;
}else{
$this->modifiers = [
self::MODIFIER_BASE => $damage
];
}
$this->originals = $this->modifiers;
if(!isset($this->modifiers[self::MODIFIER_BASE])){
throw new \Exception("BASE Damage modifier missing");
}
}
/**
* @return int
*/
public function getCause(){
return $this->cause;
}
/**
* @param int $type
*
* @return int
*/
public function getOriginalDamage($type = self::MODIFIER_BASE){
if(isset($this->originals[$type])){
return $this->originals[$type];
}
return 0;
}
/**
* @param int $type
*
* @return int
*/
public function getDamage($type = self::MODIFIER_BASE){
if(isset($this->modifiers[$type])){
return $this->modifiers[$type];
}
return 0;
}
/**
* @param float $damage
* @param int $type
*
* @throws \UnexpectedValueException
*/
public function setDamage($damage, $type = self::MODIFIER_BASE){
if(!isset($this->modifiers[$type])){
throw new \UnexpectedValueException($type ." is not applicable to ".$this->getEntity());
}
$this->modifiers[$type] = $damage;
}
/**
* @param int $type
*
* @return bool
*/
public function isApplicable($type){
return isset($this->modifiers[$type]);
}
/**
* @return int
*/
public function getFinalDamage(){
$damage = 0;
foreach($this->modifiers as $type => $d){
$damage += $d;
}
return $damage;
}
}

View File

@ -0,0 +1,68 @@
<?php
/**
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\event\entity;
use pocketmine\block\Block;
use pocketmine\entity\Entity;
use pocketmine\entity\Living;
use pocketmine\event\Cancellable;
use pocketmine\item\Item;
use pocketmine\level\Position;
class EntityDeathEvent extends EntityEvent{
public static $handlerList = null;
/** @var Item[] */
private $drops = [];
/**
* @param Living $entity
* @param Item[] $drops
*/
public function __construct(Living $entity, array $drops = []){
$this->entity = $entity;
$this->drops = $drops;
}
/**
* @return Living
*/
public function getEntity(){
return $this->entity;
}
/**
* @return \pocketmine\item\Item[]
*/
public function getDrops(){
return $this->drops;
}
/**
* @param Item[] $drops
*/
public function setDrops(array $drops){
$this->drops = $drops;
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\event\entity;
use pocketmine\entity\Entity;
use pocketmine\event\Cancellable;
class EntityRegainHealthEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
//TODO: add cause
private $amount;
/**
* @param Entity $entity
* @param float $amount
*/
public function __construct(Entity $entity, $amount){
$this->entity = $entity;
$this->amount = $amount;
}
/**
* @return float
*/
public function getAmount(){
return $this->amount;
}
/**
* @param float $amount
*/
public function setAmount($amount){
$this->amount = $amount;
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\event\player;
use pocketmine\item\Item;
use pocketmine\Player;
use pocketmine\event\entity\EntityDeathEvent;
class PlayerDeathEvent extends EntityDeathEvent{
public static $handlerList = null;
private $deathMessage;
/**
* @param Player $entity
* @param Item[] $drops
* @param string $deathMessage
*/
public function __construct(Player $entity, array $drops, $deathMessage){
parent::__construct($entity, $drops);
$this->deathMessage = $deathMessage;
}
/**
* @return Player
*/
public function getEntity(){
return $this->entity;
}
public function getDeathMessage(){
return $this->deathMessage;
}
public function setDeathMessage($deathMessage){
$this->deathMessage = $deathMessage;
}
}

View File

@ -48,7 +48,7 @@ class ChestInventory extends ContainerInventory{
$pk->z = $this->getHolder()->getZ();
$pk->case1 = 1;
$pk->case2 = 2;
Server::getInstance()->broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk);
Server::broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk);
}
}
@ -60,7 +60,7 @@ class ChestInventory extends ContainerInventory{
$pk->z = $this->getHolder()->getZ();
$pk->case1 = 1;
$pk->case2 = 0;
Server::getInstance()->broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk);
Server::broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk);
}
parent::onClose($who);
}

View File

@ -147,7 +147,7 @@ class Explosion{
$pk->z = $this->source->z;
$pk->radius = $this->size;
$pk->records = $send;
Server::getInstance()->broadcastPacket($this->level->getPlayers(), $pk);
Server::broadcastPacket($this->level->getPlayers(), $pk);
}
}