mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-14 13:25:11 +00:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
f1c071ce7f | |||
e2f46a4358 | |||
4c08a05fae | |||
b473ffdedc | |||
60dddcd12a | |||
93c26a0b0c | |||
545ec9c881 | |||
d5a1961e6b | |||
6bc79149c3 | |||
e018311e73 | |||
71d02e5870 | |||
d312aef1ac |
@ -3515,11 +3515,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
/**
|
||||
* Handles player data saving
|
||||
*
|
||||
* @param bool $async
|
||||
*
|
||||
* @throws \InvalidStateException if the player is closed
|
||||
*/
|
||||
public function save(bool $async = false){
|
||||
public function save(){
|
||||
if($this->closed){
|
||||
throw new \InvalidStateException("Tried to save closed player");
|
||||
}
|
||||
@ -3556,7 +3554,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$this->namedtag->setLong("lastPlayed", (int) floor(microtime(true) * 1000));
|
||||
|
||||
if($this->username != "" and $this->namedtag instanceof CompoundTag){
|
||||
$this->server->saveOfflinePlayerData($this->username, $this->namedtag, $async);
|
||||
$this->server->saveOfflinePlayerData($this->username, $this->namedtag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace pocketmine {
|
||||
use pocketmine\wizard\SetupWizard;
|
||||
|
||||
const NAME = "PocketMine-MP";
|
||||
const BASE_VERSION = "3.3.2";
|
||||
const BASE_VERSION = "3.3.3";
|
||||
const IS_DEVELOPMENT_BUILD = false;
|
||||
const BUILD_NUMBER = 0;
|
||||
|
||||
|
@ -91,7 +91,6 @@ use pocketmine\plugin\PluginManager;
|
||||
use pocketmine\plugin\ScriptPluginLoader;
|
||||
use pocketmine\resourcepacks\ResourcePackManager;
|
||||
use pocketmine\scheduler\AsyncPool;
|
||||
use pocketmine\scheduler\FileWriteTask;
|
||||
use pocketmine\scheduler\SendUsageTask;
|
||||
use pocketmine\snooze\SleeperHandler;
|
||||
use pocketmine\snooze\SleeperNotifier;
|
||||
@ -805,9 +804,8 @@ class Server{
|
||||
/**
|
||||
* @param string $name
|
||||
* @param CompoundTag $nbtTag
|
||||
* @param bool $async
|
||||
*/
|
||||
public function saveOfflinePlayerData(string $name, CompoundTag $nbtTag, bool $async = false){
|
||||
public function saveOfflinePlayerData(string $name, CompoundTag $nbtTag){
|
||||
$ev = new PlayerDataSaveEvent($nbtTag, $name);
|
||||
$ev->setCancelled(!$this->shouldSavePlayerData());
|
||||
|
||||
@ -816,11 +814,7 @@ class Server{
|
||||
if(!$ev->isCancelled()){
|
||||
$nbt = new BigEndianNBTStream();
|
||||
try{
|
||||
if($async){
|
||||
$this->asyncPool->submitTask(new FileWriteTask($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed($ev->getSaveData())));
|
||||
}else{
|
||||
file_put_contents($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed($ev->getSaveData()));
|
||||
}
|
||||
file_put_contents($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed($ev->getSaveData()));
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->critical($this->getLanguage()->translateString("pocketmine.data.saveError", [$name, $e->getMessage()]));
|
||||
$this->logger->logException($e);
|
||||
@ -1449,6 +1443,7 @@ class Server{
|
||||
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error2"));
|
||||
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error3"));
|
||||
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error4", ["settings.enable-dev-builds"]));
|
||||
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error5", ["https://github.com/pmmp/PocketMine-MP/releases"]));
|
||||
$this->forceShutdown();
|
||||
return;
|
||||
}
|
||||
@ -2246,6 +2241,12 @@ class Server{
|
||||
|
||||
$this->forceShutdown();
|
||||
$this->isRunning = false;
|
||||
|
||||
//Force minimum uptime to be >= 120 seconds, to reduce the impact of spammy crash loops
|
||||
$spacing = ((int) \pocketmine\START_TIME) - time() + 120;
|
||||
if($spacing > 0){
|
||||
sleep($spacing);
|
||||
}
|
||||
@Utils::kill(getmypid());
|
||||
exit(1);
|
||||
}
|
||||
@ -2397,7 +2398,7 @@ class Server{
|
||||
Timings::$worldSaveTimer->startTiming();
|
||||
foreach($this->players as $index => $player){
|
||||
if($player->spawned){
|
||||
$player->save(true);
|
||||
$player->save();
|
||||
}elseif(!$player->isConnected()){
|
||||
$this->removePlayer($player);
|
||||
}
|
||||
|
@ -655,11 +655,11 @@ abstract class Living extends Entity implements Damageable{
|
||||
|
||||
$hasUpdate = parent::entityBaseTick($tickDiff);
|
||||
|
||||
if($this->doEffectsTick($tickDiff)){
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
if($this->isAlive()){
|
||||
if($this->doEffectsTick($tickDiff)){
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
if($this->isInsideOfSolid()){
|
||||
$hasUpdate = true;
|
||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_SUFFOCATION, 1);
|
||||
|
@ -37,67 +37,68 @@ class PaintingItem extends Item{
|
||||
}
|
||||
|
||||
public function onActivate(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : bool{
|
||||
if(!$blockClicked->isTransparent() and $face > 1 and !$blockReplace->isSolid()){
|
||||
/** @var PaintingMotive[] $motives */
|
||||
$motives = [];
|
||||
if($face === Vector3::SIDE_DOWN or $face === Vector3::SIDE_UP){
|
||||
return false;
|
||||
}
|
||||
|
||||
$totalDimension = 0;
|
||||
foreach(PaintingMotive::getAll() as $motive){
|
||||
$currentTotalDimension = $motive->getHeight() + $motive->getWidth();
|
||||
if($currentTotalDimension < $totalDimension){
|
||||
continue;
|
||||
$motives = [];
|
||||
|
||||
$totalDimension = 0;
|
||||
foreach(PaintingMotive::getAll() as $motive){
|
||||
$currentTotalDimension = $motive->getHeight() + $motive->getWidth();
|
||||
if($currentTotalDimension < $totalDimension){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(Painting::canFit($player->level, $blockReplace, $face, true, $motive)){
|
||||
if($currentTotalDimension > $totalDimension){
|
||||
$totalDimension = $currentTotalDimension;
|
||||
/*
|
||||
* This drops all motive possibilities smaller than this
|
||||
* We use the total of height + width to allow equal chance of horizontal/vertical paintings
|
||||
* when there is an L-shape of space available.
|
||||
*/
|
||||
$motives = [];
|
||||
}
|
||||
|
||||
if(Painting::canFit($player->level, $blockReplace, $face, true, $motive)){
|
||||
if($currentTotalDimension > $totalDimension){
|
||||
$totalDimension = $currentTotalDimension;
|
||||
/*
|
||||
* This drops all motive possibilities smaller than this
|
||||
* We use the total of height + width to allow equal chance of horizontal/vertical paintings
|
||||
* when there is an L-shape of space available.
|
||||
*/
|
||||
$motives = [];
|
||||
}
|
||||
|
||||
$motives[] = $motive;
|
||||
}
|
||||
$motives[] = $motive;
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($motives)){ //No space available
|
||||
return false;
|
||||
}
|
||||
if(empty($motives)){ //No space available
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var PaintingMotive $motive */
|
||||
$motive = $motives[array_rand($motives)];
|
||||
/** @var PaintingMotive $motive */
|
||||
$motive = $motives[array_rand($motives)];
|
||||
|
||||
static $directions = [
|
||||
Vector3::SIDE_SOUTH => 0,
|
||||
Vector3::SIDE_WEST => 1,
|
||||
Vector3::SIDE_NORTH => 2,
|
||||
Vector3::SIDE_EAST => 3
|
||||
];
|
||||
static $directions = [
|
||||
Vector3::SIDE_SOUTH => 0,
|
||||
Vector3::SIDE_WEST => 1,
|
||||
Vector3::SIDE_NORTH => 2,
|
||||
Vector3::SIDE_EAST => 3
|
||||
];
|
||||
|
||||
$direction = $directions[$face] ?? -1;
|
||||
if($direction === -1){
|
||||
return false;
|
||||
}
|
||||
$direction = $directions[$face] ?? -1;
|
||||
if($direction === -1){
|
||||
return false;
|
||||
}
|
||||
|
||||
$nbt = Entity::createBaseNBT($blockReplace, null, $direction * 90, 0);
|
||||
$nbt->setByte("Direction", $direction);
|
||||
$nbt->setString("Motive", $motive->getName());
|
||||
$nbt->setInt("TileX", $blockClicked->getFloorX());
|
||||
$nbt->setInt("TileY", $blockClicked->getFloorY());
|
||||
$nbt->setInt("TileZ", $blockClicked->getFloorZ());
|
||||
$nbt = Entity::createBaseNBT($blockReplace, null, $direction * 90, 0);
|
||||
$nbt->setByte("Direction", $direction);
|
||||
$nbt->setString("Motive", $motive->getName());
|
||||
$nbt->setInt("TileX", $blockClicked->getFloorX());
|
||||
$nbt->setInt("TileY", $blockClicked->getFloorY());
|
||||
$nbt->setInt("TileZ", $blockClicked->getFloorZ());
|
||||
|
||||
$entity = Entity::createEntity("Painting", $blockReplace->getLevel(), $nbt);
|
||||
$entity = Entity::createEntity("Painting", $blockReplace->getLevel(), $nbt);
|
||||
|
||||
if($entity instanceof Entity){
|
||||
--$this->count;
|
||||
$entity->spawnToAll();
|
||||
if($entity instanceof Entity){
|
||||
--$this->count;
|
||||
$entity->spawnToAll();
|
||||
|
||||
$player->getLevel()->broadcastLevelEvent($blockReplace->add(0.5, 0.5, 0.5), LevelEventPacket::EVENT_SOUND_ITEMFRAME_PLACE); //item frame and painting have the same sound
|
||||
return true;
|
||||
}
|
||||
$player->getLevel()->broadcastLevelEvent($blockReplace->add(0.5, 0.5, 0.5), LevelEventPacket::EVENT_SOUND_ITEMFRAME_PLACE); //item frame and painting have the same sound
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
Submodule src/pocketmine/lang/locale updated: 0cd3f8ef30...1d525a7c1c
@ -106,13 +106,14 @@ class SubChunk implements SubChunkInterface{
|
||||
|
||||
if($data !== null){
|
||||
$i >>= 1;
|
||||
$byte = ord($this->data{$i});
|
||||
$oldPair = ord($this->data{$i});
|
||||
if(($y & 1) === 0){
|
||||
$this->data{$i} = chr(($byte & 0xf0) | ($data & 0x0f));
|
||||
$newPair = ($oldPair & 0xf0) | ($data & 0x0f);
|
||||
}else{
|
||||
$this->data{$i} = chr((($data & 0x0f) << 4) | ($byte & 0x0f));
|
||||
$newPair = (($data & 0x0f) << 4) | ($oldPair & 0x0f);
|
||||
}
|
||||
if($this->data{$i} !== $byte){
|
||||
if($newPair !== $oldPair){
|
||||
$this->data{$i} = chr($newPair);
|
||||
$changed = true;
|
||||
}
|
||||
}
|
||||
|
@ -134,4 +134,12 @@ abstract class DataPacket extends NetworkBinaryStream{
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function __get($name){
|
||||
throw new \Error("Cannot read non-existing field \"$name\"");
|
||||
}
|
||||
|
||||
public function __set($name, $value){
|
||||
throw new \Error("Cannot write non-existing field \"$name\"");
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,8 @@ if exist bin\php\php.exe (
|
||||
if exist PocketMine-MP.phar (
|
||||
set POCKETMINE_FILE=PocketMine-MP.phar
|
||||
) else (
|
||||
echo Couldn't find a valid PocketMine-MP installation
|
||||
echo PocketMine-MP.phar not found
|
||||
echo Downloads can be found at https://github.com/pmmp/PocketMine-MP/releases
|
||||
pause
|
||||
exit 1
|
||||
)
|
||||
|
@ -19,7 +19,8 @@ if($file -eq ""){
|
||||
if(Test-Path "PocketMine-MP.phar"){
|
||||
$file = "PocketMine-MP.phar"
|
||||
}else{
|
||||
echo "Couldn't find a valid PocketMine-MP installation"
|
||||
echo "PocketMine-MP.phar not found"
|
||||
echo "Downloads can be found at https://github.com/pmmp/PocketMine-MP/releases"
|
||||
pause
|
||||
exit 1
|
||||
}
|
||||
|
3
start.sh
3
start.sh
@ -37,7 +37,8 @@ if [ "$POCKETMINE_FILE" == "" ]; then
|
||||
if [ -f ./PocketMine-MP.phar ]; then
|
||||
POCKETMINE_FILE="./PocketMine-MP.phar"
|
||||
else
|
||||
echo "Couldn't find a valid PocketMine-MP installation"
|
||||
echo "PocketMine-MP.phar not found"
|
||||
echo "Downloads can be found at https://github.com/pmmp/PocketMine-MP/releases"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
Submodule tests/preprocessor updated: ea28e32720...a6ec3e1271
Reference in New Issue
Block a user