Implement Recovery compass (#5502)

Co-authored-by: Dylan K. Taylor <dktapps@pmmp.io>
This commit is contained in:
IvanCraft623 2024-12-01 13:25:45 -05:00 committed by GitHub
parent 12214792b3
commit f3763ae691
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 61 additions and 1 deletions

View File

@ -352,6 +352,7 @@ final class ItemSerializerDeserializerRegistrar{
$this->map1to1Item(Ids::RAW_COPPER, Items::RAW_COPPER());
$this->map1to1Item(Ids::RAW_GOLD, Items::RAW_GOLD());
$this->map1to1Item(Ids::RAW_IRON, Items::RAW_IRON());
$this->map1to1Item(Ids::RECOVERY_COMPASS, Items::RECOVERY_COMPASS());
$this->map1to1Item(Ids::REDSTONE, Items::REDSTONE_DUST());
$this->map1to1Item(Ids::RIB_ARMOR_TRIM_SMITHING_TEMPLATE, Items::RIB_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::ROTTEN_FLESH, Items::ROTTEN_FLESH());

View File

@ -327,8 +327,9 @@ final class ItemTypeIds{
public const GOAT_HORN = 20288;
public const END_CRYSTAL = 20289;
public const ICE_BOMB = 20290;
public const RECOVERY_COMPASS = 20291;
public const FIRST_UNUSED_ITEM_ID = 20291;
public const FIRST_UNUSED_ITEM_ID = 20292;
private static int $nextDynamicId = self::FIRST_UNUSED_ITEM_ID;

View File

@ -1481,6 +1481,7 @@ final class StringToItemParser extends StringToTParser{
$result->register("record_strad", fn() => Items::RECORD_STRAD());
$result->register("record_wait", fn() => Items::RECORD_WAIT());
$result->register("record_ward", fn() => Items::RECORD_WARD());
$result->register("recovery_compass", fn() => Items::RECOVERY_COMPASS());
$result->register("redstone", fn() => Items::REDSTONE_DUST());
$result->register("redstone_dust", fn() => Items::REDSTONE_DUST());
$result->register("rib_armor_trim_smithing_template", fn() => Items::RIB_ARMOR_TRIM_SMITHING_TEMPLATE());

View File

@ -284,6 +284,7 @@ use function strtolower;
* @method static Record RECORD_STRAD()
* @method static Record RECORD_WAIT()
* @method static Record RECORD_WARD()
* @method static Item RECOVERY_COMPASS()
* @method static Redstone REDSTONE_DUST()
* @method static Item RIB_ARMOR_TRIM_SMITHING_TEMPLATE()
* @method static RottenFlesh ROTTEN_FLESH()
@ -574,6 +575,7 @@ final class VanillaItems{
self::register("record_strad", fn(IID $id) => new Record($id, RecordType::DISK_STRAD, "Record Strad"));
self::register("record_wait", fn(IID $id) => new Record($id, RecordType::DISK_WAIT, "Record Wait"));
self::register("record_ward", fn(IID $id) => new Record($id, RecordType::DISK_WARD, "Record Ward"));
self::register("recovery_compass", fn(IID $id) => new Item($id, "Recovery Compass"));
self::register("redstone_dust", fn(IID $id) => new Redstone($id, "Redstone"));
self::register("rotten_flesh", fn(IID $id) => new RottenFlesh($id, "Rotten Flesh"));
self::register("scute", fn(IID $id) => new Item($id, "Scute"));

View File

@ -110,6 +110,7 @@ use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
use pocketmine\network\mcpe\protocol\SetActorMotionPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\types\DimensionIds;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
@ -191,6 +192,10 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
private const TAG_SPAWN_X = "SpawnX"; //TAG_Int
private const TAG_SPAWN_Y = "SpawnY"; //TAG_Int
private const TAG_SPAWN_Z = "SpawnZ"; //TAG_Int
private const TAG_DEATH_WORLD = "DeathLevel"; //TAG_String
private const TAG_DEATH_X = "DeathPositionX"; //TAG_Int
private const TAG_DEATH_Y = "DeathPositionY"; //TAG_Int
private const TAG_DEATH_Z = "DeathPositionZ"; //TAG_Int
public const TAG_LEVEL = "Level"; //TAG_String
public const TAG_LAST_KNOWN_XUID = "LastKnownXUID"; //TAG_String
@ -273,6 +278,8 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
private bool $respawnLocked = false;
private ?Position $deathPosition = null;
//TODO: Abilities
protected bool $autoJump = true;
protected bool $allowFlight = false;
@ -391,6 +398,9 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
if(($world = $this->server->getWorldManager()->getWorldByName($nbt->getString(self::TAG_SPAWN_WORLD, ""))) instanceof World){
$this->spawnPosition = new Position($nbt->getInt(self::TAG_SPAWN_X), $nbt->getInt(self::TAG_SPAWN_Y), $nbt->getInt(self::TAG_SPAWN_Z), $world);
}
if(($world = $this->server->getWorldManager()->getWorldByName($nbt->getString(self::TAG_DEATH_WORLD, ""))) instanceof World){
$this->deathPosition = new Position($nbt->getInt(self::TAG_DEATH_X), $nbt->getInt(self::TAG_DEATH_Y), $nbt->getInt(self::TAG_DEATH_Z), $world);
}
}
public function getLeaveMessage() : Translatable|string{
@ -1032,6 +1042,30 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
}
}
public function getDeathPosition() : ?Position{
if($this->deathPosition !== null && !$this->deathPosition->isValid()){
$this->deathPosition = null;
}
return $this->deathPosition;
}
/**
* @param Vector3|Position|null $pos
*/
public function setDeathPosition(?Vector3 $pos) : void{
if($pos !== null){
if($pos instanceof Position && $pos->world !== null){
$world = $pos->world;
}else{
$world = $this->getWorld();
}
$this->deathPosition = new Position($pos->x, $pos->y, $pos->z, $world);
}else{
$this->deathPosition = null;
}
$this->networkPropertiesDirty = true;
}
/**
* @return Position
*/
@ -2336,6 +2370,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
unset($this->cursorInventory);
unset($this->craftingGrid);
$this->spawnPosition = null;
$this->deathPosition = null;
$this->blockBreakHandler = null;
parent::destroyCycles();
}
@ -2377,6 +2412,13 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$nbt->setInt(self::TAG_SPAWN_Z, $spawn->getFloorZ());
}
if($this->deathPosition !== null && $this->deathPosition->isValid()){
$nbt->setString(self::TAG_DEATH_WORLD, $this->deathPosition->getWorld()->getFolderName());
$nbt->setInt(self::TAG_DEATH_X, $this->deathPosition->getFloorX());
$nbt->setInt(self::TAG_DEATH_Y, $this->deathPosition->getFloorY());
$nbt->setInt(self::TAG_DEATH_Z, $this->deathPosition->getFloorZ());
}
$nbt->setInt(self::TAG_GAME_MODE, GameModeIdMap::getInstance()->toId($this->gamemode));
$nbt->setLong(self::TAG_FIRST_PLAYED, $this->firstPlayed);
$nbt->setLong(self::TAG_LAST_PLAYED, (int) floor(microtime(true) * 1000));
@ -2396,6 +2438,8 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
//main inventory and drops the rest on the ground.
$this->removeCurrentWindow();
$this->setDeathPosition($this->getPosition());
$ev = new PlayerDeathEvent($this, $this->getDrops(), $this->getXpDropAmount(), null);
$ev->call();
@ -2524,6 +2568,17 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$properties->setPlayerFlag(PlayerMetadataFlags::SLEEP, $this->sleeping !== null);
$properties->setBlockPos(EntityMetadataProperties::PLAYER_BED_POSITION, $this->sleeping !== null ? BlockPosition::fromVector3($this->sleeping) : new BlockPosition(0, 0, 0));
if($this->deathPosition !== null && $this->deathPosition->world === $this->location->world){
$properties->setBlockPos(EntityMetadataProperties::PLAYER_DEATH_POSITION, BlockPosition::fromVector3($this->deathPosition));
//TODO: this should be updated when dimensions are implemented
$properties->setInt(EntityMetadataProperties::PLAYER_DEATH_DIMENSION, DimensionIds::OVERWORLD);
$properties->setByte(EntityMetadataProperties::PLAYER_HAS_DIED, 1);
}else{
$properties->setBlockPos(EntityMetadataProperties::PLAYER_DEATH_POSITION, new BlockPosition(0, 0, 0));
$properties->setInt(EntityMetadataProperties::PLAYER_DEATH_DIMENSION, DimensionIds::OVERWORLD);
$properties->setByte(EntityMetadataProperties::PLAYER_HAS_DIED, 0);
}
}
public function sendData(?array $targets, ?array $data = null) : void{