Compare commits

..

51 Commits

Author SHA1 Message Date
f4181a6e36 Bump Minecraft: PE version 2014-11-27 14:37:44 +01:00
38089af098 Improved global entity motion encoding using per-player queues 2014-11-27 14:26:36 +01:00
cd135b39ad Improved player spawn item in hand sending 2014-11-27 13:59:32 +01:00
dd3207cbd8 Possible fix for #2267, #2314 2014-11-27 13:47:17 +01:00
a7abd5ff9d Catch exceptions when chunks are unloaded 2014-11-27 13:35:54 +01:00
a3e50f6337 Properly close inventory windows from Players 2014-11-27 13:32:07 +01:00
441a98e60a Removed old trigger_error() calls, closes #2335 2014-11-27 13:16:39 +01:00
4a90ac270f Improved exception handling and debugging 2014-11-22 13:52:36 +01:00
a906a2988b Bumped Minecraft: PE version string 2014-11-22 13:44:34 +01:00
545f68382c Increased Fence, Fence Gate and Stone Wall Y bounding box 2014-11-22 13:44:05 +01:00
8249cac592 Catch corrupted chunk data errors 2014-11-20 22:02:00 +01:00
7b7bbe9105 Regenerate corrupt player data if invalid data is found 2014-11-20 21:58:27 +01:00
05679c7872 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-11-20 21:46:14 +01:00
8eb80be691 Remove duplicated tiles from chunk table automatically 2014-11-20 21:45:52 +01:00
f55b0d0b45 Merge pull request #2295 from LukeDarling/patch-1
Fixed Server->getOps() capitalization
2014-11-19 13:10:03 +01:00
754e0dbb49 Protect permission removal against bad plugins 2014-11-18 18:43:30 +01:00
525c8db779 Improved chunk loading/unloading 2014-11-18 18:33:24 +01:00
c7f578f297 Possible fix for #2297 2014-11-18 13:57:03 +01:00
19c030281f Fixed #1969 2014-11-18 13:53:38 +01:00
ca9fe1b89a Improved and fixed command exception message, closes #2301 2014-11-18 13:46:00 +01:00
9fd6a695f6 Fixed permission-related memory leak 2014-11-18 13:42:24 +01:00
c07b0ff35b Fixed tile entities not being placed in the correct array 2014-11-15 11:49:09 +01:00
00be3f0dd3 Fixed Server->getOps() capitalization
I'm not 100% sure, but I believe this is how it's supposed to be.
2014-11-15 00:01:57 -05:00
6796fca2b6 Merge pull request #2294 from LukeDarling/patch-1
fixed version message color
2014-11-15 14:20:14 +10:30
5657cce3db fixed version message color 2014-11-14 15:52:38 -05:00
05ac256cc3 Fixed Acacia / Dark Oak logs crafting recipes 2014-11-14 15:58:31 +01:00
49977c5410 Bumped weakref version, fixes travis builds 2014-11-14 10:30:06 +01:00
ca40bb678c Merge pull request #2288 from sekjun9878/master
Get timezone directly. Fixes #2287.
2014-11-13 23:08:22 +10:30
2068cc9cdf Merge pull request #2243 from PEMapModder/patch-1
cmd files comment syntax should be like this.
2014-11-13 21:42:25 +10:30
ea4617cedd Get timezone directly. Fixes #2287. 2014-11-13 21:13:12 +10:30
1a5544f68c Fixed Chunk tile indexes 2014-11-08 15:00:18 +01:00
0128a7aeb2 API version 1.7.1 (fixes) 2014-11-07 09:45:30 +01:00
fd954ce708 Fixed PlayerInventory->setItem() with null items 2014-11-07 09:43:36 +01:00
d63a82de0a MCPE protocol 20 2014-11-06 19:08:32 +01:00
92143d523c Added SetDifficultyPacket 2014-11-06 19:07:24 +01:00
1818e64c8e Merge branch 'master' into 0.10 2014-11-06 18:56:47 +01:00
522b75645c Merge branch 'master' into 0.10 2014-11-05 19:04:36 +01:00
4fba6d7c86 Merge branch 'master' into 0.10 2014-10-30 23:20:59 +01:00
577a7a1c3d cmd files comment syntax should be like this. 2014-10-29 17:20:36 +08:00
1fc066fc37 Updated time steps from x2.5 to x1.25 2014-10-24 12:12:01 +02:00
b565844062 Merge branch 'master' into 0.10 2014-10-24 12:07:35 +02:00
5cb428e5cc Updated build number 2014-10-23 17:23:59 +02:00
d2f4a14d66 Merge branch 'master' into 0.10 2014-10-23 17:21:24 +02:00
5437567e95 Merge branch 'master' into 0.10 2014-10-20 12:53:14 +02:00
7d9a98ec6b Updated UseItemPacket 2014-10-18 23:42:41 +02:00
92facc94b9 Added new fences and fence gates to fuel types 2014-10-18 18:02:39 +02:00
d3327f450c Added different Fence Gates, new Fence Gate crafting recipes 2014-10-18 17:56:18 +02:00
570cab9c66 Added different Fences, new Fence crafting recipes 2014-10-18 17:44:24 +02:00
582ba100b0 Bumped protocol version to 19 2014-10-18 17:01:36 +02:00
4c0daa462d Merge branch 'master' into 0.10 2014-10-18 16:54:03 +02:00
a879104a6f Minecraft: PE version bump 2014-10-17 14:43:10 +02:00
55 changed files with 814 additions and 291 deletions

View File

@ -10,7 +10,7 @@ before_script:
- mkdir plugins
- wget -O plugins/DevTools.phar https://github.com/PocketMine/DevTools/releases/download/v1.9.0/DevTools_v1.9.0.phar
- pecl install channel://pecl.php.net/pthreads-2.0.10
- pecl install channel://pecl.php.net/weakref-0.2.4
- pecl install channel://pecl.php.net/weakref-0.2.6
- echo | pecl install channel://pecl.php.net/yaml-1.1.1
script:
@ -18,4 +18,4 @@ script:
notifications:
email: false
#webhooks: http://n.tkte.ch/h/214/wsNvmG43-ncxUVRrFPwSM-r0
#webhooks: http://n.tkte.ch/h/214/wsNvmG43-ncxUVRrFPwSM-r0

View File

