mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-12 12:25:09 +00:00
Compare commits
16 Commits
Alpha_1.4d
...
Alpha_1.4d
Author | SHA1 | Date | |
---|---|---|---|
e44ed4da3b | |||
a72488d41e | |||
3930f379cf | |||
66ba327e62 | |||
329ca62465 | |||
26e47ef694 | |||
61ea149ff0 | |||
b3c3f896a3 | |||
d139e5f342 | |||
3abf36ad07 | |||
0bc9a9bdab | |||
98340522d9 | |||
6d09754ea7 | |||
a3b1d318cc | |||
f866efb622 | |||
b1c4578726 |
@ -1098,7 +1098,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$dz = $this->newPosition->z - $this->z;
|
||||
|
||||
//$this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
|
||||
$revert = !$this->move($dx, $dy, $dz);
|
||||
$this->move($dx, $dy, $dz);
|
||||
|
||||
$diffX = $this->x - $this->newPosition->x;
|
||||
$diffZ = $this->z - $this->newPosition->z;
|
||||
@ -1130,6 +1130,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$deltaAngle = abs($this->lastYaw - $to->yaw) + abs($this->lastPitch - $to->pitch);
|
||||
|
||||
if(!$revert and ($delta > (1 / 16) or $deltaAngle > 10)){
|
||||
|
||||
$isFirst = ($this->lastX === null or $this->lastY === null or $this->lastZ === null);
|
||||
|
||||
$this->lastX = $to->x;
|
||||
$this->lastY = $to->y;
|
||||
$this->lastZ = $to->z;
|
||||
@ -1137,29 +1140,39 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->lastYaw = $to->yaw;
|
||||
$this->lastPitch = $to->pitch;
|
||||
|
||||
$ev = new PlayerMoveEvent($this, $from, $to);
|
||||
if(!$isFirst){
|
||||
$ev = new PlayerMoveEvent($this, $from, $to);
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
|
||||
if(!($revert = $ev->isCancelled())){ //Yes, this is intended
|
||||
if($to->distance($ev->getTo()) > 0.1){ //If plugins modify the destination
|
||||
$this->teleport($ev->getTo());
|
||||
}else{
|
||||
$pk = new MovePlayerPacket();
|
||||
$pk->eid = $this->id;
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
$pk->z = $this->z;
|
||||
$pk->yaw = $this->yaw;
|
||||
$pk->pitch = $this->pitch;
|
||||
$pk->bodyYaw = $this->yaw;
|
||||
if(!($revert = $ev->isCancelled())){ //Yes, this is intended
|
||||
if($to->distance($ev->getTo()) > 0.1){ //If plugins modify the destination
|
||||
$this->teleport($ev->getTo());
|
||||
}else{
|
||||
$pk = new MovePlayerPacket();
|
||||
$pk->eid = $this->id;
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
$pk->z = $this->z;
|
||||
$pk->yaw = $this->yaw;
|
||||
$pk->pitch = $this->pitch;
|
||||
$pk->bodyYaw = $this->yaw;
|
||||
|
||||
Server::broadcastPacket($this->hasSpawned, $pk);
|
||||
Server::broadcastPacket($this->hasSpawned, $pk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($revert){
|
||||
|
||||
$this->lastX = $from->x;
|
||||
$this->lastY = $from->y;
|
||||
$this->lastZ = $from->z;
|
||||
|
||||
$this->lastYaw = $from->yaw;
|
||||
$this->lastPitch = $from->pitch;
|
||||
|
||||
$pk = new MovePlayerPacket();
|
||||
$pk->eid = 0;
|
||||
$pk->x = $from->x;
|
||||
@ -1628,10 +1641,13 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->inventory->sendHeldItem($this);
|
||||
}else{
|
||||
$item = $this->inventory->getItemInHand();
|
||||
$oldItem = clone $item;
|
||||
//TODO: Implement adventure mode checks
|
||||
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){
|
||||
$this->inventory->setItemInHand($item, $this);
|
||||
$this->inventory->sendHeldItem($this->hasSpawned);
|
||||
if(!$item->equals($oldItem, true) or $item->getCount() !== $oldItem->getCount()){
|
||||
$this->inventory->setItemInHand($item, $this);
|
||||
$this->inventory->sendHeldItem($this->hasSpawned);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1802,13 +1818,17 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
if($this->isCreative()){
|
||||
$item = $this->inventory->getItemInHand();
|
||||
}else{
|
||||
$item = clone $this->inventory->getItemInHand();
|
||||
$item = $this->inventory->getItemInHand();
|
||||
}
|
||||
|
||||
$oldItem = clone $item;
|
||||
|
||||
if($this->level->useBreakOn($vector, $item, $this) === true){
|
||||
if($this->isSurvival()){
|
||||
$this->inventory->setItemInHand($item, $this);
|
||||
$this->inventory->sendHeldItem($this->hasSpawned);
|
||||
if(!$item->equals($oldItem, true) or $item->getCount() !== $oldItem->getCount()){
|
||||
$this->inventory->setItemInHand($item, $this);
|
||||
$this->inventory->sendHeldItem($this->hasSpawned);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ namespace pocketmine {
|
||||
use pocketmine\wizard\Installer;
|
||||
|
||||
const VERSION = "Alpha_1.4dev";
|
||||
const API_VERSION = "1.7.1";
|
||||
const API_VERSION = "1.8.0";
|
||||
const CODENAME = "絶好(Zekkou)ケーキ(Cake)";
|
||||
const MINECRAFT_VERSION = "v0.10.4 alpha";
|
||||
|
||||
@ -367,8 +367,8 @@ namespace pocketmine {
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "2.0.8") < 0){
|
||||
$logger->critical("pthreads >= 2.0.8 is required, while you have $pthreads_version.");
|
||||
if(version_compare($pthreads_version, "2.0.9") < 0){
|
||||
$logger->critical("pthreads >= 2.0.9 is required, while you have $pthreads_version.");
|
||||
++$errors;
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,7 @@ class Server{
|
||||
* @return int
|
||||
*/
|
||||
public function getViewDistance(){
|
||||
return max(56, $this->getProperty("chunk-sending.max-chunks"));
|
||||
return max(56, $this->getProperty("chunk-sending.max-chunks", 96));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,7 +313,7 @@ class Server{
|
||||
* @return string
|
||||
*/
|
||||
public function getServerName(){
|
||||
return $this->getConfigString("motd", "Unknown server");
|
||||
return $this->getConfigString("motd", "Minecraft: PE Server");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1615,14 +1615,7 @@ class Server{
|
||||
Generator::addGenerator(Normal::class, "normal");
|
||||
Generator::addGenerator(Normal::class, "default");
|
||||
|
||||
//Temporal workaround, pthreads static property nullification test
|
||||
if(PluginManager::$pluginParentTimer === null or Timings::$serverTickTimer === null){
|
||||
$this->getLogger()->emergency("You are using an invalid pthreads version. Please update your binaries.");
|
||||
kill(getmypid());
|
||||
return;
|
||||
}
|
||||
|
||||
foreach($this->getProperty("worlds", []) as $name => $worldSetting){
|
||||
foreach((array) $this->getProperty("worlds", []) as $name => $worldSetting){
|
||||
if($this->loadLevel($name) === false){
|
||||
$seed = $this->getProperty("worlds.$name.seed", time());
|
||||
$options = explode(":", $this->getProperty("worlds.$name.generator", Generator::getGenerator("default")));
|
||||
|
@ -528,6 +528,14 @@ class Block extends Position implements Metadatable{
|
||||
|
||||
/** @var \SplFixedArray */
|
||||
public static $list = null;
|
||||
/** @var \SplFixedArray */
|
||||
public static $light = null;
|
||||
/** @var \SplFixedArray */
|
||||
public static $lightFilter = null;
|
||||
/** @var \SplFixedArray */
|
||||
public static $solid = null;
|
||||
/** @var \SplFixedArray */
|
||||
public static $transparent = null;
|
||||
protected $id;
|
||||
protected $meta;
|
||||
protected $name = "Unknown";
|
||||
@ -542,8 +550,8 @@ class Block extends Position implements Metadatable{
|
||||
public $isReplaceable = false;
|
||||
public $isPlaceable = true;
|
||||
public $hasPhysics = false;
|
||||
public $isLiquid = false;
|
||||
public $isFullBlock = true;
|
||||
public $lightLevel = 0;
|
||||
public $x = 0;
|
||||
public $y = 0;
|
||||
public $z = 0;
|
||||
@ -555,6 +563,10 @@ class Block extends Position implements Metadatable{
|
||||
public static function init(){
|
||||
if(self::$list === null){
|
||||
self::$list = new \SplFixedArray(256);
|
||||
self::$light = new \SplFixedArray(256);
|
||||
self::$lightFilter = new \SplFixedArray(256);
|
||||
self::$solid = new \SplFixedArray(256);
|
||||
self::$transparent = new \SplFixedArray(256);
|
||||
self::$list[self::AIR] = Air::class;;
|
||||
self::$list[self::STONE] = Stone::class;;
|
||||
self::$list[self::GRASS] = Grass::class;;
|
||||
@ -697,11 +709,37 @@ class Block extends Position implements Metadatable{
|
||||
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;;
|
||||
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;
|
||||
|
||||
foreach(self::$list as $id => $class){
|
||||
if($class !== null){
|
||||
/** @var Block $block */
|
||||
$block = new $class();
|
||||
self::$solid[$id] = (bool) $block->isSolid;
|
||||
self::$transparent[$id] = (bool) $block->isTransparent;
|
||||
self::$light[$id] = (int) $block->lightLevel;
|
||||
|
||||
if($block->isSolid){
|
||||
if($block->isTransparent){
|
||||
if($block instanceof Liquid or $block instanceof Ice){
|
||||
self::$lightFilter[$id] = 2;
|
||||
}else{
|
||||
self::$lightFilter[$id] = 1;
|
||||
}
|
||||
}else{
|
||||
self::$lightFilter[$id] = 15;
|
||||
}
|
||||
}else{
|
||||
self::$lightFilter[$id] = 1;
|
||||
}
|
||||
}else{
|
||||
self::$lightFilter[$id] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,9 @@ use pocketmine\level\Level;
|
||||
use pocketmine\Player;
|
||||
|
||||
class BrownMushroom extends Flowable{
|
||||
|
||||
public $lightLevel = 1;
|
||||
|
||||
public function __construct(){
|
||||
parent::__construct(self::BROWN_MUSHROOM, 0, "Brown Mushroom");
|
||||
$this->hardness = 0;
|
||||
|
@ -32,6 +32,9 @@ use pocketmine\tile\Furnace;
|
||||
use pocketmine\tile\Tile;
|
||||
|
||||
class BurningFurnace extends Solid{
|
||||
|
||||
public $lightLevel = 13;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::BURNING_FURNACE, $meta, "Burning Furnace");
|
||||
$this->isActivable = true;
|
||||
|
@ -24,6 +24,9 @@ namespace pocketmine\block;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
class EndPortal extends Solid{
|
||||
|
||||
public $lightLevel = 1;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::END_PORTAL, $meta, "End Portal");
|
||||
$this->hardness = 18000000;
|
||||
|
@ -32,6 +32,7 @@ use pocketmine\Server;
|
||||
class Fire extends Flowable{
|
||||
|
||||
public $hasEntityCollision = true;
|
||||
public $lightLevel = 15;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::FIRE, $meta, "Fire");
|
||||
|
@ -23,6 +23,9 @@ namespace pocketmine\block;
|
||||
|
||||
|
||||
class GlowingObsidian extends Solid{
|
||||
|
||||
public $lightLevel = 12;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::GLOWING_OBSIDIAN, $meta, "Glowing Obsidian");
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
|
||||
class GlowingRedstoneOre extends Solid{
|
||||
|
||||
public $lightLevel = 9;
|
||||
|
||||
public function __construct(){
|
||||
parent::__construct(self::GLOWING_REDSTONE_ORE, 0, "Glowing Redstone Ore");
|
||||
$this->hardness = 15;
|
||||
|
@ -24,6 +24,9 @@ namespace pocketmine\block;
|
||||
use pocketmine\item\Item;
|
||||
|
||||
class Glowstone extends Transparent{
|
||||
|
||||
public $lightLevel = 15;
|
||||
|
||||
public function __construct(){
|
||||
parent::__construct(self::GLOWSTONE_BLOCK, 0, "Glowstone");
|
||||
$this->hardness = 1.5;
|
||||
|
@ -31,6 +31,8 @@ use pocketmine\Server;
|
||||
|
||||
class Lava extends Liquid{
|
||||
|
||||
public $lightLevel = 15;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::LAVA, $meta, "Lava");
|
||||
$this->hardness = 0;
|
||||
|
@ -30,7 +30,6 @@ use pocketmine\math\Vector3;
|
||||
abstract class Liquid extends Transparent{
|
||||
public $hasEntityCollision = true;
|
||||
|
||||
public $isLiquid = true;
|
||||
public $breakable = false;
|
||||
public $isReplaceable = true;
|
||||
public $isSolid = false;
|
||||
|
@ -25,6 +25,9 @@ use pocketmine\item\Item;
|
||||
use pocketmine\Player;
|
||||
|
||||
class LitPumpkin extends Solid{
|
||||
|
||||
public $lightLevel = 15;
|
||||
|
||||
public function __construct(){
|
||||
parent::__construct(self::LIT_PUMPKIN, "Jack o'Lantern");
|
||||
$this->hardness = 5;
|
||||
|
@ -26,6 +26,9 @@ use pocketmine\level\Level;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Torch extends Flowable{
|
||||
|
||||
public $lightLevel = 15;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::TORCH, $meta, "Torch");
|
||||
$this->hardness = 0;
|
||||
|
@ -90,9 +90,9 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
protected $lastDamageCause = null;
|
||||
|
||||
public $lastX;
|
||||
public $lastY;
|
||||
public $lastZ;
|
||||
public $lastX = null;
|
||||
public $lastY = null;
|
||||
public $lastZ = null;
|
||||
|
||||
public $motionX;
|
||||
public $motionY;
|
||||
|
@ -85,10 +85,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
foreach($this->inventory->getContents() as $item){
|
||||
$drops[] = $item;
|
||||
}
|
||||
|
||||
foreach($this->inventory->getArmorContents() as $item){
|
||||
$drops[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $drops;
|
||||
@ -208,13 +204,10 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
public function close(){
|
||||
if(!$this->closed){
|
||||
if(!($this instanceof Player) or $this->loggedIn){
|
||||
foreach($this->getInventory()->getViewers() as $player){
|
||||
$this->getInventory()->close($player);
|
||||
foreach($this->inventory->getViewers() as $viewer){
|
||||
$viewer->removeWindow($this->inventory);
|
||||
}
|
||||
}
|
||||
foreach($this->inventory->getViewers() as $viewer){
|
||||
$viewer->removeWindow($this->inventory);
|
||||
}
|
||||
parent::close();
|
||||
}
|
||||
}
|
||||
|
@ -233,41 +233,59 @@ abstract class BaseInventory implements Inventory{
|
||||
$source = null;
|
||||
}
|
||||
|
||||
/** @var Item[] $itemSlots */
|
||||
/** @var Item[] $slots */
|
||||
foreach($slots as $i => $slot){
|
||||
$slots[$i] = clone $slot;
|
||||
$itemSlots = [];
|
||||
foreach($slots as $slot){
|
||||
if($slot->getId() !== 0 and $slot->getCount() > 0){
|
||||
$itemSlots[] = clone $slot;
|
||||
}
|
||||
}
|
||||
|
||||
$emptySlots = [];
|
||||
|
||||
for($i = 0; $i < $this->getSize(); ++$i){
|
||||
$item = $this->getItem($i);
|
||||
foreach($slots as $index => $slot){
|
||||
if($item->getID() === Item::AIR or $item->getCount() <= 0){
|
||||
$amount = min($slot->getMaxStackSize(), $slot->getCount(), $this->getMaxStackSize());
|
||||
$slot->setCount($slot->getCount() - $amount);
|
||||
$item = clone $slot;
|
||||
$item->setCount($amount);
|
||||
$this->setItem($i, $item, $source);
|
||||
$item = $this->getItem($i);
|
||||
if($slot->getCount() <= 0){
|
||||
unset($slots[$index]);
|
||||
}
|
||||
}elseif($slot->equals($item, true) and $item->getCount() < $item->getMaxStackSize()){
|
||||
if($item->getId() === Item::AIR or $item->getCount() <= 0){
|
||||
$emptySlots[] = $i;
|
||||
}
|
||||
|
||||
foreach($itemSlots as $index => $slot){
|
||||
if($slot->equals($item, true) and $item->getCount() < $item->getMaxStackSize()){
|
||||
$amount = min($item->getMaxStackSize() - $item->getCount(), $slot->getCount(), $this->getMaxStackSize());
|
||||
$slot->setCount($slot->getCount() - $amount);
|
||||
$item->setCount($item->getCount() + $amount);
|
||||
$this->setItem($i, $item, $source);
|
||||
if($slot->getCount() <= 0){
|
||||
unset($slots[$index]);
|
||||
if($amount > 0){
|
||||
$slot->setCount($slot->getCount() - $amount);
|
||||
$item->setCount($item->getCount() + $amount);
|
||||
$this->setItem($i, $item, $source);
|
||||
if($slot->getCount() <= 0){
|
||||
unset($itemSlots[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(count($slots) === 0){
|
||||
if(count($itemSlots) === 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $slots;
|
||||
if(count($itemSlots) > 0 and count($emptySlots) > 0){
|
||||
foreach($emptySlots as $slotIndex){
|
||||
foreach($itemSlots as $index => $slot){
|
||||
$amount = min($slot->getMaxStackSize(), $slot->getCount(), $this->getMaxStackSize());
|
||||
$slot->setCount($slot->getCount() - $amount);
|
||||
$item = clone $slot;
|
||||
$item->setCount($amount);
|
||||
$this->setItem($slotIndex, $item, $source);
|
||||
if($slot->getCount() <= 0){
|
||||
unset($itemSlots[$index]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $itemSlots;
|
||||
}
|
||||
|
||||
public function removeItem(...$slots){
|
||||
@ -279,31 +297,39 @@ abstract class BaseInventory implements Inventory{
|
||||
$source = null;
|
||||
}
|
||||
|
||||
/** @var Item[] $itemSlots */
|
||||
/** @var Item[] $slots */
|
||||
$itemSlots = [];
|
||||
foreach($slots as $slot){
|
||||
if($slot->getId() !== 0 and $slot->getCount() > 0){
|
||||
$itemSlots[] = clone $slot;
|
||||
}
|
||||
}
|
||||
|
||||
for($i = 0; $i < $this->getSize(); ++$i){
|
||||
$item = $this->getItem($i);
|
||||
if($item->getID() === Item::AIR){
|
||||
if($item->getId() === Item::AIR or $item->getCount() <= 0){
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach($slots as $index => $slot){
|
||||
foreach($itemSlots as $index => $slot){
|
||||
if($slot->equals($item, $slot->getDamage() === null ? false : true)){
|
||||
$amount = min($item->getCount(), $slot->getCount());
|
||||
$slot->setCount($slot->getCount() - $amount);
|
||||
$item->setCount($item->getCount() - $amount);
|
||||
$this->setItem($i, $item, $source);
|
||||
if($slot->getCount() <= 0){
|
||||
unset($slots[$index]);
|
||||
unset($itemSlots[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(count($slots) === 0){
|
||||
if(count($itemSlots) === 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $slots;
|
||||
return $itemSlots;
|
||||
}
|
||||
|
||||
public function clear($index, $source = null){
|
||||
|
@ -85,7 +85,7 @@ class CraftingManager{
|
||||
$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)));
|
||||
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::LADDER, 0, 2)))->addIngredient(Item::get(Item::STICK, 0, 7)));
|
||||
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::NETHER_REACTOR, 0, 1)))->addIngredient(Item::get(Item::DIAMOND, 0, 3))->addIngredient(Item::get(Item::IRON_INGOT, 0, 6)));
|
||||
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::TRAPDOOR, 0, 2)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 6)));
|
||||
$this->registerRecipe((new BigShapelessRecipe(Item::get(Item::WOODEN_DOOR, 0, 1)))->addIngredient(Item::get(Item::WOODEN_PLANK, null, 6)));
|
||||
|
@ -625,7 +625,7 @@ class Item{
|
||||
}
|
||||
|
||||
final public function __toString(){
|
||||
return "Item " . $this->name . " (" . $this->id . ":" . ($this->meta === null ? "?" : $this->meta) . ")";
|
||||
return "Item " . $this->name . " (" . $this->id . ":" . ($this->meta === null ? "?" : $this->meta) . ")x".$this->count;
|
||||
}
|
||||
|
||||
public function getDestroySpeed(Block $block, Player $player){
|
||||
|
@ -514,7 +514,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
if(($mini & (1 << $Y)) === 0){
|
||||
continue;
|
||||
}
|
||||
if(count($this->changedBlocks[$index][$Y]) < 582){ //Optimal value, calculated using the relation between minichunks and single packets
|
||||
if(count($this->changedBlocks[$index][$Y]) < 256){
|
||||
continue;
|
||||
}else{
|
||||
$X = null;
|
||||
@ -574,13 +574,13 @@ class Level implements ChunkManager, Metadatable{
|
||||
$x = $player->x >> 4;
|
||||
$z = $player->z >> 4;
|
||||
|
||||
$index = "$x:$z";
|
||||
$index = Level::chunkHash($x, $z);
|
||||
$existingPlayers = max(0, isset($this->chunkTickList[$index]) ? $this->chunkTickList[$index] : 0);
|
||||
$this->chunkTickList[$index] = $existingPlayers + 1;
|
||||
for($chunk = 0; $chunk < $chunksPerPlayer; ++$chunk){
|
||||
$dx = mt_rand(-$randRange, $randRange);
|
||||
$dz = mt_rand(-$randRange, $randRange);
|
||||
$hash = ($dx + $x) .":". ($dz + $z);
|
||||
$hash = Level::chunkHash($dx + $x, $dz + $z);
|
||||
if(!isset($this->chunkTickList[$hash]) and $this->isChunkLoaded($dx + $x, $dz + $z)){
|
||||
$this->chunkTickList[$hash] = -1;
|
||||
}
|
||||
@ -881,6 +881,20 @@ class Level implements ChunkManager, Metadatable{
|
||||
}
|
||||
*/
|
||||
|
||||
public function getFullLight(Vector3 $pos){
|
||||
$chunk = $this->getChunk($pos->x >> 4, $pos->z >> 4, true);
|
||||
$level = 0;
|
||||
if($chunk instanceof FullChunk){
|
||||
$level = $chunk->getBlockSkyLight($pos->x & 0x0f, $pos->y & 0x7f, $pos->z & 0x0f);
|
||||
//TODO: decrease light level by time of day
|
||||
if($level < 15){
|
||||
$level = max($chunk->getBlockLight($pos->x & 0x0f, $pos->y & 0x7f, $pos->z & 0x0f));
|
||||
}
|
||||
}
|
||||
|
||||
return $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Block object on the Vector3 location
|
||||
*
|
||||
@ -911,6 +925,102 @@ class Level implements ChunkManager, Metadatable{
|
||||
return $this->blockCache[$index] = Block::get($blockId, $meta, $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z));
|
||||
}
|
||||
|
||||
public function updateAllLight(Vector3 $pos){
|
||||
$this->updateBlockSkyLight($pos->x, $pos->y, $pos->z);
|
||||
$this->updateBlockLight($pos->x, $pos->y, $pos->z);
|
||||
}
|
||||
|
||||
public function updateBlockSkyLight($x, $y, $z){
|
||||
//TODO
|
||||
}
|
||||
|
||||
public function updateBlockLight($x, $y, $z){
|
||||
$lightPropagationQueue = new \SplQueue();
|
||||
$lightRemovalQueue = new \SplQueue();
|
||||
$visited = [];
|
||||
$removalVisited = [];
|
||||
|
||||
$oldLevel = $this->getBlockLightAt($x, $y, $z);
|
||||
$newLevel = (int) Block::$light[$this->getBlockIdAt($x, $y, $z)];
|
||||
|
||||
if($oldLevel !== $newLevel){
|
||||
$this->setBlockLightAt($x, $y, $z, $newLevel);
|
||||
|
||||
if($newLevel < $oldLevel){
|
||||
$removalVisited["$x:$y:$z"] = true;
|
||||
$lightRemovalQueue->enqueue([new Vector3($x, $y, $z), $oldLevel]);
|
||||
}else{
|
||||
$visited["$x:$y:$z"] = true;
|
||||
$lightPropagationQueue->enqueue(new Vector3($x, $y, $z));
|
||||
}
|
||||
}
|
||||
|
||||
while(!$lightRemovalQueue->isEmpty()){
|
||||
/** @var Vector3 $node */
|
||||
$val = $lightRemovalQueue->dequeue();
|
||||
$node = $val[0];
|
||||
$lightLevel = $val[1];
|
||||
|
||||
$this->computeRemoveBlockLight($node->x - 1, $node->y, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
|
||||
$this->computeRemoveBlockLight($node->x + 1, $node->y, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
|
||||
$this->computeRemoveBlockLight($node->x, $node->y - 1, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
|
||||
$this->computeRemoveBlockLight($node->x, $node->y + 1, $node->z, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
|
||||
$this->computeRemoveBlockLight($node->x, $node->y, $node->z - 1, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
|
||||
$this->computeRemoveBlockLight($node->x, $node->y, $node->z + 1, $lightLevel, $lightRemovalQueue, $lightPropagationQueue, $removalVisited, $visited);
|
||||
}
|
||||
|
||||
while(!$lightPropagationQueue->isEmpty()){
|
||||
/** @var Vector3 $node */
|
||||
$node = $lightPropagationQueue->dequeue();
|
||||
|
||||
$lightLevel = $this->getBlockLightAt($node->x, $node->y, $node->z) - (int) Block::$lightFilter[$this->getBlockIdAt($node->x, $node->y, $node->z)];
|
||||
|
||||
if($lightLevel >= 1){
|
||||
$this->computeSpreadBlockLight($node->x - 1, $node->y, $node->z, $lightLevel, $lightPropagationQueue, $visited);
|
||||
$this->computeSpreadBlockLight($node->x + 1, $node->y, $node->z, $lightLevel, $lightPropagationQueue, $visited);
|
||||
$this->computeSpreadBlockLight($node->x, $node->y - 1, $node->z, $lightLevel, $lightPropagationQueue, $visited);
|
||||
$this->computeSpreadBlockLight($node->x, $node->y + 1, $node->z, $lightLevel, $lightPropagationQueue, $visited);
|
||||
$this->computeSpreadBlockLight($node->x, $node->y, $node->z - 1, $lightLevel, $lightPropagationQueue, $visited);
|
||||
$this->computeSpreadBlockLight($node->x, $node->y, $node->z + 1, $lightLevel, $lightPropagationQueue, $visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function computeRemoveBlockLight($x, $y, $z, $currentLight, \SplQueue $queue, \SplQueue $spreadQueue, array &$visited, array &$spreadVisited){
|
||||
$current = $this->getBlockLightAt($x, $y, $z);
|
||||
|
||||
if($current !== 0 and $current < $currentLight){
|
||||
$this->setBlockLightAt($x, $y, $z, 0);
|
||||
|
||||
if(!isset($visited[$index = "$x:$y:$z"])){
|
||||
$visited[$index] = true;
|
||||
if($current > 1){
|
||||
$queue->enqueue([new Vector3($x, $y, $z), $current]);
|
||||
}
|
||||
}
|
||||
}elseif($current >= $currentLight){
|
||||
if(!isset($spreadVisited[$index = "$x:$y:$z"])){
|
||||
$spreadVisited[$index] = true;
|
||||
$spreadQueue->enqueue(new Vector3($x, $y, $z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function computeSpreadBlockLight($x, $y, $z, $currentLight, \SplQueue $queue, array &$visited){
|
||||
$current = $this->getBlockLightAt($x, $y, $z);
|
||||
|
||||
if($current < $currentLight){
|
||||
$this->setBlockLightAt($x, $y, $z, $currentLight);
|
||||
|
||||
if(!isset($visited[$index = "$x:$y:$z"])){
|
||||
$visited[$index] = true;
|
||||
if($currentLight > 1){
|
||||
$queue->enqueue(new Vector3($x, $y, $z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets on Vector3 the data from a Block object,
|
||||
* does block updates and puts the changes to the send queue.
|
||||
@ -946,7 +1056,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
Cache::remove("world:" . $this->getID() . ":" . $index);
|
||||
}
|
||||
|
||||
//if($direct === true){
|
||||
if($direct === true){
|
||||
$pk = new UpdateBlockPacket();
|
||||
$pk->x = $pos->x;
|
||||
$pk->y = $pos->y;
|
||||
@ -955,7 +1065,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
$pk->meta = $block->getDamage();
|
||||
|
||||
Server::broadcastPacket($this->getUsingChunk($pos->x >> 4, $pos->z >> 4), $pk);
|
||||
/*}else{
|
||||
}else{
|
||||
if(!($pos instanceof Position)){
|
||||
$pos = $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z);
|
||||
}
|
||||
@ -970,9 +1080,11 @@ class Level implements ChunkManager, Metadatable{
|
||||
$this->changedCount[$index] |= 1 << $Y;
|
||||
}
|
||||
$this->changedBlocks[$index][$Y][] = clone $block;
|
||||
}*/
|
||||
}
|
||||
|
||||
if($update === true){
|
||||
$this->updateAllLight($block);
|
||||
|
||||
$this->updateAround($pos);
|
||||
$this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($block));
|
||||
if(!$ev->isCancelled()){
|
||||
@ -1091,8 +1203,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
$tile->unpair();
|
||||
}
|
||||
|
||||
foreach($tile->getInventory()->getContents() as $item){
|
||||
$this->dropItem($target, $item);
|
||||
foreach($tile->getInventory()->getContents() as $chestItem){
|
||||
$this->dropItem($target, $chestItem);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1552,7 +1664,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @return Chunk
|
||||
*/
|
||||
public function getChunk($x, $z, $create = false){
|
||||
if(isset($this->chunks[$index = "$x:$z"])){
|
||||
if(isset($this->chunks[$index = Level::chunkHash($x, $z)])){
|
||||
return $this->chunks[$index];
|
||||
}elseif($this->loadChunk($x, $z, $create) and $this->chunks[$index] instanceof FullChunk){
|
||||
return $this->chunks[$index];
|
||||
@ -1576,7 +1688,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
public function generateChunkCallback($x, $z, FullChunk $chunk){
|
||||
$oldChunk = $this->getChunk($x, $z);
|
||||
unset($this->chunkGenerationQueue["$x:$z"]);
|
||||
unset($this->chunkGenerationQueue[Level::chunkHash($x, $z)]);
|
||||
$this->setChunk($x, $z, $chunk);
|
||||
$chunk = $this->getChunk($x, $z);
|
||||
if($chunk instanceof FullChunk and (!($oldChunk instanceof FullChunk) or $oldChunk->isPopulated() === false) and $chunk->isPopulated()){
|
||||
@ -1597,7 +1709,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
$this->chunks[$index] = $chunk;
|
||||
}
|
||||
if(ADVANCED_CACHE == true){
|
||||
Cache::remove("world:" . $this->getID() . ":$x:$z");
|
||||
Cache::remove("world:" . $this->getID() . ":". Level::chunkHash($x, $z));
|
||||
}
|
||||
$chunk->setChanged();
|
||||
}
|
||||
@ -1625,7 +1737,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @return bool
|
||||
*/
|
||||
public function isChunkLoaded($x, $z){
|
||||
return isset($this->chunks["$x:$z"]) or $this->provider->isChunkLoaded($x, $z);
|
||||
return isset($this->chunks[Level::chunkHash($x, $z)]) or $this->provider->isChunkLoaded($x, $z);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2045,8 +2157,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
|
||||
public function generateChunk($x, $z){
|
||||
if(!isset($this->chunkGenerationQueue["$x:$z"])){
|
||||
$this->chunkGenerationQueue["$x:$z"] = true;
|
||||
if(!isset($this->chunkGenerationQueue[Level::chunkHash($x, $z)])){
|
||||
$this->chunkGenerationQueue[Level::chunkHash($x, $z)] = true;
|
||||
$this->server->getGenerationManager()->requestChunk($this, $x, $z);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user