From f55fb8d4903b5d5556cd6e239a7298190dab471a Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Mon, 3 Jun 2013 16:31:33 +0200 Subject: [PATCH] Player actions and bows [WiP] --- src/API/LevelAPI.php | 2 +- src/Player.php | 71 ++++++++++++++++-- src/constants/GeneralConstants.php | 1 + src/network/CustomPacketHandler.php | 27 ++++++- src/world/Entity.php | 110 +++++++++++++++++----------- src/world/Level.php | 43 +++++++++-- 6 files changed, 196 insertions(+), 58 deletions(-) diff --git a/src/API/LevelAPI.php b/src/API/LevelAPI.php index 7e5094c9c9..4605e7a141 100644 --- a/src/API/LevelAPI.php +++ b/src/API/LevelAPI.php @@ -174,7 +174,7 @@ class LevelAPI{ $e = $this->server->api->entity->add($this->levels[$name], ENTITY_FALLING, $entity["id"], $entity); $e->setPosition(new Vector3($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2]), $entity["Rotation"][0], $entity["Rotation"][1]); $e->setHealth($entity["Health"]); - }elseif($entity["id"] === OBJECT_PAINTING){ //Painting + }elseif($entity["id"] === OBJECT_PAINTING or $entity["id"] === OBJECT_ARROW){ //Painting $e = $this->server->api->entity->add($this->levels[$name], ENTITY_OBJECT, $entity["id"], $entity); $e->setPosition(new Vector3($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2]), $entity["Rotation"][0], $entity["Rotation"][1]); $e->setHealth($entity["Health"]); diff --git a/src/Player.php b/src/Player.php index 170e52768a..e527659d09 100644 --- a/src/Player.php +++ b/src/Player.php @@ -42,6 +42,7 @@ class Player{ private $username; private $iusername; private $eid = false; + private $startAction = false; public $data; public $entity = false; public $auth = false; @@ -435,6 +436,12 @@ class Player{ } $this->dataPacket(MC_PLAYER_EQUIPMENT, $data); + break; + case "player.action": + if($data["eid"] === $this->eid or $data["player"]->level !== $this->level){ + break; + } + $this->dataPacket(MC_USE_ITEM, $data); break; case "entity.move": if($data->eid === $this->eid or $data->level !== $this->level){ @@ -946,6 +953,7 @@ class Player{ $this->evid[] = $this->server->event("entity.metadata", array($this, "eventHandler")); $this->evid[] = $this->server->event("player.equipment.change", array($this, "eventHandler")); $this->evid[] = $this->server->event("player.armor", array($this, "eventHandler")); + $this->evid[] = $this->server->event("player.action", array($this, "eventHandler")); $this->evid[] = $this->server->event("player.pickup", array($this, "eventHandler")); $this->evid[] = $this->server->event("tile.container.slot", array($this, "eventHandler")); $this->evid[] = $this->server->event("tile.update", array($this, "eventHandler")); @@ -1015,6 +1023,10 @@ class Player{ }elseif($this->itemEnforcement === true){ $this->sendInventory(); } + if($this->entity->inAction === true){ + $this->entity->inAction = false; + $this->entity->updateMetadata(); + } break; case MC_REQUEST_CHUNK: if($this->spawned === false){ @@ -1026,13 +1038,50 @@ class Player{ break; } $data["eid"] = $this->eid; - if($this->blocked === true or Utils::distance($this->entity->position, $data) > 10){ - break; - }elseif(!$this->hasItem($data["block"], $data["meta"]) and $this->itemEnforcement === true){ - $this->sendInventory(); + $data["player"] = $this; + if($data["face"] >= 0 and $data["face"] <= 5){ //Use Block, place + if($this->entity->inAction === true){ + $this->entity->inAction = false; + $this->entity->updateMetadata(); + } + if($this->blocked === true or Utils::distance($this->entity->position, $data) > 10){ + break; + }elseif(!$this->hasItem($data["block"], $data["meta"]) and $this->itemEnforcement === true){ + $this->sendInventory(); + break; + } + $this->server->api->block->playerBlockAction($this, new Vector3($data["x"], $data["y"], $data["z"]), $data["face"], $data["fx"], $data["fy"], $data["fz"]); + }elseif($data["face"] === 0xFF and $this->server->handle("player.action", $data) !== false){ + $this->entity->inAction = true; + $this->startAction = microtime(true); + $this->entity->updateMetadata(); + } + break; + case MC_PLAYER_ACTION: + if($this->spawned === false){ break; } - $this->server->api->block->playerBlockAction($this, new Vector3($data["x"], $data["y"], $data["z"]), $data["face"], $data["fx"], $data["fy"], $data["fz"]); + if($this->entity->inAction === true){ + switch($data["action"]){ + case 5: //Shot arrow + if($this->equipment->getID() === BOW){ + if($this->startAction !== false){ + $time = microtime(true) - $this->startAction; + $d = array( + "x" => $this->entity->x, + "y" => $this->entity->y + 1.6, + "z" => $this->entity->z, + ); + $e = $this->server->api->entity->add($this->level, ENTITY_OBJECT, OBJECT_ARROW, $d); + $this->server->api->entity->spawnToAll($this->level, $e->eid); + } + } + break; + } + } + $this->startAction = false; + $this->entity->inAction = false; + $this->entity->updateMetadata(); break; case MC_REMOVE_BLOCK: if($this->spawned === false){ @@ -1050,6 +1099,10 @@ class Player{ $data["eid"] = $this->eid; $data["player"] = $this; $this->server->handle("player.armor", $data); + if($this->entity->inAction === true){ + $this->entity->inAction = false; + $this->entity->updateMetadata(); + } break; case MC_INTERACT: if($this->spawned === false){ @@ -1163,6 +1216,10 @@ class Player{ break; } $data["eid"] = $this->eid; + if($this->entity->inAction === true){ + $this->entity->inAction = false; + $this->entity->updateMetadata(); + } switch($data["event"]){ case 9: //Eating $items = array( @@ -1205,6 +1262,10 @@ class Player{ $this->server->api->entity->drop(new Position($this->entity->x - 0.5, $this->entity->y, $this->entity->z - 0.5, $this->level), $item); } } + if($this->entity->inAction === true){ + $this->entity->inAction = false; + $this->entity->updateMetadata(); + } break; case MC_SIGN_UPDATE: if($this->spawned === false){ diff --git a/src/constants/GeneralConstants.php b/src/constants/GeneralConstants.php index 79fc150884..25960a9fa2 100644 --- a/src/constants/GeneralConstants.php +++ b/src/constants/GeneralConstants.php @@ -61,6 +61,7 @@ define("ENTITY_MOB", 2); define("MOB_PIGMAN", 36); define("ENTITY_OBJECT", 3); + define("OBJECT_ARROW", 80); define("OBJECT_PAINTING", 83); define("ENTITY_ITEM", 4); diff --git a/src/network/CustomPacketHandler.php b/src/network/CustomPacketHandler.php index 89774c79d7..ac705bdc4f 100644 --- a/src/network/CustomPacketHandler.php +++ b/src/network/CustomPacketHandler.php @@ -554,13 +554,34 @@ class CustomPacketHandler{ $this->data["fy"] = Utils::readFloat($this->get(4)); $this->data["fz"] = Utils::readFloat($this->get(4)); }else{ - /*$this->raw .= Utils::writeByte($this->data["action"]); + $this->raw .= Utils::writeInt($this->data["x"]); + $this->raw .= Utils::writeInt($this->data["y"]); + $this->raw .= Utils::writeInt($this->data["z"]); + $this->raw .= Utils::writeInt($this->data["face"]); + $this->raw .= Utils::writeShort($this->data["block"]); + $this->raw .= Utils::writeByte($this->data["meta"]); $this->raw .= Utils::writeInt($this->data["eid"]); - $this->raw .= Utils::writeInt($this->data["target"]);*/ + $this->raw .= Utils::writeFloat($this->data["fx"]); + $this->raw .= Utils::writeFloat($this->data["fy"]); + $this->raw .= Utils::writeFloat($this->data["fz"]); } break; case MC_PLAYER_ACTION: - //TODO + if($this->c === false){ + $this->data["action"] = Utils::readInt($this->get(4)); + $this->data["x"] = Utils::readInt($this->get(4)); + $this->data["y"] = Utils::readInt($this->get(4)); + $this->data["z"] = Utils::readInt($this->get(4)); + $this->data["face"] = Utils::readInt($this->get(4)); + $this->data["eid"] = Utils::readInt($this->get(4)); + }else{ + $this->raw .= Utils::writeInt($this->data["action"]); + $this->raw .= Utils::writeInt($this->data["x"]); + $this->raw .= Utils::writeInt($this->data["y"]); + $this->raw .= Utils::writeInt($this->data["z"]); + $this->raw .= Utils::writeInt($this->data["face"]); + $this->raw .= Utils::writeInt($this->data["eid"]); + } break; case MC_SET_ENTITY_DATA: if($this->c === false){ diff --git a/src/world/Entity.php b/src/world/Entity.php index 661fa8cecb..239fc84185 100644 --- a/src/world/Entity.php +++ b/src/world/Entity.php @@ -54,10 +54,12 @@ class Entity extends Position{ private $tickCounter; private $speedMeasure = array(0, 0, 0, 0, 0); private $server; + private $isStatic; public $level; public $lastUpdate; public $check = true; public $size = 1; + public $inAction = false; function __construct(Level $level, $eid, $class, $type = 0, $data = array()){ $this->level = $level; @@ -80,6 +82,7 @@ class Entity extends Position{ $this->lastUpdate = $this->spawntime = microtime(true); $this->dead = false; $this->closed = false; + $this->isStatic = false; $this->name = ""; $this->tickCounter = 0; $this->server->query("INSERT OR REPLACE INTO entities (EID, level, type, class, health, hasUpdate) VALUES (".$this->eid.", '".$this->level->getName()."', ".$this->type.", ".$this->class.", ".$this->health.", 0);"); @@ -130,6 +133,9 @@ class Entity extends Position{ $this->setHealth(1, "generic"); //$this->setName((isset($objects[$this->type]) ? $objects[$this->type]:$this->type)); $this->size = 1; + if($this->type === OBJECT_PAINTING){ + $this->isStatic = true; + } break; } $this->updateLast(); @@ -346,7 +352,7 @@ class Entity extends Position{ $this->tickCounter = 0; } - if(($this->class === ENTITY_ITEM or $this->class === ENTITY_MOB or $this->class === ENTITY_PLAYER or $this->class === ENTITY_FALLING)){ + if($this->isStatic === false){ $startX = ((int) round($this->x - 0.5)) - 1; $y = (int) round($this->y - 1); $startZ = ((int) round($this->z - 0.5)) - 1; @@ -372,56 +378,58 @@ class Entity extends Position{ break; } } - if($this->class === ENTITY_ITEM or $this->class === ENTITY_MOB or $this->class === ENTITY_FALLING){ + if($this->class !== ENTITY_PLAYER){ $update = false; - $drag = 0.4 * $tdiff; - if($this->speedX != 0){ - $this->speedX -= $this->speedX * $drag; - $this->x += $this->speedX * $tdiff; - $update = true; - } - if($this->speedZ != 0){ - $this->speedZ -= $this->speedZ * $drag; - $this->z += $this->speedZ * $tdiff; - $update = true; - } - if($this->speedY != 0){ - $this->speedY -= $this->speedY * $drag; - $ny = $this->y + $this->speedY * $tdiff; - if($ny <= $this->y){ - $x = (int) ($this->x - 0.5); - $z = (int) ($this->z - 0.5); - $lim = (int) floor($ny); - for($y = (int) ceil($this->y) - 1; $y >= $lim; --$y){ - if($this->level->getBlock(new Vector3($x, $y, $z))->isSolid === true){ - $ny = $y + 1; - $this->speedY = 0; - $this->support = true; - if($this->class === ENTITY_FALLING){ - $this->y = $ny; - $fall = $this->level->getBlock(new Vector3(intval($this->x - 0.5), intval(ceil($this->y)), intval($this->z - 0.5))); - $down = $this->level->getBlock(new Vector3(intval($this->x - 0.5), intval(ceil($this->y) - 1), intval($this->z - 0.5))); - if($fall->isFullBlock === false or $down->isFullBlock === false){ - $this->server->api->entity->drop($this, BlockAPI::getItem($this->data["Tile"] & 0xFFFF, 0, 1), true); - }else{ - $this->level->setBlock($fall, BlockAPI::get($this->data["Tile"]), true, false, true); + if($this->class !== ENTITY_OBJECT or $support === false){ + $drag = 0.4 * $tdiff; + if($this->speedX != 0){ + $this->speedX -= $this->speedX * $drag; + $this->x += $this->speedX * $tdiff; + $update = true; + } + if($this->speedZ != 0){ + $this->speedZ -= $this->speedZ * $drag; + $this->z += $this->speedZ * $tdiff; + $update = true; + } + if($this->speedY != 0){ + $this->speedY -= $this->speedY * $drag; + $ny = $this->y + $this->speedY * $tdiff; + if($ny <= $this->y){ + $x = (int) ($this->x - 0.5); + $z = (int) ($this->z - 0.5); + $lim = (int) floor($ny); + for($y = (int) ceil($this->y) - 1; $y >= $lim; --$y){ + if($this->level->getBlock(new Vector3($x, $y, $z))->isSolid === true){ + $ny = $y + 1; + $this->speedY = 0; + $this->support = true; + if($this->class === ENTITY_FALLING){ + $this->y = $ny; + $fall = $this->level->getBlock(new Vector3(intval($this->x - 0.5), intval(ceil($this->y)), intval($this->z - 0.5))); + $down = $this->level->getBlock(new Vector3(intval($this->x - 0.5), intval(ceil($this->y) - 1), intval($this->z - 0.5))); + if($fall->isFullBlock === false or $down->isFullBlock === false){ + $this->server->api->entity->drop($this, BlockAPI::getItem($this->data["Tile"] & 0xFFFF, 0, 1), true); + }else{ + $this->level->setBlock($fall, BlockAPI::get($this->data["Tile"]), true, false, true); + } + $this->server->api->handle("entity.motion", $this); + $this->close(); + return; } - $this->server->api->handle("entity.motion", $this); - $this->close(); - return; + break; } - break; } } + $this->y = $ny; + $update = true; } - $this->y = $ny; - $update = true; } if($support === false){ $this->speedY -= ($this->class === ENTITY_FALLING ? 18:32) * $tdiff; $update = true; - }elseif($this->speedY <= 0.1){ + }elseif($this->class === ENTITY_OBJECT or $this->speedY <= 0.1){ $this->speedX = 0; $this->speedY = 0; $this->speedZ = 0; @@ -435,7 +443,7 @@ class Entity extends Position{ $this->server->api->handle("entity.motion", $this); } - }elseif($this->class === ENTITY_PLAYER and ($this->player instanceof Player)){ + }elseif($this->player instanceof Player){ if($isFlying === true and ($this->player->gamemode & 0x01) === 0x00){ if($this->fallY === false or $this->fallStart === false){ $this->fallY = $y; @@ -468,7 +476,7 @@ class Entity extends Position{ } } - if($this->class !== ENTITY_OBJECT and ($this->last[0] != $this->x or $this->last[1] != $this->y or $this->last[2] != $this->z or $this->last[3] != $this->yaw or $this->last[4] != $this->pitch)){ + if($this->isStatic === false and ($this->last[0] != $this->x or $this->last[1] != $this->y or $this->last[2] != $this->z or $this->last[3] != $this->yaw or $this->last[4] != $this->pitch)){ if($this->class === ENTITY_PLAYER or ($this->last[5] + 8) < $now){ if($this->server->api->handle("entity.move", $this) === false){ if($this->class === ENTITY_PLAYER){ @@ -510,7 +518,8 @@ class Entity extends Position{ public function getMetadata(){ $flags = 0; $flags |= $this->fire > 0 ? 1:0; - $flags |= ($this->crouched === true ? 1:0) << 1; + $flags |= ($this->crouched === true ? 0b10:0) << 1; + $flags |= ($this->inAction === true ? 0b10000:0); $d = array( 0 => array("type" => 0, "value" => $flags), 1 => array("type" => 1, "value" => $this->air), @@ -600,6 +609,21 @@ class Entity extends Position{ "direction" => $this->getDirection(), "title" => $this->data["Motive"], )); + }elseif($this->type === OBJECT_ARROW){ + $player->dataPacket(MC_ADD_ENTITY, array( + "eid" => $this->eid, + "type" => $this->type, + "x" => $this->x, + "y" => $this->y, + "z" => $this->z, + "did" => 0, + )); + $player->dataPacket(MC_SET_ENTITY_MOTION, array( + "eid" => $this->eid, + "speedX" => (int) ($this->speedX * 400), + "speedY" => (int) ($this->speedY * 400), + "speedZ" => (int) ($this->speedZ * 400), + )); } break; case ENTITY_FALLING: diff --git a/src/world/Level.php b/src/world/Level.php index 98ced637ed..e2d9b1699f 100644 --- a/src/world/Level.php +++ b/src/world/Level.php @@ -144,21 +144,52 @@ class Level{ ), ); }elseif($entity->class === ENTITY_OBJECT){ + if($entity->type === OBJECT_PAINTING){ + $entities[] = array( + "id" => $entity->type, + "TileX" => $entity->x, + "TileX" => $entity->y, + "TileX" => $entity->z, + "Health" => $entity->health, + "Motive" => $entity->data["Motive"], + "Pos" => array( + 0 => $entity->x, + 1 => $entity->y, + 2 => $entity->z, + ), + "Rotation" => array( + 0 => $entity->yaw, + 1 => $entity->pitch, + ), + ); + }else{ + $entities[] = array( + "id" => $entity->type, + "Health" => $entity->health, + "Pos" => array( + 0 => $entity->x, + 1 => $entity->y, + 2 => $entity->z, + ), + "Rotation" => array( + 0 => $entity->yaw, + 1 => $entity->pitch, + ), + ); + } + }elseif($entity->class === ENTITY_FALLING){ $entities[] = array( "id" => $entity->type, - "TileX" => $entity->x, - "TileX" => $entity->y, - "TileX" => $entity->z, "Health" => $entity->health, - "Motive" => $entity->data["Motive"], + "Tile" => $entity->data["Tile"], "Pos" => array( 0 => $entity->x, 1 => $entity->y, 2 => $entity->z, ), "Rotation" => array( - 0 => $entity->yaw, - 1 => $entity->pitch, + 0 => 0, + 1 => 0, ), ); }elseif($entity->class === ENTITY_ITEM){