@ -93,7 +93,10 @@ use pocketmine\network\protocol\FullChunkDataPacket;
use pocketmine\network\protocol\Info as ProtocolInfo;
use pocketmine\network\protocol\LoginStatusPacket;
use pocketmine\network\protocol\MessagePacket;
use pocketmine\network\protocol\MoveEntityPacket;
use pocketmine\network\protocol\MovePlayerPacket;
use pocketmine\network\protocol\SetDifficultyPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\network\protocol\SetHealthPacket;
use pocketmine\network\protocol\SetSpawnPositionPacket;
use pocketmine\network\protocol\SetTimePacket;
@ -141,6 +144,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
protected $sendIndex = 0;
protected $moveToSend = [];
protected $motionToSend = [];
public $blocked = false;
public $achievements = [];
public $lastCorrect;
@ -566,7 +572,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$index = $this->chunkACK[$identifier];
unset($this->chunkACK[$identifier]);
if(isset($this->usedChunks[$index])){
$this->usedChunks[$index][0] = true;
$this->usedChunks[$index] = true;
$X = null;
$Z = null;
Level::getXZ($index, $X, $Z);
@ -606,21 +612,23 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
if($count >= $this->chunksPerTick){
break;
}
++$count;
$X = null;
$Z = null;
Level::getXZ($index, $X, $Z);
if(!$this->level->isChunkPopulated($X, $Z)){
$this->level->generateChunk($X, $Z);
if($this->spawned === true){
if($this->spawned){
continue;
}else{
break;
}
}
++$count;
unset($this->loadQueue[$index]);
$this->usedChunks[$index] = [false, 0];
$this->usedChunks[$index] = false;
$this->level->useChunk($X, $Z, $this);
$this->level->requestChunk($X, $Z, $this, LevelProvider::ORDER_ZXY);
@ -629,7 +637,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
if(count($this->usedChunks) >= 56 and $this->spawned === false){
$spawned = 0;
foreach($this->usedChunks as $d){
if($d[0] === true){
if($d === true){
$spawned++;
}
}
@ -673,7 +681,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
return false;
}
$this->nextChunkOrderRun = 100;
$this->nextChunkOrderRun = 200;
$radiusSquared = $this->viewDistance;
$radius = ceil(sqrt($radiusSquared));
@ -681,23 +689,41 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$newOrder = [];
$lastChunk = $this->usedChunks;
$currentQueue = [];
$centerX = $this->x >> 4;
$centerZ = $this->z >> 4;
$count = 0;
for($X = -$side; $X <= $side; ++$X){
for($Z = -$side; $Z <= $side; ++$Z){
++$count;
$chunkX = $X + $centerX;
$chunkZ = $Z + $centerZ;
if(!isset($this->usedChunks[$index = "$chunkX:$chunkZ"])){
$newOrder[$index] = abs($X) + abs($Z);
}else{
$currentQueue[$index] = abs($X) + abs($Z);
}
unset($lastChunk[$index]);
}
}
$loadedChunks = max(0, count($this->usedChunks) - count($lastChunk));
asort($newOrder);
asort($currentQueue);
$limit = $this->viewDistance;
foreach($currentQueue as $index => $distance){
if($limit-- <= 0){
break;
}
unset($lastChunk[$index]);
}
foreach($lastChunk as $index => $Yndex){
$X = null;
$Z = null;
Level::getXZ($index, $X, $Z);
$this->unloadChunk($X, $Z);
}
$loadedChunks = count($this->usedChunks);
if((count($newOrder) + $loadedChunks) > $this->viewDistance){
$count = $loadedChunks;
$this->loadQueue = [];
@ -711,14 +737,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->loadQueue = $newOrder;
}
foreach($lastChunk as $index => $Yndex){
$X = null;
$Z = null;
Level::getXZ($index, $X, $Z);
$this->unloadChunk($X, $Z);
}
return true;
}
@ -1040,6 +1058,14 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
return -1;
}
public function addEntityMotion($entityId, $x, $y, $z){
$this->motionToSend[$entityId] = [$entityId, $x, $y, $z];
}
public function addEntityMovement($entityId, $x, $y, $z, $yaw, $pitch){
$this->moveToSend[$entityId] = [$entityId, $x, $y, $z, $yaw, $pitch];
}
protected function processMovement($currentTick){
if($this->dead or !$this->spawned or !($this->newPosition instanceof Vector3)){
return;
@ -1058,6 +1084,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$revert = true;
$this->nextChunkOrderRun = 0;
}else{
if($this->chunk instanceof FullChunk){
$this->chunk->removeEntity($this);
}
$this->chunk = $chunk;
}
}
@ -1134,7 +1163,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$pk = new MovePlayerPacket();
$pk->eid = 0;
$pk->x = $from->x;
$pk->y = $from->y + $this->getEyeHeight() + 0.01;
$pk->y = $from->y + $this->getEyeHeight();
$pk->z = $from->z;
$pk->bodyYaw = $from->yaw;
$pk->pitch = $from->pitch;
@ -1145,7 +1174,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->newPosition = null;
}else{
$this->forceMovement = null;
if($this->nextChunkOrderRun > 20){
if($distanceSquared != 0 and $this->nextChunkOrderRun > 20){
$this->nextChunkOrderRun = 20;
}
}
@ -1255,6 +1284,21 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->sendNextChunk();
}
if(count($this->moveToSend) > 0){
$pk = new MoveEntityPacket();
$pk->entities = $this->moveToSend;
$this->dataPacket($pk);
$this->moveToSend = [];
}
if(count($this->motionToSend) > 0){
$pk = new SetEntityMotionPacket();
$pk->entities = $this->motionToSend;
$this->dataPacket($pk);
$this->motionToSend = [];
}
$this->timings->stopTiming();
return true;
@ -1447,6 +1491,10 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->dead = true;
}
$pk = new SetDifficultyPacket();
$pk->difficulty = $this->server->getDifficulty();
$this->dataPacket($pk);
$this->server->getLogger()->info(TextFormat::AQUA . $this->username . TextFormat::WHITE . "[/" . $this->ip . ":" . $this->port . "] logged in with entity id " . $this->id . " at (" . $this->level->getName() . ", " . round($this->x, 4) . ", " . round($this->y, 4) . ", " . round($this->z, 4) . ")");
@ -2316,6 +2364,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
foreach($this->usedChunks as $index => $d){
Level::getXZ($index, $chunkX, $chunkZ);
$this->level->freeChunk($chunkX, $chunkZ, $this);
unset($this->usedChunks[$index]);
}
parent::close();
@ -2338,9 +2387,14 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
unset($this->buffer);
}
$this->perm->clearPermissions();
$this->server->removePlayer($this);
}
public function __debugInfo(){
return [];
}
/**
* Handles player data saving
*/

View File

