Skip to content
This repository was archived by the owner on Jan 18, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
f022641
Version dump to 0.1.0-REVIVAL
PresentKim Jul 28, 2018
b093f2b
Support api 3.0.0, 4.0.0
PresentKim Jul 28, 2018
ab2e0b9
Reformat code
PresentKim Jul 28, 2018
0b4edb2
Fix protocol namespace
PresentKim Jul 28, 2018
23a002b
Remove PlayerInputPacket : Already implemented
PresentKim Jul 28, 2018
4b1aeb7
BoatItem : Extends from already implemented boat item
PresentKim Jul 28, 2018
571aef1
Main : Set alias of entity\Boat to BoatEntity
PresentKim Jul 28, 2018
316c1f3
Main : Use "::class"
PresentKim Jul 28, 2018
47cb303
BoatEntity : Remove useless override
PresentKim Jul 28, 2018
e6d48ca
Add return types
PresentKim Jul 28, 2018
e59dcac
BoatEntity : Remove obsolete parameter of attack()
PresentKim Jul 28, 2018
429c418
BoatEntity : Remove useless override
PresentKim Jul 28, 2018
d55a49b
BoatEntity : Set max hp on initEntity()
PresentKim Jul 28, 2018
208f347
Main : Register item to ItemFactory
PresentKim Jul 28, 2018
bfcad2f
Main : Register creative item with direct constructed item instance
PresentKim Jul 28, 2018
6b1a80e
Main : Register recipe to CraftingManager
PresentKim Jul 28, 2018
d683630
Main : Use ShapelessRecipe instead of BigShapelessRecipe
PresentKim Jul 28, 2018
ec480c9
Main : Saperate event listener
PresentKim Jul 28, 2018
605d111
Main : Fix WOODEN_PLANK to WOODEN_PLANKS
PresentKim Jul 28, 2018
a112a81
BoatItem : Change the reduce item count code
PresentKim Jul 28, 2018
884658a
BoatItem : Remove redundant Level parameter from onActivate()
PresentKim Jul 28, 2018
e9d56bd
BoatItem : Fix BoatEntity construct
PresentKim Jul 28, 2018
6da0488
Refactoring about packets
PresentKim Jul 28, 2018
99d34b8
Main : Fix Item::get() parameter
PresentKim Jul 28, 2018
ac2eaa4
Version dump to 0.2.0-REVIVAL
PresentKim Jul 28, 2018
eb511a1
BoatEntity : Add properties about bounding box
PresentKim Jul 28, 2018
5a7344b
EventListener : Unhandle InteractPacket when unknown action
PresentKim Jul 28, 2018
76d03b3
EventListener : Handle InventoryTransactionPacket for ride boat
PresentKim Jul 28, 2018
62c6ebd
Use constants for more readability
PresentKim Jul 28, 2018
34b2101
EventListener : Merge if-statement for more readability
PresentKim Jul 28, 2018
e0530f4
EventListener : Handle MoveEntityAbsolutePacket instead of MovePlayer…
PresentKim Jul 28, 2018
b31a6e2
EventListener : Replace rider and vehicle
PresentKim Jul 28, 2018
53afafb
EventListener : Ready to handle PlayerInputPacket
PresentKim Jul 28, 2018
742f213
EventListener : Cancel event of data packets
PresentKim Jul 28, 2018
6bd385e
BoatItem : Remove unused method canBeActivated()
PresentKim Jul 28, 2018
50cbcf0
BoatItem : Prevent reduce item when player is creative
PresentKim Jul 28, 2018
3eeee6d
BoatItem : Spawn boat on center
PresentKim Jul 28, 2018
90778af
EventListener : Cancel all interact to boat
PresentKim Jul 28, 2018
ee6192f
EventListener : Filter out transaction when is not interact action
PresentKim Jul 28, 2018
9053449
EventListener : Rename handle methods
PresentKim Jul 28, 2018
b9a55c4
Add PHP DOCs
PresentKim Jul 28, 2018
3d25519
BoatEntity : Set visibiliy of NETWORK_ID and use constant
PresentKim Jul 28, 2018
264d778
Support boat wood type
PresentKim Jul 28, 2018
da37e95
Main : Remove addCreativeItem() is already exists
PresentKim Jul 28, 2018
751cb4e
BoatEntity : Set stactable to true
PresentKim Jul 28, 2018
1e82675
BoatItem : Fix logic of `Reduce boat item count`
PresentKim Jul 28, 2018
4335656
BoatEntity : Regenerate 1⁄10 per tick
PresentKim Jul 28, 2018
b4cdc8c
BoatEntity : Drop item when boat death, Use getDrops()
PresentKim Jul 28, 2018
a7c39c7
EventListener : Ready to handle SetEntityMotionPacket
PresentKim Jul 28, 2018
0b71c99
Move link methods to BoatEntity from EventListener
PresentKim Jul 28, 2018
b98a758
BoatEntity : Not teleport when absoluteMove()
PresentKim Jul 28, 2018
b27fabf
EventListener : Rename $boat to $entity
PresentKim Jul 28, 2018
0625231
BoatEntity : Lock the rider rotation -90 to 90
PresentKim Jul 28, 2018
b07d478
BoatEntity : Set the rider seat position to y + 1
PresentKim Jul 28, 2018
e1de9d8
BoatEntity : Use Server::broadcastPacket()
PresentKim Jul 28, 2018
e1ba26a
BoatEntity : Not allow null on absoluteMove() $yaw, $pitch
PresentKim Jul 28, 2018
b25a39a
Merge pull request #1 from Blugin/fix-according-to-current-system
PresentKim Jul 28, 2018
9b46c50
EventListener : Fix an error that can't attack the boat
PresentKim Jul 28, 2018
2660e45
change base class of Boat class
eternalharvest Jun 28, 2019
838475d
handle AnimatePacket
eternalharvest Jun 30, 2019
70cb24d
send entity link at boat spawning when boat has rider
eternalharvest Jul 2, 2019
7ad8492
Merge pull request #3 from eternalharvest/feature/animation
PresentKim Jul 2, 2019
7018112
Merge pull request #2 from eternalharvest/patch1
PresentKim Jul 2, 2019
5128273
Merge branch 'master' into feature/link_at_spawn_player
PresentKim Jul 2, 2019
50a7441
Merge pull request #4 from eternalharvest/feature/link_at_spawn_player
PresentKim Jul 2, 2019
62b5e61
blame my self!! remove duplicate definition (already defined in pmmp)
eternalharvest Jul 2, 2019
a8e66e7
Merge pull request #5 from eternalharvest/hotfix/remove_duplicate_def…
PresentKim Jul 2, 2019
da376a1
Source updated successfully.
skh6075 Feb 26, 2021
25cf4ff
Source updated successfully.
skh6075 Feb 26, 2021
6c2d02d
Source updated successfully.
skh6075 Feb 26, 2021
73b7f0b
Modified the onload and onable parts.
skh6075 Feb 26, 2021
df4e471
Source Alignment and Source Modified
skh6075 Feb 26, 2021
f9ea5d8
Modified the part related to the item.
skh6075 Feb 26, 2021
0f58682
update EventListener.php
Jul 22, 2021
9c02778
Merge pull request #6 from sky-min/master
skh6075 Aug 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions plugin.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
name: Boat
main: onebone\boat\Main
version: "1.0"
version: 0.2.0-REVIVAL
author: onebone
api: [1.12.0]
api: [3.0.0, 4.0.0]
...
106 changes: 23 additions & 83 deletions src/onebone/boat/Main.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,89 +2,29 @@

