mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-10-18 20:14:31 +00:00
Merge branch 'stable'
This commit is contained in:
@@ -189,9 +189,16 @@ class CrashDump{
|
||||
|
||||
if($this->server->getConfigGroup()->getProperty("auto-report.send-settings", true) !== false){
|
||||
$this->data["parameters"] = (array) $argv;
|
||||
$this->data["server.properties"] = @file_get_contents($this->server->getDataPath() . "server.properties");
|
||||
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $this->data["server.properties"]);
|
||||
$this->data["pocketmine.yml"] = @file_get_contents($this->server->getDataPath() . "pocketmine.yml");
|
||||
if(($serverDotProperties = @file_get_contents($this->server->getDataPath() . "server.properties")) !== false){
|
||||
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $serverDotProperties);
|
||||
}else{
|
||||
$this->data["server.properties"] = $serverDotProperties;
|
||||
}
|
||||
if(($pocketmineDotYml = @file_get_contents($this->server->getDataPath() . "pocketmine.yml")) !== false){
|
||||
$this->data["pocketmine.yml"] = $pocketmineDotYml;
|
||||
}else{
|
||||
$this->data["pocketmine.yml"] = "";
|
||||
}
|
||||
}else{
|
||||
$this->data["pocketmine.yml"] = "";
|
||||
$this->data["server.properties"] = "";
|
||||
|
@@ -903,8 +903,7 @@ class Server{
|
||||
|
||||
$this->onlineMode = $this->configGroup->getConfigBool("xbox-auth", true);
|
||||
if($this->onlineMode){
|
||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.auth.enabled"));
|
||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.authProperty.enabled"));
|
||||
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.auth.enabled"));
|
||||
}else{
|
||||
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.auth.disabled"));
|
||||
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.authWarning"));
|
||||
|
@@ -472,6 +472,7 @@ abstract class Liquid extends Transparent{
|
||||
return $isOptimalFlowDirection;
|
||||
}
|
||||
|
||||
/** @phpstan-impure */
|
||||
private function getSmallestFlowDecay(Block $block, int $decay) : int{
|
||||
if(!($block instanceof Liquid) or !$block->isSameType($this)){
|
||||
return $decay;
|
||||
|
@@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network;
|
||||
|
||||
use pocketmine\event\player\PlayerDuplicateLoginEvent;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use function count;
|
||||
use function spl_object_id;
|
||||
@@ -59,33 +58,6 @@ class NetworkSessionManager{
|
||||
$this->updateSessions[spl_object_id($session)] = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this network session is a duplicate of an already-connected session (same player connecting from
|
||||
* 2 locations).
|
||||
*
|
||||
* @return bool if the network session is still connected.
|
||||
*/
|
||||
public function kickDuplicates(NetworkSession $connectingSession) : bool{
|
||||
foreach($this->sessions as $existingSession){
|
||||
if($existingSession === $connectingSession){
|
||||
continue;
|
||||
}
|
||||
$info = $existingSession->getPlayerInfo();
|
||||
if($info !== null and ($info->getUsername() === $connectingSession->getPlayerInfo()->getUsername() or $info->getUuid()->equals($connectingSession->getPlayerInfo()->getUuid()))){
|
||||
$ev = new PlayerDuplicateLoginEvent($connectingSession, $existingSession);
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
$connectingSession->disconnect($ev->getDisconnectMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
$existingSession->disconnect($ev->getDisconnectMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of known connected sessions.
|
||||
*/
|
||||
@@ -93,6 +65,9 @@ class NetworkSessionManager{
|
||||
return count($this->sessions);
|
||||
}
|
||||
|
||||
/** @return NetworkSession[] */
|
||||
public function getSessions() : array{ return $this->sessions; }
|
||||
|
||||
/**
|
||||
* Updates all sessions which need it.
|
||||
*/
|
||||
|
@@ -30,6 +30,7 @@ use pocketmine\entity\effect\EffectInstance;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\Human;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\event\player\PlayerDuplicateLoginEvent;
|
||||
use pocketmine\event\server\DataPacketReceiveEvent;
|
||||
use pocketmine\event\server\DataPacketSendEvent;
|
||||
use pocketmine\form\Form;
|
||||
@@ -607,43 +608,68 @@ class NetworkSession{
|
||||
}
|
||||
$this->logger->debug("Xbox Live authenticated: " . ($this->authenticated ? "YES" : "NO"));
|
||||
|
||||
//TODO: make player data loading async
|
||||
//TODO: we shouldn't be loading player data here at all, but right now we don't have any choice :(
|
||||
$this->cachedOfflinePlayerData = $this->server->getOfflinePlayerData($this->info->getUsername());
|
||||
if((bool) $this->server->getConfigGroup()->getProperty("player.verify-xuid", true)){
|
||||
$recordedXUID = $this->cachedOfflinePlayerData !== null ? $this->cachedOfflinePlayerData->getTag("LastKnownXUID") : null;
|
||||
if(!($recordedXUID instanceof StringTag)){
|
||||
$this->logger->debug("No previous XUID recorded, no choice but to trust this player");
|
||||
}elseif(($this->info instanceof XboxLivePlayerInfo ? $this->info->getXuid() : "") !== $recordedXUID->getValue()){
|
||||
$checkXUID = (bool) $this->server->getConfigGroup()->getProperty("player.verify-xuid", true);
|
||||
$myXUID = $this->info instanceof XboxLivePlayerInfo ? $this->info->getXuid() : "";
|
||||
$kickForXUIDMismatch = function(string $xuid) use ($checkXUID, $myXUID) : bool{
|
||||
if($checkXUID && $myXUID !== $xuid){
|
||||
//TODO: Longer term, we should be identifying playerdata using something more reliable, like XUID or UUID.
|
||||
//However, that would be a very disruptive change, so this will serve as a stopgap for now.
|
||||
//Side note: this will also prevent offline players hijacking XBL playerdata on online servers, since their
|
||||
//XUID will always be empty.
|
||||
$this->disconnect("XUID does not match (possible impersonation attempt)");
|
||||
return;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
foreach($this->manager->getSessions() as $existingSession){
|
||||
if($existingSession === $this){
|
||||
continue;
|
||||
}
|
||||
$info = $existingSession->getPlayerInfo();
|
||||
if($info !== null and ($info->getUsername() === $this->info->getUsername() or $info->getUuid()->equals($this->info->getUuid()))){
|
||||
if($kickForXUIDMismatch($info instanceof XboxLivePlayerInfo ? $info->getXuid() : "")){
|
||||
return;
|
||||
}
|
||||
$ev = new PlayerDuplicateLoginEvent($this, $existingSession);
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
$this->disconnect($ev->getDisconnectMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
$existingSession->disconnect($ev->getDisconnectMessage());
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: make player data loading async
|
||||
//TODO: we shouldn't be loading player data here at all, but right now we don't have any choice :(
|
||||
$this->cachedOfflinePlayerData = $this->server->getOfflinePlayerData($this->info->getUsername());
|
||||
if($checkXUID){
|
||||
$recordedXUID = $this->cachedOfflinePlayerData !== null ? $this->cachedOfflinePlayerData->getTag("LastKnownXUID") : null;
|
||||
if(!($recordedXUID instanceof StringTag)){
|
||||
$this->logger->debug("No previous XUID recorded, no choice but to trust this player");
|
||||
}elseif(!$kickForXUIDMismatch($recordedXUID->getValue())){
|
||||
$this->logger->debug("XUID match");
|
||||
}
|
||||
}
|
||||
|
||||
if($this->manager->kickDuplicates($this)){
|
||||
if(EncryptionContext::$ENABLED){
|
||||
$this->server->getAsyncPool()->submitTask(new PrepareEncryptionTask($clientPubKey, function(string $encryptionKey, string $handshakeJwt) : void{
|
||||
if(!$this->connected){
|
||||
return;
|
||||
}
|
||||
$this->sendDataPacket(ServerToClientHandshakePacket::create($handshakeJwt), true); //make sure this gets sent before encryption is enabled
|
||||
if(EncryptionContext::$ENABLED){
|
||||
$this->server->getAsyncPool()->submitTask(new PrepareEncryptionTask($clientPubKey, function(string $encryptionKey, string $handshakeJwt) : void{
|
||||
if(!$this->connected){
|
||||
return;
|
||||
}
|
||||
$this->sendDataPacket(ServerToClientHandshakePacket::create($handshakeJwt), true); //make sure this gets sent before encryption is enabled
|
||||
|
||||
$this->cipher = new EncryptionContext($encryptionKey);
|
||||
$this->cipher = new EncryptionContext($encryptionKey);
|
||||
|
||||
$this->setHandler(new HandshakePacketHandler(function() : void{
|
||||
$this->onServerLoginSuccess();
|
||||
}));
|
||||
$this->logger->debug("Enabled encryption");
|
||||
$this->setHandler(new HandshakePacketHandler(function() : void{
|
||||
$this->onServerLoginSuccess();
|
||||
}));
|
||||
}else{
|
||||
$this->onServerLoginSuccess();
|
||||
}
|
||||
$this->logger->debug("Enabled encryption");
|
||||
}));
|
||||
}else{
|
||||
$this->onServerLoginSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -44,6 +44,7 @@ class ResourcePackClientResponsePacket extends DataPacket implements Serverbound
|
||||
protected function decodePayload(PacketSerializer $in) : void{
|
||||
$this->status = $in->getByte();
|
||||
$entryCount = $in->getLShort();
|
||||
$this->packIds = [];
|
||||
while($entryCount-- > 0){
|
||||
$this->packIds[] = $in->getString();
|
||||
}
|
||||
|
@@ -1180,8 +1180,6 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
$deltaAngle = abs($this->lastLocation->yaw - $to->yaw) + abs($this->lastLocation->pitch - $to->pitch);
|
||||
|
||||
if($delta > 0.0001 or $deltaAngle > 1.0){
|
||||
$this->lastLocation = clone $to; //avoid PlayerMoveEvent modifying this
|
||||
|
||||
$ev = new PlayerMoveEvent($this, $from, $to);
|
||||
|
||||
$ev->call();
|
||||
@@ -1196,6 +1194,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->lastLocation = $to;
|
||||
$this->broadcastMovement();
|
||||
|
||||
$distance = sqrt((($from->x - $to->x) ** 2) + (($from->z - $to->z) ** 2));
|
||||
@@ -1218,8 +1217,6 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
}
|
||||
|
||||
protected function revertMovement(Location $from) : void{
|
||||
$this->lastLocation = $from;
|
||||
|
||||
$this->setPosition($from);
|
||||
$this->sendPosition($from, $from->yaw, $from->pitch, MovePlayerPacket::MODE_RESET);
|
||||
}
|
||||
|
Reference in New Issue
Block a user