@ -71,9 +71,9 @@ namespace pocketmine {
use pocketmine\wizard\Installer;
const VERSION = "Alpha_1.4dev";
const API_VERSION = "1.7.0";
const API_VERSION = "1.7.1";
const CODENAME = "絶好(Zekkou)ケーキ(Cake)";
const MINECRAFT_VERSION = "v0.9.5 alpha";
const MINECRAFT_VERSION = "v0.10.4 alpha";
/*
* Startup code. Do not look at it, it may harm you.
@ -136,7 +136,7 @@ namespace pocketmine {
if(!ini_get("date.timezone")){
if(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
//Success! Timezone has already been set and validated in the if statement.
//This here is just for redundancy just in case some stupid program wants to read timezone data from the ini.
//This here is just for redundancy just in case some program wants to read timezone data from the ini.
ini_set("date.timezone", $timezone);
}else{
//If system timezone detection fails or timezone is an invalid value.
@ -155,7 +155,8 @@ namespace pocketmine {
}
}else{
/*
* This is here so that stupid idiots don't come to us complaining and fill up the issue tracker when they put an incorrect timezone abbreviation in php.ini apparently.
* This is here so that people don't come to us complaining and fill up the issue tracker when they put
* an incorrect timezone abbreviation in php.ini apparently.
*/
$default_timezone = date_default_timezone_get();
if(strpos($default_timezone, "/") === false){
@ -168,13 +169,27 @@ namespace pocketmine {
function detect_system_timezone(){
switch(Utils::getOS()){
case 'win':
$regex = '/(?:Time Zone:\s*\()(UTC)(\+*\-*\d*\d*\:*\d*\d*)(?:\))/';
$regex = '/(UTC)(\+*\-*\d*\d*\:*\d*\d*)/';
exec("systeminfo", $output);
/*
* wmic timezone get Caption
* Get the timezone offset
*
* Sample Output var_dump
* array(3) {
* [0] =>
* string(7) "Caption"
* [1] =>
* string(20) "(UTC+09:30) Adelaide"
* [2] =>
* string(0) ""
* }
*/
exec("wmic timezone get Caption", $output);
$string = trim(implode("\n", $output));
//Detect the Time Zone string in systeminfo
//Detect the Time Zone string
preg_match($regex, $string, $matches);
if(!isset($matches[2]))

View File

@ -681,107 +681,112 @@ class Server{
public function getOfflinePlayerData($name){
$name = strtolower($name);
$path = $this->getDataPath() . "players/";
if(!file_exists($path . "$name.dat")){
$spawn = $this->getDefaultLevel()->getSafeSpawn();
$nbt = new Compound(false, [
new Long("firstPlayed", floor(microtime(true) * 1000)),
new Long("lastPlayed", floor(microtime(true) * 1000)),
new Enum("Pos", [
new Double(0, $spawn->x),
new Double(1, $spawn->y),
new Double(2, $spawn->z)
]),
new String("Level", $this->getDefaultLevel()->getName()),
//new String("SpawnLevel", $this->getDefaultLevel()->getName()),
//new Int("SpawnX", (int) $spawn->x),
//new Int("SpawnY", (int) $spawn->y),
//new Int("SpawnZ", (int) $spawn->z),
//new Byte("SpawnForced", 1), //TODO
new Enum("Inventory", []),
new Compound("Achievements", []),
new Int("playerGameType", $this->getGamemode()),
new Enum("Motion", [
new Double(0, 0.0),
new Double(1, 0.0),
new Double(2, 0.0)
]),
new Enum("Rotation", [
new Float(0, 0.0),
new Float(1, 0.0)
]),
new Float("FallDistance", 0.0),
new Short("Fire", 0),
new Short("Air", 0),
new Byte("OnGround", 1),
new Byte("Invulnerable", 0),
new String("NameTag", $name),
]);
$nbt->Pos->setTagType(NBT::TAG_Double);
$nbt->Inventory->setTagType(NBT::TAG_Compound);
$nbt->Motion->setTagType(NBT::TAG_Double);
$nbt->Rotation->setTagType(NBT::TAG_Float);
if(file_exists($path . "$name.dat")){
try{
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->readCompressed(file_get_contents($path . "$name.dat"));
if(file_exists($path . "$name.yml")){ //Importing old PocketMine-MP files
$data = new Config($path . "$name.yml", Config::YAML, []);
$nbt["playerGameType"] = (int) $data->get("gamemode");
$nbt["Level"] = $data->get("position")["level"];
$nbt["Pos"][0] = $data->get("position")["x"];
$nbt["Pos"][1] = $data->get("position")["y"];
$nbt["Pos"][2] = $data->get("position")["z"];
$nbt["SpawnLevel"] = $data->get("spawn")["level"];
$nbt["SpawnX"] = (int) $data->get("spawn")["x"];
$nbt["SpawnY"] = (int) $data->get("spawn")["y"];
$nbt["SpawnZ"] = (int) $data->get("spawn")["z"];
$this->logger->notice("Old Player data found for \"" . $name . "\", upgrading profile");
foreach($data->get("inventory") as $slot => $item){
if(count($item) === 3){
$nbt->Inventory[$slot + 9] = new Compound(false, [
new Short("id", $item[0]),
new Short("Damage", $item[1]),
new Byte("Count", $item[2]),
new Byte("Slot", $slot + 9),
new Byte("TrueSlot", $slot + 9)
]);
}
}
foreach($data->get("hotbar") as $slot => $itemSlot){
if(isset($nbt->Inventory[$itemSlot + 9])){
$item = $nbt->Inventory[$itemSlot + 9];
$nbt->Inventory[$slot] = new Compound(false, [
new Short("id", $item["id"]),
new Short("Damage", $item["Damage"]),
new Byte("Count", $item["Count"]),
new Byte("Slot", $slot),
new Byte("TrueSlot", $item["TrueSlot"])
]);
}
}
foreach($data->get("armor") as $slot => $item){
if(count($item) === 2){
$nbt->Inventory[$slot + 100] = new Compound(false, [
new Short("id", $item[0]),
new Short("Damage", $item[1]),
new Byte("Count", 1),
new Byte("Slot", $slot + 100)
]);
}
}
foreach($data->get("achievements") as $achievement => $status){
$nbt->Achievements[$achievement] = new Byte($achievement, $status == true ? 1 : 0);
}
unlink($path . "$name.yml");
}else{
$this->logger->notice("Player data not found for \"" . $name . "\", creating new profile");
return $nbt->getData();
}catch(\Exception $e){ //zlib decode error / corrupt data
rename($path . "$name.dat", $path . "$name.dat.bak");
$this->logger->warning("Corrupted data found for \"" . $name . "\", creating new profile");
}
$this->saveOfflinePlayerData($name, $nbt);
return $nbt;
}else{
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->readCompressed(file_get_contents($path . "$name.dat"));
return $nbt->getData();
$this->logger->notice("Player data not found for \"" . $name . "\", creating new profile");
}
$spawn = $this->getDefaultLevel()->getSafeSpawn();
$nbt = new Compound(false, [
new Long("firstPlayed", floor(microtime(true) * 1000)),
new Long("lastPlayed", floor(microtime(true) * 1000)),
new Enum("Pos", [
new Double(0, $spawn->x),
new Double(1, $spawn->y),
new Double(2, $spawn->z)
]),
new String("Level", $this->getDefaultLevel()->getName()),
//new String("SpawnLevel", $this->getDefaultLevel()->getName()),
//new Int("SpawnX", (int) $spawn->x),
//new Int("SpawnY", (int) $spawn->y),
//new Int("SpawnZ", (int) $spawn->z),
//new Byte("SpawnForced", 1), //TODO
new Enum("Inventory", []),
new Compound("Achievements", []),
new Int("playerGameType", $this->getGamemode()),
new Enum("Motion", [
new Double(0, 0.0),
new Double(1, 0.0),
new Double(2, 0.0)
]),
new Enum("Rotation", [
new Float(0, 0.0),
new Float(1, 0.0)
]),
new Float("FallDistance", 0.0),
new Short("Fire", 0),
new Short("Air", 0),
new Byte("OnGround", 1),
new Byte("Invulnerable", 0),
new String("NameTag", $name),
]);
$nbt->Pos->setTagType(NBT::TAG_Double);
$nbt->Inventory->setTagType(NBT::TAG_Compound);
$nbt->Motion->setTagType(NBT::TAG_Double);
$nbt->Rotation->setTagType(NBT::TAG_Float);
if(file_exists($path . "$name.yml")){ //Importing old PocketMine-MP files
$data = new Config($path . "$name.yml", Config::YAML, []);
$nbt["playerGameType"] = (int) $data->get("gamemode");
$nbt["Level"] = $data->get("position")["level"];
$nbt["Pos"][0] = $data->get("position")["x"];
$nbt["Pos"][1] = $data->get("position")["y"];
$nbt["Pos"][2] = $data->get("position")["z"];
$nbt["SpawnLevel"] = $data->get("spawn")["level"];
$nbt["SpawnX"] = (int) $data->get("spawn")["x"];
$nbt["SpawnY"] = (int) $data->get("spawn")["y"];
$nbt["SpawnZ"] = (int) $data->get("spawn")["z"];
$this->logger->notice("Old Player data found for \"" . $name . "\", upgrading profile");
foreach($data->get("inventory") as $slot => $item){
if(count($item) === 3){
$nbt->Inventory[$slot + 9] = new Compound(false, [
new Short("id", $item[0]),
new Short("Damage", $item[1]),
new Byte("Count", $item[2]),
new Byte("Slot", $slot + 9),
new Byte("TrueSlot", $slot + 9)
]);
}
}
foreach($data->get("hotbar") as $slot => $itemSlot){
if(isset($nbt->Inventory[$itemSlot + 9])){
$item = $nbt->Inventory[$itemSlot + 9];
$nbt->Inventory[$slot] = new Compound(false, [
new Short("id", $item["id"]),
new Short("Damage", $item["Damage"]),
new Byte("Count", $item["Count"]),
new Byte("Slot", $slot),
new Byte("TrueSlot", $item["TrueSlot"])
]);
}
}
foreach($data->get("armor") as $slot => $item){
if(count($item) === 2){
$nbt->Inventory[$slot + 100] = new Compound(false, [
new Short("id", $item[0]),
new Short("Damage", $item[1]),
new Byte("Count", 1),
new Byte("Slot", $slot + 100)
]);
}
}
foreach($data->get("achievements") as $achievement => $status){
$nbt->Achievements[$achievement] = new Byte($achievement, $status == true ? 1 : 0);
}
unlink($path . "$name.yml");
}
$this->saveOfflinePlayerData($name, $nbt);
return $nbt;
}
/**
@ -1401,7 +1406,7 @@ class Server{
/**
* @return Config
*/
public function getOPs(){
public function getOps(){
return $this->operators;
}
@ -1564,7 +1569,7 @@ class Server{
$this->addInterface($this->mainInterface = new RakLibInterface($this));
$this->logger->info("This server is running " . $this->getName() . " version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(true) . TextFormat::RESET . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
$this->logger->info("This server is running " . $this->getName() . " version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(true) . TextFormat::WHITE . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
$this->logger->info($this->getName() . " is distributed under the LGPL License", true, true, 0);
PluginManager::$pluginParentTimer = new TimingsHandler("** Plugins");
@ -2083,7 +2088,14 @@ class Server{
//Do level ticks
foreach($this->getLevels() as $level){
$level->doTick($currentTick);
try{
$level->doTick($currentTick);
}catch (\Exception $e){
$this->logger->critical("Could not tick level ".$level->getName().": ".$e->getMessage());
if($this->logger instanceof MainLogger){
$this->logger->logException($e);
}
}
}
}
@ -2192,7 +2204,13 @@ class Server{
}
}
$this->generationManager->process();
try{
$this->generationManager->process();
}catch (\Exception $e){
if($this->logger instanceof MainLogger){
$this->logger->logException($e);
}
}
if(($this->tickCounter % 100) === 0){
foreach($this->levels as $level){

View File

@ -144,6 +144,7 @@ class Block extends Position implements Metadatable{
const SUGARCANE_BLOCK = 83;
const FENCE = 85;
const FENCE_OAK = 85;
const PUMPKIN = 86;
const NETHERRACK = 87;
const SOUL_SAND = 88;
@ -228,6 +229,17 @@ class Block extends Position implements Metadatable{
const HARDENED_CLAY = 172;
const COAL_BLOCK = 173;
const FENCE_GATE_SPRUCE = 183;
const FENCE_GATE_BIRCH = 184;
const FENCE_GATE_JUNGLE = 185;
const FENCE_GATE_DARK_OAK = 186;
const FENCE_GATE_ACACIA = 187;
const FENCE_SPRUCE = 188;
const FENCE_BIRCH = 189;
const FENCE_JUNGLE = 190;
const FENCE_DARK_OAK = 191;
const FENCE_ACACIA = 192;
const PODZOL = 243;
const BEETROOT_BLOCK = 244;
const STONECUTTER = 245;
@ -354,7 +366,16 @@ class Block extends Position implements Metadatable{
[Item::WOODEN_DOOR, 0],
[Item::TRAPDOOR, 0],
[Item::FENCE, 0],
[Item::FENCE_SPRUCE, 0],
[Item::FENCE_BIRCH, 0],
[Item::FENCE_DARK_OAK, 0],
[Item::FENCE_JUNGLE, 0],
[Item::FENCE_GATE, 0],
[Item::FENCE_GATE_BIRCH, 0],
[Item::FENCE_GATE_SPRUCE, 0],
[Item::FENCE_GATE_DARK_OAK, 0],
[Item::FENCE_GATE_JUNGLE, 0],
[Item::FENCE_GATE_ACACIA, 0],
[Item::IRON_BARS, 0],
[Item::BED, 0],
[Item::BOOKSHELF, 0],
@ -665,12 +686,22 @@ class Block extends Position implements Metadatable{
self::$list[self::HARDENED_CLAY] = HardenedClay::class;;
self::$list[self::COAL_BLOCK] = Coal::class;;
self::$list[self::FENCE_GATE_SPRUCE] = FenceGateSpruce::class;
self::$list[self::FENCE_GATE_BIRCH] = FenceGateBirch::class;
self::$list[self::FENCE_GATE_JUNGLE] = FenceGateJungle::class;
self::$list[self::FENCE_GATE_DARK_OAK] = FenceGateDarkOak::class;
self::$list[self::FENCE_GATE_ACACIA] = FenceGateAcacia::class;
self::$list[self::FENCE_SPRUCE] = FenceSpruce::class;
self::$list[self::FENCE_BIRCH] = FenceBirch::class;
self::$list[self::FENCE_DARK_OAK] = FenceDarkOak::class;
self::$list[self::FENCE_JUNGLE] = FenceJungle::class;
self::$list[self::FENCE_ACACIA] = FenceAcacia::class;
self::$list[self::PODZOL] = Podzol::class;;
self::$list[self::BEETROOT_BLOCK] = Beetroot::class;;
self::$list[self::STONECUTTER] = Stonecutter::class;;
self::$list[self::GLOWING_OBSIDIAN] = GlowingObsidian::class;;
self::$list[self::NETHER_REACTOR] = NetherReactor::class;;
}
}

View File

@ -21,12 +21,11 @@
namespace pocketmine\block;
use pocketmine\math\AxisAlignedBB;
class Fence extends Transparent{
public function __construct(){
parent::__construct(self::FENCE, 0, "Fence");
parent::__construct(self::FENCE, 0, "Oak Fence");
$this->isFullBlock = false;
$this->hardness = 15;
}
@ -48,13 +47,13 @@ class Fence extends Transparent{
$this->y,
$this->z + $f2,
$this->x + $f1,
$this->y + 1,
$this->y + 1.5,
$this->z + $f3
);
}
public function canConnect(Block $block){
return ($block->getID() !== self::FENCE and $block->getID() !== self::FENCE_GATE) ? $block->isSolid : true;
return (!($block instanceof Fence) and !($block instanceof FenceGate)) ? $block->isSolid : true;
}
}

View File

@ -0,0 +1,30 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceAcacia extends Fence{
public function __construct(){
Transparent::__construct(self::FENCE_ACACIA, 0, "Acacia Fence");
$this->isFullBlock = false;
$this->hardness = 15;
}
}

View File

@ -0,0 +1,30 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceBirch extends Fence{
public function __construct(){
Transparent::__construct(self::FENCE_BIRCH, 0, "Birch Fence");
$this->isFullBlock = false;
$this->hardness = 15;
}
}

View File

@ -0,0 +1,30 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceDarkOak extends Fence{
public function __construct(){
Transparent::__construct(self::FENCE_DARK_OAK, 0, "Dark Oak Fence");
$this->isFullBlock = false;
$this->hardness = 15;
}
}

View File

@ -27,7 +27,7 @@ use pocketmine\Player;
class FenceGate extends Transparent{
public function __construct($meta = 0){
parent::__construct(self::FENCE_GATE, $meta, "Fence Gate");
parent::__construct(self::FENCE_GATE, $meta, "Oak Fence Gate");
$this->isActivable = true;
if(($this->meta & 0x04) === 0x04){
$this->isFullBlock = true;
@ -51,7 +51,7 @@ class FenceGate extends Transparent{
$this->y,
$this->z + 0.375,
$this->x + 1,
$this->y + 1,
$this->y + 1.5,
$this->z + 0.625
);
}else{
@ -60,7 +60,7 @@ class FenceGate extends Transparent{
$this->y,
$this->z,
$this->x + 0.625,
$this->y + 1,
$this->y + 1.5,
$this->z + 1
);
}

View File

@ -0,0 +1,36 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceGateAcacia extends FenceGate{
public function __construct($meta = 0){
Transparent::__construct(self::FENCE_GATE_ACACIA, $meta, "Acacia Fence Gate");
$this->isActivable = true;
if(($this->meta & 0x04) === 0x04){
$this->isFullBlock = true;
}else{
$this->isFullBlock = false;
}
$this->hardness = 15;
}
}

View File

@ -0,0 +1,36 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceGateBirch extends FenceGate{
public function __construct($meta = 0){
Transparent::__construct(self::FENCE_GATE_BIRCH, $meta, "Birch Fence Gate");
$this->isActivable = true;
if(($this->meta & 0x04) === 0x04){
$this->isFullBlock = true;
}else{
$this->isFullBlock = false;
}
$this->hardness = 15;
}
}

View File

@ -0,0 +1,36 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceGateDarkOak extends FenceGate{
public function __construct($meta = 0){
Transparent::__construct(self::FENCE_GATE_DARK_OAK, $meta, "Dark Oak Fence Gate");
$this->isActivable = true;
if(($this->meta & 0x04) === 0x04){
$this->isFullBlock = true;
}else{
$this->isFullBlock = false;
}
$this->hardness = 15;
}
}

View File

@ -0,0 +1,36 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceGateJungle extends FenceGate{
public function __construct($meta = 0){
Transparent::__construct(self::FENCE_GATE_JUNGLE, $meta, "Jungle Fence Gate");
$this->isActivable = true;
if(($this->meta & 0x04) === 0x04){
$this->isFullBlock = true;
}else{
$this->isFullBlock = false;
}
$this->hardness = 15;
}
}

View File

@ -0,0 +1,36 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceGateSpruce extends FenceGate{
public function __construct($meta = 0){
Transparent::__construct(self::FENCE_GATE_SPRUCE, $meta, "Spruce Fence Gate");
$this->isActivable = true;
if(($this->meta & 0x04) === 0x04){
$this->isFullBlock = true;
}else{
$this->isFullBlock = false;
}
$this->hardness = 15;
}
}

View File

@ -0,0 +1,30 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceJungle extends Fence{
public function __construct(){
Transparent::__construct(self::FENCE_JUNGLE, 0, "Jungle Fence");
$this->isFullBlock = false;
$this->hardness = 15;
}
}

View File

@ -0,0 +1,30 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceSpruce extends Fence{
public function __construct(){
Transparent::__construct(self::FENCE_SPRUCE, 0, "Spruce Fence");
$this->isFullBlock = false;
$this->hardness = 15;
}
}

View File

@ -21,12 +21,7 @@
namespace pocketmine\block;
abstract class Solid extends Block{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
$this->isSolid = true;
$this->isFullBlock = true;
}
public $isSolid = true;
public $isFullBlock = true;
}

View File

@ -47,14 +47,11 @@ class StoneWall extends Transparent{
$f1 = $flag3 ? 1 : 0.75;
$f2 = $flag ? 0 : 0.25;
$f3 = $flag1 ? 1 : 0.75;
$f4 = 1;
if($flag and $flag1 and !$flag2 and !$flag3){
$f4 = 0.8125;
$f = 0.3125;
$f1 = 0.6875;
}elseif(!$flag and !$flag1 and $flag2 and $flag3){
$f4 = 0.8125;
$f2 = 0.3125;
$f3 = 0.6875;
}
@ -64,7 +61,7 @@ class StoneWall extends Transparent{
$this->y,
$this->z + $f2,
$this->x + $f1,
$this->y + $f4,
$this->y + 1.5,
$this->z + $f3
);
}

View File

@ -23,14 +23,18 @@ namespace pocketmine\block;
class Wood2 extends Wood{
const ACACIA = 0;
const DARK_OAK = 1;
public function __construct($meta = 0){
Solid::__construct(self::WOOD2, $meta, "Wood");
$names = [
0 => "Acacia Wood",
1 => "Dark Oak Wood"
1 => "Dark Oak Wood",
2 => ""
];
$this->name = $names[$this->meta & 0x03];
$this->hardness = 10;
}
}
}

View File

@ -22,6 +22,7 @@
namespace pocketmine\command;
use pocketmine\Server;
use pocketmine\utils\MainLogger;
use pocketmine\utils\TextFormat;
class FormattedCommandAlias extends Command{
@ -49,6 +50,9 @@ class FormattedCommandAlias extends Command{
$sender->sendMessage(TextFormat::RED . $e->getMessage());
}else{
$sender->sendMessage(TextFormat::RED . "An internal error occurred while attempting to perform this command");
if(($logger = $sender->getServer()->getLogger()) instanceof MainLogger){
$logger->logException($e);
}
}
return false;

View File

@ -56,6 +56,7 @@ use pocketmine\command\defaults\VanillaCommand;
use pocketmine\command\defaults\VersionCommand;
use pocketmine\command\defaults\WhitelistCommand;
use pocketmine\Server;
use pocketmine\utils\MainLogger;
class SimpleCommandMap implements CommandMap{
@ -181,7 +182,10 @@ class SimpleCommandMap implements CommandMap{
try{
$target->execute($sender, $sentCommandLabel, $args);
}catch(\Exception $e){
$this->server->getLogger()->critical("Unhandled exception executing command '". $commandLine ,"' in ". $target);
$this->server->getLogger()->critical("Unhandled exception executing command '". $commandLine ."' in ". $target.": ".$e->getMessage());
if(($logger = $sender->getServer()->getLogger()) instanceof MainLogger){
$logger->logException($e);
}
}
$target->timings->stopTiming();

View File

@ -22,6 +22,7 @@
namespace pocketmine\command\defaults;
use pocketmine\command\CommandSender;
use pocketmine\network\protocol\SetDifficultyPacket;
use pocketmine\Server;
use pocketmine\utils\TextFormat;
@ -55,6 +56,9 @@ class DifficultyCommand extends VanillaCommand{
if($difficulty !== -1){
$sender->getServer()->setConfigInt("difficulty", $difficulty);
$pk = new SetDifficultyPacket();
$pk->difficulty = $sender->getServer()->getDifficulty();
Server::broadcastPacket($sender->getServer()->getOnlinePlayers(), $pk);
$sender->sendMessage("Set difficulty to " . $difficulty);
}else{
$sender->sendMessage("Unknown difficulty");

View File

@ -24,7 +24,6 @@ namespace pocketmine\entity;
use pocketmine\level\format\FullChunk;
use pocketmine\nbt\tag\Compound;
use pocketmine\network\protocol\AddEntityPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\Player;
class Arrow extends Projectile{
@ -73,11 +72,7 @@ class Arrow extends Projectile{
$pk->did = 0; //TODO: send motion here
$player->dataPacket($pk);
$pk = new SetEntityMotionPacket();
$pk->entities = [
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
];
$player->dataPacket($pk);
$player->addEntityMotion($this->getId(), $this->motionX, $this->motionY, $this->motionZ);
parent::spawnTo($player);
}

View File

@ -51,11 +51,9 @@ use pocketmine\nbt\tag\Float;
use pocketmine\nbt\tag\Short;
use pocketmine\nbt\tag\String;
use pocketmine\Network;
use pocketmine\network\protocol\MoveEntityPacket;
use pocketmine\network\protocol\MovePlayerPacket;
use pocketmine\network\protocol\RemoveEntityPacket;
use pocketmine\network\protocol\SetEntityDataPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\network\protocol\SetTimePacket;
use pocketmine\Player;
use pocketmine\plugin\Plugin;
@ -176,6 +174,7 @@ abstract class Entity extends Location implements Metadatable{
$this->id = Entity::$entityCount++;
$this->justCreated = true;
$this->namedtag = $nbt;
$this->chunk = $chunk;
$this->setLevel($chunk->getProvider()->getLevel());
$this->server = $chunk->getProvider()->getLevel()->getServer();
@ -593,15 +592,13 @@ abstract class Entity extends Location implements Metadatable{
$pk->yaw = $this->yaw;
$pk->pitch = $this->pitch;
$pk->bodyYaw = $this->yaw;
Server::broadcastPacket($this->hasSpawned, $pk);
}else{
//TODO: add to move list
$pk = new MoveEntityPacket();
$pk->entities = [
[$this->id, $this->x, $this->y + $this->getEyeHeight(), $this->z, $this->yaw, $this->pitch]
];
foreach($this->hasSpawned as $player){
$player->addEntityMovement($this->id, $this->x, $this->y + $this->getEyeHeight(), $this->z, $this->yaw, $this->pitch);
}
}
Server::broadcastPacket($this->hasSpawned, $pk);
}
if(($this->lastMotionX != $this->motionX or $this->lastMotionY != $this->motionY or $this->lastMotionZ != $this->motionZ)){
@ -609,12 +606,9 @@ abstract class Entity extends Location implements Metadatable{
$this->lastMotionY = $this->motionY;
$this->lastMotionZ = $this->motionZ;
$pk = new SetEntityMotionPacket();
$pk->entities = [
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
];
Server::broadcastPacket($this->hasSpawned, $pk);
foreach($this->hasSpawned as $player){
$player->addEntityMotion($this->id, $this->motionX, $this->motionY, $this->motionZ);
}
if($this instanceof Player){
$this->motionX = 0;
@ -1151,11 +1145,7 @@ abstract class Entity extends Location implements Metadatable{
if(!$this->justCreated){
if($this instanceof Player){
$pk = new SetEntityMotionPacket();
$pk->entities = [
[0, $this->motionX, $this->motionY, $this->motionZ]
];
$this->dataPacket($pk);
$this->addEntityMotion(0, $this->motionX, $this->motionY, $this->motionZ);
}
$this->updateMovement();
}

View File

@ -31,7 +31,6 @@ use pocketmine\math\Vector3;
use pocketmine\nbt\tag\Byte;
use pocketmine\nbt\tag\Int;
use pocketmine\network\protocol\AddEntityPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\Player;
class FallingSand extends Entity{
@ -159,11 +158,7 @@ class FallingSand extends Entity{
$pk->did = -($this->getBlock() | $this->getDamage() << 0x10);
$player->dataPacket($pk);
$pk = new SetEntityMotionPacket();
$pk->entities = [
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
];
$player->dataPacket($pk);
$player->addEntityMotion($this->getId(), $this->motionX, $this->motionY, $this->motionZ);
parent::spawnTo($player);
}

View File

@ -32,7 +32,6 @@ use pocketmine\nbt\tag\Short;
use pocketmine\Network;
use pocketmine\network\protocol\AddPlayerPacket;
use pocketmine\network\protocol\RemovePlayerPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\Player;
use pocketmine\utils\TextFormat;
@ -169,18 +168,13 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$pk->z = $this->z;
$pk->yaw = $this->yaw;
$pk->pitch = $this->pitch;
$pk->unknown1 = 0;
$pk->unknown2 = 0;
$item = $this->getInventory()->getItemInHand();
$pk->item = $item->getID();
$pk->meta = $item->getDamage();
$pk->metadata = $this->getData();
$player->dataPacket($pk);
$pk = new SetEntityMotionPacket();
$pk->entities = [
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
];
$player->dataPacket($pk);
$this->inventory->sendHeldItem($player);
$player->addEntityMotion($this->getId(), $this->motionX, $this->motionY, $this->motionZ);
$this->inventory->sendArmorContents($player);
}
@ -218,7 +212,9 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$this->getInventory()->close($player);
}
}
$this->inventory = null;
foreach($this->inventory->getViewers() as $viewer){
$viewer->removeWindow($this->inventory);
}
parent::close();
}
}

View File

@ -32,7 +32,6 @@ use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Short;
use pocketmine\nbt\tag\String;
use pocketmine\network\protocol\AddItemEntityPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\Player;
class Item extends Entity{
@ -237,11 +236,7 @@ class Item extends Entity{
$pk->item = $this->getItem();
$player->dataPacket($pk);
$pk = new SetEntityMotionPacket();
$pk->entities = [
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
];
$player->dataPacket($pk);
$player->addEntityMotion($this->getId(), $this->motionX, $this->motionY, $this->motionZ);
parent::spawnTo($player);
}

View File

@ -28,7 +28,6 @@ use pocketmine\event\entity\ExplosionPrimeEvent;
use pocketmine\level\Explosion;
use pocketmine\nbt\tag\Byte;
use pocketmine\network\protocol\AddEntityPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\Player;
class PrimedTNT extends Entity implements Explosive{
@ -147,11 +146,7 @@ class PrimedTNT extends Entity implements Explosive{
$pk->did = 0;
$player->dataPacket($pk);
$pk = new SetEntityMotionPacket();
$pk->entities = [
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
];
$player->dataPacket($pk);
$player->addEntityMotion($this->getId(), $this->motionX, $this->motionY, $this->motionZ);
parent::spawnTo($player);
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\entity;
use pocketmine\level\format\FullChunk;
use pocketmine\nbt\tag\Compound;
use pocketmine\network\protocol\AddEntityPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\Player;
class Snowball extends Projectile{
@ -72,11 +71,7 @@ class Snowball extends Projectile{
$pk->did = 0; //TODO: send motion here
$player->dataPacket($pk);
$pk = new SetEntityMotionPacket();
$pk->entities = [
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
];
$player->dataPacket($pk);
$player->addEntityMotion($this->getId(), $this->motionX, $this->motionY, $this->motionZ);
parent::spawnTo($player);
}

View File

@ -24,7 +24,6 @@ namespace pocketmine\entity;
use pocketmine\nbt\tag\Int;
use pocketmine\network\protocol\AddMobPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\Player;
class Villager extends Creature implements NPC, Ageable{
@ -64,11 +63,7 @@ class Villager extends Creature implements NPC, Ageable{
$pk->metadata = $this->getData();
$player->dataPacket($pk);
$pk = new SetEntityMotionPacket();
$pk->entities = [
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
];
$player->dataPacket($pk);
$player->addEntityMotion($this->getId(), $this->motionX, $this->motionY, $this->motionZ);
parent::spawnTo($player);
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\entity;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\item\Item as ItemItem;
use pocketmine\network\protocol\AddMobPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\Player;
class Zombie extends Monster{
@ -52,11 +51,7 @@ class Zombie extends Monster{
$pk->metadata = $this->getData();
$player->dataPacket($pk);
$pk = new SetEntityMotionPacket();
$pk->entities = [
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
];
$player->dataPacket($pk);
$player->addEntityMotion($this->getId(), $this->motionX, $this->motionY, $this->motionZ);
parent::spawnTo($player);
}

View File

@ -71,8 +71,18 @@ class CraftingManager{
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::BED, 0, 1)))->addIngredient(Item::get(Item::WOOL, null, 3))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 3)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::CHEST, 0, 1)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 8)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE, 0, 2)))->addIngredient(Item::get(Item::STICK, 0, 6)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_GATE, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 4))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 2)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE, 0, 3)))->addIngredient(Item::get(Item::STICK, 0, 4))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::OAK, 2)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_SPRUCE, 0, 3)))->addIngredient(Item::get(Item::STICK, 0, 2))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::SPRUCE, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_BIRCH, 0, 3)))->addIngredient(Item::get(Item::STICK, 0, 2))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::BIRCH, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_JUNGLE, 0, 3)))->addIngredient(Item::get(Item::STICK, 0, 2))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::JUNGLE, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_ACACIA, 0, 3)))->addIngredient(Item::get(Item::STICK, 0, 2))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::ACACIA, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_DARK_OAK, 0, 3)))->addIngredient(Item::get(Item::STICK, 0, 2))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::DARK_OAK, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_GATE, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 4))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::OAK, 2))->addIngredient(Item::get(Item::STICK, 0, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_GATE_SPRUCE, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 4))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::SPRUCE, 2))->addIngredient(Item::get(Item::STICK, 0, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_GATE_BIRCH, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 4))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::BIRCH, 2))->addIngredient(Item::get(Item::STICK, 0, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_GATE_JUNGLE, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 4))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::JUNGLE, 2))->addIngredient(Item::get(Item::STICK, 0, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_GATE_DARK_OAK, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 4))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::DARK_OAK, 2))->addIngredient(Item::get(Item::STICK, 0, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FENCE_GATE_ACACIA, 0, 1)))->addIngredient(Item::get(Item::STICK, 0, 4))->addIngredient(Item::get(Item::WOODEN_PLANK, Planks::ACACIA, 2))->addIngredient(Item::get(Item::STICK, 0, 4)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::FURNACE, 0, 1)))->addIngredient(Item::get(Item::COBBLESTONE, 0, 8)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::GLASS_PANE, 0, 16)))->addIngredient(Item::get(Item::GLASS, 0, 6)));
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::LADDER, 0, 3)))->addIngredient(Item::get(Item::STICK, 0, 7)));