namespace onebone\boat;

use pocketmine\plugin\PluginBase;
use pocketmine\event\Listener;
use pocketmine\inventory\BigShapelessRecipe;
use pocketmine\item\Item;
use pocketmine\entity\Entity;
use pocketmine\event\server\DataPacketReceiveEvent;
use pocketmine\network\protocol\InteractPacket;
use pocketmine\network\protocol\SetEntityLinkPacket;
use pocketmine\network\protocol\MovePlayerPacket;
use pocketmine\event\player\PlayerQuitEvent;

use onebone\boat\entity\Boat as BoatEntity;
use onebone\boat\item\Boat as BoatItem;
use onebone\boat\packet\PlayerInputPacket;
use onebone\boat\entity\Boat;

class Main extends PluginBase implements Listener{
private $riding = [];

public function onEnable(){
$this->getServer()->getPluginManager()->registerEvents($this, $this);

Item::$list[333] = BoatItem::class;
Item::addCreativeItem(new Item(333));
$this->getServer()->addRecipe((new BigShapelessRecipe(Item::get(333, 0, 1)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 5))->addIngredient(Item::get(Item::WOODEN_SHOVEL, null, 1)));

Entity::registerEntity("\\onebone\\boat\\entity\\Boat", true);

$this->getServer()->getNetwork()->registerPacket(0xae, PlayerInputPacket::class);
}

public function onQuit(PlayerQuitEvent $event){
if(isset($this->riding[$event->getPlayer()->getName()])){
unset($this->riding[$event->getPlayer()->getName()]);
}
}

public function onPacketReceived(DataPacketReceiveEvent $event){
$packet = $event->getPacket();
$player = $event->getPlayer();
if($packet instanceof InteractPacket){
$boat = $player->getLevel()->getEntity($packet->target);
if($boat instanceof Boat){
if($packet->action === 1){
$pk = new SetEntityLinkPacket();
$pk->from = $boat->getId();
$pk->to = $player->getId();
$pk->type = 2;

$this->getServer()->broadcastPacket($player->getLevel()->getPlayers(), $pk);
$pk = new SetEntityLinkPacket();
$pk->from = $boat->getId();
$pk->to = 0;
$pk->type = 2;
$player->dataPacket($pk);

$this->riding[$player->getName()] = $packet->target;
}elseif($packet->action === 3){
$pk = new SetEntityLinkPacket();
$pk->from = $boat->getId();
$pk->to = $player->getId();
$pk->type = 3;

$this->getServer()->broadcastPacket($player->getLevel()->getPlayers(), $pk);
$pk = new SetEntityLinkPacket();
$pk->from = $boat->getId();
$pk->to = 0;
$pk->type = 3;
$player->dataPacket($pk);
use onebone\boat\listener\EventListener;
use pocketmine\entity\Entity;
use pocketmine\inventory\ShapelessRecipe;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\plugin\PluginBase;

if(isset($this->riding[$event->getPlayer()->getName()])){
unset($this->riding[$event->getPlayer()->getName()]);
}
}
}
}elseif($packet instanceof MovePlayerPacket){
if(isset($this->riding[$player->getName()])){
$boat = $player->getLevel()->getEntity($this->riding[$player->getName()]);
if($boat instanceof Boat){
$boat->x = $packet->x;
$boat->y = $packet->y;
$boat->z = $packet->z;
}
}
}
}
class Main extends PluginBase{
public function onLoad(): void{
Entity::registerEntity(BoatEntity::class, true);
ItemFactory::registerItem($item = new BoatItem(), true);
if (!Item::isCreativeItem($item))
Item::addCreativeItem($item);
}
public function onEnable() : void{
$this->getServer()->getCraftingManager()->registerShapelessRecipe(new ShapelessRecipe([
Item::get(Item::WOODEN_PLANKS, 0, 5),
Item::get(Item::WOODEN_SHOVEL, 0, 1)
], [Item::get(Item::BOAT, 0, 1)]));
$this->getServer()->getPluginManager()->registerEvents(new EventListener(), $this);
}
}
236 changes: 182 additions & 54 deletions src/onebone/boat/entity/Boat.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,192 @@

namespace onebone\boat\entity;

use pocketmine\entity\Entity;
use pocketmine\network\protocol\AddEntityPacket;
use pocketmine\event\entity\EntityDeathEvent;
use onebone\boat\item\Boat as BoatItem;
use pocketmine\network\mcpe\protocol\AddActorPacket;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\math\Vector3;
use pocketmine\block\Planks;
use pocketmine\entity\Entity;
use pocketmine\entity\Vehicle;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\network\protocol\EntityEventPacket;
use pocketmine\item\Item;

class Boat extends Entity{
const NETWORK_ID = 90;

public function spawnTo(Player $player){
$pk = new AddEntityPacket();
$pk->eid = $this->getId();
$pk->type = self::NETWORK_ID;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$pk->speedX = 0;
$pk->speedY = 0;
$pk->speedZ = 0;
$pk->yaw = 0;
$pk->pitch = 0;
$pk->metadata = $this->dataProperties;
$player->dataPacket($pk);

parent::spawnTo($player);
}

public function attack($damage, EntityDamageEvent $source){
parent::attack($damage, $source);

if(!$source->isCancelled()){
$pk = new EntityEventPacket();
$pk->eid = $this->id;
$pk->event = EntityEventPacket::HURT_ANIMATION;
foreach($this->getLevel()->getPlayers() as $player){
$player->dataPacket($pk);
}
}
}

public function kill(){
parent::kill();
use pocketmine\event\entity\EntityRegainHealthEvent;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\SetActorLinkPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\types\EntityLink;

class Boat extends Vehicle{

public const NETWORK_ID = self::BOAT;

public const TAG_WOOD_ID = "WoodID";

public const ACTION_ROW_RIGHT = 128;
public const ACTION_ROW_LEFT = 129;

public $height = 0.455;

public $width = 1.4;

/** @var float */
public $gravity = 0.0;
/** @var float */
public $drag = 0.1;

public ?Entity $rider = null;


public function initEntity() : void{
parent::initEntity();

$woodId = $this->namedtag->getInt(self::TAG_WOOD_ID, Planks::OAK);
if($woodId > 5 || $woodId < 0){
$woodId = Planks::OAK;
}

$this->setWoodId($woodId);
$this->setMaxHealth(4);
$this->setGenericFlag(self::DATA_FLAG_STACKABLE, true);
}

public function saveNBT() : void{
parent::saveNBT();
$this->namedtag->setInt(self::TAG_WOOD_ID, $this->getWoodId());
}

public function attack(EntityDamageEvent $source) : void{
parent::attack($source);

if(!$source->isCancelled()){
$pk = new ActorEventPacket();
$pk->entityRuntimeId = $this->id;
$pk->event = ActorEventPacket::HURT_ANIMATION;
Server::getInstance()->broadcastPacket($this->getViewers(), $pk);
}
}

protected function sendSpawnPacket(Player $player) : void{
$pk = new AddActorPacket();
$pk->type = "minecraft:boat";
$pk->entityRuntimeId = $this->getId();
$pk->position = $this->getPosition();
$pk->motion = $this->getMotion();
$pk->attributes = $this->getAttributeMap()->getAll();
$pk->metadata = $this->getDataPropertyManager()->getAll();
if ($this->rider !== null) {
$pk->links[] = new EntityLink($this->getId(), $this->rider->getId(), EntityLink::TYPE_RIDER, true, true);
}

$player->sendDataPacket($pk);
}

public function kill() : void{
parent::kill();

if($this->lastDamageCause instanceof EntityDamageByEntityEvent){
$damager = $this->lastDamageCause->getDamager();
if($damager instanceof Player and $damager->isCreative()){
return;
}
}
foreach($this->getDrops() as $item){
$this->getLevel()->dropItem($this, $item);
}
}

public function getDrops(){
return [
Item::get(333, 0, 1)
];
}

public function getSaveId(){
$class = new \ReflectionClass(static::class);
return $class->getShortName();
}
}

public function onUpdate(int $currentTick) : bool{
if($this->closed){
return false;
}

if($this->getHealth() < $this->getMaxHealth() && $currentTick % 10 === 0){
$this->heal(new EntityRegainHealthEvent($this, 1, EntityRegainHealthEvent::CAUSE_REGEN));
}

return parent::onUpdate($currentTick);
}

public function getDrops() : array{
return [
new BoatItem($this->getWoodId())
];
}

public function getWoodId() : int{
return $this->propertyManager->getInt(self::DATA_VARIANT);
}

public function setWoodId(int $woodId) : void{
$this->propertyManager->setInt(self::DATA_VARIANT, $woodId);
}

public function canLink(Entity $rider) : bool{
return $this->rider === null;
}

public function link(Entity $rider) : bool{
if($this->rider === null){
$rider->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_RIDING, true);
$rider->getDataPropertyManager()->setVector3(Entity::DATA_RIDER_SEAT_POSITION, new Vector3(0, 1, 0));
$rider->getDataPropertyManager()->setByte(self::DATA_RIDER_ROTATION_LOCKED, true);
$rider->getDataPropertyManager()->setFloat(self::DATA_RIDER_MAX_ROTATION, 90);
$rider->getDataPropertyManager()->setFloat(self::DATA_RIDER_MIN_ROTATION, -90);

$pk = new SetActorLinkPacket();
$pk->link = new EntityLink($this->getId(), $rider->getId(), EntityLink::TYPE_RIDER, true, true);
Server::getInstance()->broadcastPacket($this->getViewers(), $pk);

$this->rider = $rider;
return true;
}

return false;
}

public function unlink(Entity $rider) : bool{
if($this->rider === $rider){
$rider->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_RIDING, false);
$rider->getDataPropertyManager()->setVector3(Entity::DATA_RIDER_SEAT_POSITION, new Vector3(0, 0, 0));
$rider->getDataPropertyManager()->setByte(self::DATA_RIDER_ROTATION_LOCKED, false);

$pk = new SetActorLinkPacket();
$pk->link = new EntityLink($this->getId(), $rider->getId(), EntityLink::TYPE_REMOVE, true, true);
Server::getInstance()->broadcastPacket($this->getViewers(), $pk);

$this->rider = null;
return true;
}

return false;
}

public function absoluteMove(Vector3 $pos, float $yaw = 0, float $pitch = 0) : void{
$this->setComponents($pos->x, $pos->y, $pos->z);
$this->setRotation($yaw, $pitch);
$this->updateMovement();
}

public function handleAnimatePacket(AnimatePacket $packet) : void{
if($this->rider !== null){
switch($packet->action){
case self::ACTION_ROW_RIGHT:
$this->propertyManager->setFloat(self::DATA_PADDLE_TIME_RIGHT, $packet->float);
break;

case self::ACTION_ROW_LEFT:
$this->propertyManager->setFloat(self::DATA_PADDLE_TIME_LEFT, $packet->float);
break;
}
}
}

public function getRider() : ?Entity{
return $this->rider;
}

public function isRider(Entity $rider) : bool{
return $this->rider === $rider;
}
}
Loading