PocketMine-MP 5.15.1 git-5ef247620a7c6301a849b54e5ef1009217729fc8
DatFilePlayerDataProvider.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\player;
25
33use Symfony\Component\Filesystem\Path;
34use function file_exists;
35use function rename;
36use function strtolower;
37use function zlib_decode;
38use function zlib_encode;
39use const ZLIB_ENCODING_GZIP;
40
45
46 public function __construct(
47 private string $path
48 ){}
49
50 private function getPlayerDataPath(string $username) : string{
51 return Path::join($this->path, strtolower($username) . '.dat');
52 }
53
54 private function handleCorruptedPlayerData(string $name) : void{
55 $path = $this->getPlayerDataPath($name);
56 rename($path, $path . '.bak');
57 }
58
59 public function hasData(string $name) : bool{
60 return file_exists($this->getPlayerDataPath($name));
61 }
62
63 public function loadData(string $name) : ?CompoundTag{
64 $name = strtolower($name);
65 $path = $this->getPlayerDataPath($name);
66
67 if(!file_exists($path)){
68 return null;
69 }
70
71 try{
72 $contents = Filesystem::fileGetContents($path);
73 }catch(\RuntimeException $e){
74 throw new PlayerDataLoadException("Failed to read player data file \"$path\": " . $e->getMessage(), 0, $e);
75 }
76 try{
77 $decompressed = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => zlib_decode($contents));
78 }catch(\ErrorException $e){
79 $this->handleCorruptedPlayerData($name);
80 throw new PlayerDataLoadException("Failed to decompress raw player data for \"$name\": " . $e->getMessage(), 0, $e);
81 }
82
83 try{
84 return (new BigEndianNbtSerializer())->read($decompressed)->mustGetCompoundTag();
85 }catch(NbtDataException $e){ //corrupt data
86 $this->handleCorruptedPlayerData($name);
87 throw new PlayerDataLoadException("Failed to decode NBT data for \"$name\": " . $e->getMessage(), 0, $e);
88 }
89 }
90
91 public function saveData(string $name, CompoundTag $data) : void{
92 $nbt = new BigEndianNbtSerializer();
93 $contents = Utils::assumeNotFalse(zlib_encode($nbt->write(new TreeRoot($data)), ZLIB_ENCODING_GZIP), "zlib_encode() failed unexpectedly");
94 try{
95 Filesystem::safeFilePutContents($this->getPlayerDataPath($name), $contents);
96 }catch(\RuntimeException $e){
97 throw new PlayerDataSaveException("Failed to write player data file: " . $e->getMessage(), 0, $e);
98 }
99 }
100}
static trapAndRemoveFalse(\Closure $closure, int $levels=E_WARNING|E_NOTICE)
static fileGetContents(string $fileName, bool $useIncludePath=false, $context=null, int $offset=0, ?int $length=null)
Definition: Filesystem.php:305