View File

@ -38,7 +38,17 @@ abstract class Fuel{
Item::WOODEN_HOE => 200,
Item::STICK => 100,
Item::FENCE => 300,
Item::FENCE_SPRUCE => 300,
Item::FENCE_BIRCH => 300,
Item::FENCE_JUNGLE => 300,
Item::FENCE_ACACIA => 300,
Item::FENCE_DARK_OAK => 300,
Item::FENCE_GATE => 300,
Item::FENCE_GATE_SPRUCE => 300,
Item::FENCE_GATE_BIRCH => 300,
Item::FENCE_GATE_JUNGLE => 300,
Item::FENCE_GATE_ACACIA => 300,
Item::FENCE_GATE_DARK_OAK => 300,
Item::WOODEN_STAIRS => 300,
Item::SPRUCE_WOOD_STAIRS => 300,
Item::BIRCH_WOOD_STAIRS => 300,

View File

@ -202,8 +202,8 @@ class PlayerInventory extends BaseInventory{
public function setItem($index, Item $item, $source = null){
if($index < 0 or $index >= $this->size){
return false;
}elseif($item->getID() === 0){
$this->clear($index, $source);
}elseif($item->getID() === 0 or $item->getCount() <= 0){
return $this->clear($index, $source);
}
if($index >= $this->getSize()){ //Armor change

View File

@ -220,6 +220,17 @@ class Item{
const HARDENED_CLAY = 172;
const COAL_BLOCK = 173;
const FENCE_GATE_SPRUCE = 183;
const FENCE_GATE_BIRCH = 184;
const FENCE_GATE_JUNGLE = 185;
const FENCE_GATE_DARK_OAK = 186;
const FENCE_GATE_ACACIA = 187;
const FENCE_SPRUCE = 188;
const FENCE_BIRCH = 189;
const FENCE_JUNGLE = 190;
const FENCE_DARK_OAK = 191;
const FENCE_ACACIA = 192;
const PODZOL = 243;
const BEETROOT_BLOCK = 244;
const STONECUTTER = 245;

View File

@ -92,6 +92,7 @@ use pocketmine\tile\Chest;
use pocketmine\tile\Tile;
use pocketmine\utils\Cache;
use pocketmine\utils\LevelException;
use pocketmine\utils\MainLogger;
use pocketmine\utils\ReversePriorityQueue;
use pocketmine\utils\TextFormat;
@ -430,7 +431,7 @@ class Level implements ChunkManager, Metadatable{
if($this->stopTime == true){
return;
}else{
$this->time += 2.5;
$this->time += 1.25;
}
}
@ -1369,7 +1370,7 @@ class Level implements ChunkManager, Metadatable{
$chunk = $this->getChunk($pos->x >> 4, $pos->z >> 4);
if($chunk instanceof FullChunk){
return $chunk->getTile($pos->x & 0x0f, $pos->y & 0x7f, $pos->z & 0x0f);
return $chunk->getTile($pos->x & 0x0f, $pos->y & 0xff, $pos->z & 0x0f);
}
return null;
@ -1876,12 +1877,20 @@ class Level implements ChunkManager, Metadatable{
}
}
if($chunk instanceof FullChunk and $chunk->hasChanged() and $this->getAutoSave()){
$this->provider->setChunk($x, $z, $chunk);
$this->provider->saveChunk($x, $z);
try{
if($chunk instanceof FullChunk and $chunk->hasChanged() and $this->getAutoSave()){
$this->provider->setChunk($x, $z, $chunk);
$this->provider->saveChunk($x, $z);
}
$this->provider->unloadChunk($x, $z, $safe);
}catch (\Exception $e){
$logger = $this->server->getLogger();
$logger->error("Error when unloading a chunk: ".$e->getMessage());
if($logger instanceof MainLogger){
$logger->logException($e);
}
}
$this->provider->unloadChunk($x, $z, $safe);
unset($this->chunks[$index]);
unset($this->usedChunks[$index]);
Cache::remove("world:" . $this->getID() . ":$index");
@ -1927,18 +1936,18 @@ class Level implements ChunkManager, Metadatable{
}
if($spawn instanceof Vector3){
$v = $spawn->floor();
for(; $v->y > 0; $v->y -= 2){
for(; $v->y > 0; --$v->y){
$b = $this->getBlock($v);
if($b === null){
return $spawn;
}elseif(!($b instanceof Air)){
$v->y += 1;
}elseif($b->isSolid){
$v->y++;
break;
}
}
for(; $v->y < 128; ++$v->y){
if($this->getBlock($v->getSide(1)) instanceof Air){
if($this->getBlock($v) instanceof Air){
if(!$this->getBlock($v->getSide(1))->isSolid){
if(!$this->getBlock($v)->isSolid){
return new Position($spawn->x, $v->y === Math::floorFloat($spawn->y) ? $spawn->y : $v->y, $spawn->z, $this);
}
}else{

View File

@ -133,14 +133,19 @@ class Chunk extends BaseChunk{
*/
public static function fromBinary($data, LevelProvider $provider = null){
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->readCompressed($data, ZLIB_ENCODING_DEFLATE);
$chunk = $nbt->getData();
try{
$nbt->readCompressed($data, ZLIB_ENCODING_DEFLATE);
$chunk = $nbt->getData();
if(!isset($chunk->Level) or !($chunk->Level instanceof Compound)){
if(!isset($chunk->Level) or !($chunk->Level instanceof Compound)){
return null;
}
return new Chunk($provider instanceof LevelProvider ? $provider : Anvil::class, $chunk->Level);
}catch (\Exception $e){
return null;
}
return new Chunk($provider instanceof LevelProvider ? $provider : Anvil::class, $chunk->Level);
}
public function toBinary(){

View File

@ -31,6 +31,7 @@ use pocketmine\nbt\tag\Int;
use pocketmine\nbt\tag\IntArray;
use pocketmine\nbt\tag\Long;
use pocketmine\utils\Binary;
use pocketmine\utils\MainLogger;
class RegionLoader extends \pocketmine\level\format\mcregion\RegionLoader{
const VERSION = 1;
@ -88,11 +89,11 @@ class RegionLoader extends \pocketmine\level\format\mcregion\RegionLoader{
}
if($length > ($this->locationTable[$index][1] << 12)){ //Invalid chunk, bigger than defined number of sectors
trigger_error("Corrupted bigger chunk detected", E_USER_WARNING);
MainLogger::getLogger()->error("Corrupted chunk detected");
$this->locationTable[$index][1] = $length >> 12;
$this->writeLocationIndex($index);
}elseif($compression !== self::COMPRESSION_ZLIB and $compression !== self::COMPRESSION_GZIP){
trigger_error("Invalid compression type", E_USER_WARNING);
MainLogger::getLogger()->error("Invalid compression type");
return false;
}
@ -101,7 +102,7 @@ class RegionLoader extends \pocketmine\level\format\mcregion\RegionLoader{
if($chunk instanceof Chunk){
return $chunk;
}elseif($forward === false){
trigger_error("Corrupted chunk detected", E_USER_WARNING);
MainLogger::getLogger()->error("Corrupted chunk detected");
$this->generateChunk($x, $z);
return $this->readChunk($x, $z, $generate, true);

View File

@ -237,13 +237,16 @@ abstract class BaseFullChunk implements FullChunk{
public function addTile(Tile $tile){
$this->tiles[$tile->getID()] = $tile;
$this->tiles[(($tile->z & 0x0f) << 8) | (($tile->x & 0x0f) << 4) | ($tile->y & 0x7f)] = $tile;
if(isset($this->tileList[$index = (($tile->z & 0x0f) << 12) | (($tile->x & 0x0f) << 8) | ($tile->y & 0xff)]) and $this->tileList[$index] !== $tile){
$this->tileList[$index]->close();
}
$this->tileList[$index] = $tile;
$this->hasChanged = true;
}
public function removeTile(Tile $tile){
unset($this->tiles[$tile->getID()]);
unset($this->tiles[(($tile->z & 0x0f) << 8) | (($tile->x & 0x0f) << 4) | ($tile->y & 0x7f)]);
unset($this->tileList[(($tile->z & 0x0f) << 12) | (($tile->x & 0x0f) << 8) | ($tile->y & 0xff)]);
$this->hasChanged = true;
}
@ -256,7 +259,7 @@ abstract class BaseFullChunk implements FullChunk{
}
public function getTile($x, $y, $z){
$index = ($z << 8) | ($x << 4) | $y;
$index = ($z << 12) | ($x << 8) | $y;
return isset($this->tileList[$index]) ? $this->tileList[$index] : null;
}
@ -329,4 +332,4 @@ abstract class BaseFullChunk implements FullChunk{
$this->hasChanged = (bool) $changed;
}
}
}

View File

@ -255,14 +255,19 @@ class Chunk extends BaseFullChunk{
*/
public static function fromBinary($data, LevelProvider $provider = null){
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->readCompressed($data, ZLIB_ENCODING_DEFLATE);
$chunk = $nbt->getData();
if(!isset($chunk->Level) or !($chunk->Level instanceof Compound)){
try{
$nbt->readCompressed($data, ZLIB_ENCODING_DEFLATE);
$chunk = $nbt->getData();
if(!isset($chunk->Level) or !($chunk->Level instanceof Compound)){
return null;
}
return new Chunk($provider instanceof LevelProvider ? $provider : McRegion::class, $chunk->Level);
}catch (\Exception $e){
return null;
}
return new Chunk($provider instanceof LevelProvider ? $provider : McRegion::class, $chunk->Level);
}
public function toBinary(){

View File

@ -32,6 +32,7 @@ use pocketmine\nbt\tag\Int;
use pocketmine\nbt\tag\IntArray;
use pocketmine\nbt\tag\Long;
use pocketmine\utils\Binary;
use pocketmine\utils\MainLogger;
class RegionLoader{
const VERSION = 1;
@ -109,11 +110,11 @@ class RegionLoader{
}
if($length > ($this->locationTable[$index][1] << 12)){ //Invalid chunk, bigger than defined number of sectors
trigger_error("Corrupted bigger chunk detected", E_USER_WARNING);
MainLogger::getLogger()->error("Corrupted bigger chunk detected");
$this->locationTable[$index][1] = $length >> 12;
$this->writeLocationIndex($index);
}elseif($compression !== self::COMPRESSION_ZLIB and $compression !== self::COMPRESSION_GZIP){
trigger_error("Invalid compression type", E_USER_WARNING);
MainLogger::getLogger()->error("Invalid compression type");
return false;
}
@ -122,7 +123,7 @@ class RegionLoader{
if($chunk instanceof Chunk){
return $chunk;
}elseif($forward === false){
trigger_error("Corrupted chunk detected", E_USER_WARNING);
MainLogger::getLogger()->error("Corrupted chunk detected");
$this->generateChunk($x, $z);
return $this->readChunk($x, $z, $generate, true);
@ -212,11 +213,14 @@ class RegionLoader{
if($length <= 1){
$this->locationTable[$i] = [0, 0, 0]; //Non-generated chunk, remove it from index
}
$chunk = zlib_decode(substr($chunk, 5));
if(strlen($chunk) <= 1){
try{
$chunk = zlib_decode(substr($chunk, 5));
}catch (\Exception $e){
$this->locationTable[$i] = [0, 0, 0]; //Corrupted chunk, remove it
continue;
}
$chunk = chr(self::COMPRESSION_ZLIB) . zlib_encode($chunk, 15, 9);
$chunk = Binary::writeInt(strlen($chunk)) . $chunk;
$sectors = (int) ceil(strlen($chunk) / 4096);

View File

@ -60,6 +60,7 @@ use pocketmine\network\protocol\RemovePlayerPacket;
use pocketmine\network\protocol\RespawnPacket;
use pocketmine\network\protocol\RotateHeadPacket;
use pocketmine\network\protocol\SendInventoryPacket;
use pocketmine\network\protocol\SetDifficultyPacket;
use pocketmine\network\protocol\SetEntityDataPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\network\protocol\SetHealthPacket;
@ -183,8 +184,8 @@ class RakLibInterface implements ServerInstance, SourceInterface{
if(\pocketmine\DEBUG > 1){
$logger = $this->server->getLogger();
if($logger instanceof MainLogger){
$logger->logException($e);
$logger->debug("Packet ".get_class($pk)." 0x".bin2hex($packet->buffer));
$logger->logException($e);
}
}
}
@ -328,6 +329,7 @@ class RakLibInterface implements ServerInstance, SourceInterface{
$this->registerPacket(ProtocolInfo::ADVENTURE_SETTINGS_PACKET, AdventureSettingsPacket::class);
$this->registerPacket(ProtocolInfo::ENTITY_DATA_PACKET, EntityDataPacket::class);
$this->registerPacket(ProtocolInfo::UNLOAD_CHUNK_PACKET, UnloadChunkPacket::class);
$this->registerPacket(ProtocolInfo::SET_DIFFICULTY_PACKET, SetDifficultyPacket::class);
}
private function getPacket($buffer){

View File

@ -39,8 +39,8 @@ class AddPlayerPacket extends DataPacket{
public $z;
public $pitch;
public $yaw;
public $unknown1;
public $unknown2;
public $item;
public $meta;
public $metadata;
public function pid(){
@ -61,8 +61,8 @@ class AddPlayerPacket extends DataPacket{
$this->putFloat($this->z);
$this->putByte((int) ($this->yaw * (256 / 360)));
$this->putByte((int) ($this->pitch * (256 / 360)));
$this->putShort($this->unknown1);
$this->putShort($this->unknown2);
$this->putShort($this->item);
$this->putShort($this->meta);
$this->put(Binary::writeMetadata($this->metadata));
}

View File

@ -30,7 +30,7 @@ interface Info{
/**
* Actual Minecraft: PE protocol version
*/
const CURRENT_PROTOCOL = 18;
const CURRENT_PROTOCOL = 20;
const LOGIN_PACKET = 0x82;
@ -88,5 +88,6 @@ interface Info{
//const PLAYER_INPUT_PACKET = 0xb9;
const FULL_CHUNK_DATA_PACKET = 0xba;
const UNLOAD_CHUNK_PACKET = 0xbb;
const SET_DIFFICULTY_PACKET = 0xbc;
}

View File

@ -0,0 +1,46 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\network\protocol;
#include <rules/DataPacket.h>
class SetDifficultyPacket extends DataPacket{
public static $pool = [];
public static $next = 0;
public $difficulty;
public function pid(){
return Info::SET_DIFFICULTY_PACKET;
}
public function decode(){
$this->difficulty = $this->getInt();
}
public function encode(){
$this->reset();
$this->putInt($this->difficulty);
}
}

View File

@ -50,7 +50,7 @@ class UseItemPacket extends DataPacket{
$this->x = $this->getInt();
$this->y = $this->getInt();
$this->z = $this->getInt();
$this->face = $this->getInt();
$this->face = $this->getByte();
$this->item = $this->getShort();
$this->meta = $this->getShort();
$this->eid = $this->getInt();

View File

@ -66,7 +66,7 @@ class PluginDescription{
$this->main = $plugin["main"];
$this->api = !is_array($plugin["api"]) ? [$plugin["api"]] : $plugin["api"];
if(stripos($this->main, "pocketmine\\") === 0){
trigger_error("Invalid PluginDescription main, cannot start within the PocketMine namespace", E_USER_ERROR);
throw new PluginException("Invalid PluginDescription main, cannot start within the PocketMine namespace");
return;
}
@ -97,9 +97,7 @@ class PluginDescription{
if(isset($plugin["load"])){
$order = strtoupper($plugin["load"]);
if(!defined(PluginLoadOrder::class . "::" . $order)){
trigger_error("Invalid PluginDescription load", E_USER_ERROR);
return;
throw new PluginException("Invalid PluginDescription load");
}else{
$this->order = constant(PluginLoadOrder::class . "::" . $order);
}

View File

@ -251,6 +251,9 @@ class PluginManager{
}
}catch(\Exception $e){
$this->server->getLogger()->error("Could not load '" . $file . "' in folder '" . $directory . "': " . $e->getMessage());
if(($logger = $this->server->getLogger()) instanceof MainLogger){
$logger->logException($e);
}
}
}
}
@ -666,6 +669,9 @@ class PluginManager{
$registration->callEvent($event);
}catch(\Exception $e){
$this->server->getLogger()->critical("Could not pass event ". $event->getEventName() ." to ". $registration->getPlugin()->getDescription()->getFullName() .": ".$e->getMessage()." on ".get_class($registration->getListener()));
if(($logger = $this->server->getLogger()) instanceof MainLogger){
$logger->logException($e);
}
}
}
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\scheduler;
use pocketmine\plugin\Plugin;
use pocketmine\Server;
use pocketmine\utils\MainLogger;
use pocketmine\utils\PluginException;
use pocketmine\utils\ReversePriorityQueue;
@ -236,6 +237,9 @@ class ServerScheduler{
$task->run($this->currentTick);
}catch (\Exception $e){
Server::getInstance()->getLogger()->critical("Could not execute task ". $task->getTaskName() .": ".$e->getMessage());
if(($logger = Server::getInstance()->getLogger()) instanceof MainLogger){
$logger->logException($e);
}
}
$task->timings->stopTiming();
}

View File

@ -59,11 +59,11 @@ class Chest extends Spawnable implements InventoryHolder, Container{
public function close(){
if($this->closed === false){
foreach($this->getInventory()->getViewers() as $player){
$this->getInventory()->close($player);
$player->removeWindow($this->getInventory());
}
foreach($this->getRealInventory()->getViewers() as $player){
$this->getRealInventory()->close($player);
foreach($this->getInventory()->getViewers() as $player){
$player->removeWindow($this->getRealInventory());
}
parent::close();
}

View File

@ -71,7 +71,7 @@ class Furnace extends Tile implements InventoryHolder, Container{
public function close(){
if($this->closed === false){
foreach($this->getInventory()->getViewers() as $player){
$this->getInventory()->close($player);
$player->removeWindow($this->getInventory());
}
parent::close();
}

View File

@ -71,11 +71,11 @@ class Sign extends Spawnable{
public function getSpawnCompound(){
return new Compound("", [
new String("Text1", $this->namedtag["Text1"]),
new String("Text2", $this->namedtag["Text2"]),
new String("Text3", $this->namedtag["Text3"]),
new String("Text4", $this->namedtag["Text4"]),
new String("id", Tile::SIGN),
$this->namedtag->Text1,
$this->namedtag->Text2,
$this->namedtag->Text3,
$this->namedtag->Text4,
new Int("x", (int) $this->x),
new Int("y", (int) $this->y),
new Int("z", (int) $this->z)

View File

@ -53,16 +53,18 @@ class InstallerLang{
$this->lang = $lang;
$this->langfile = \pocketmine\PATH . "src/pocketmine/lang/Installer/" . $lang . ".ini";
}else{
$l = glob(\pocketmine\PATH . "src/pocketmine/lang/Installer/" . $lang . "_*.ini");
if(count($l) > 0){
$files = [];
foreach($l as $file){
$files[$file] = filesize($file);
$files = [];
foreach(new \DirectoryIterator(\pocketmine\PATH . "src/pocketmine/lang/Installer/") as $file){
if($file->getExtension() === "ini"){
$files[$file->getFilename()] = $file->getSize();
}
}
if(count($files) > 0){
arsort($files);
reset($files);
$l = key($files);
$l = substr($l, strrpos($l, "/") + 1, -4);
$l = substr($l, 0, -4);
$this->lang = isset(self::$languages[$l]) ? $l : $lang;
$this->langfile = \pocketmine\PATH . "src/pocketmine/lang/Installer/" . $l . ".ini";
}else{

View File

@ -19,12 +19,12 @@ if exist PocketMine-MP.phar (
)
)
#if exist bin\php\php_wxwidgets.dll (
# %PHP_BINARY% %POCKETMINE_FILE% --enable-gui %*
#) else (
REM if exist bin\php\php_wxwidgets.dll (
REM %PHP_BINARY% %POCKETMINE_FILE% --enable-gui %*
REM ) else (
if exist bin\mintty.exe (
start "" bin\mintty.exe -o Columns=88 -o Rows=32 -o AllowBlinking=0 -o FontQuality=3 -o Font="DejaVu Sans Mono" -o FontHeight=10 -o CursorType=0 -o CursorBlinks=1 -h error -t "PocketMine-MP" -i bin/pocketmine.ico -w max %PHP_BINARY% %POCKETMINE_FILE% --enable-ansi %*
) else (
%PHP_BINARY% -c bin\php %POCKETMINE_FILE% %*
)
#)
REM )