Merge branch 'master' into Sugarcane

This commit is contained in:
PeratX 2016-04-10 08:06:52 +08:00
commit f0f2379670
50 changed files with 641 additions and 257 deletions

View file

@ -11,7 +11,8 @@ ANY ISSUE ON OUTDATED GENISYS WILL BE CLOSED. CONTINUING SPAMMNG WILL CAUSE A BA
#### OS and versions
<!--- Try Docker for library/extension issues
use the 'version' command in Genisys
Valid version must contain build number or git hash -->
Valid version must contain build number or git hash
Version "latest" is INVALID! Please write properly -->
* Genisys:
* PHP:
* OS:

2
.gitignore vendored
View file

@ -6,7 +6,7 @@ timings/*
*.log
*.phar
server.properties
pocketmine.yml
/pocketmine.yml
*.txt
genisys.yml
crashdumps/*

View file

@ -4,12 +4,12 @@ Chat on Gitter: [![Gitter](https://img.shields.io/gitter/room/iTXTech/Genisys.sv
You can also join #genisys on freenode IRC.
### Build status
Jenkins: [![Jenkins](https://img.shields.io/jenkins/s/http/jenkins.mcper.cn/Genisys-master.svg)](http://jenkins.mcper.cn/job/Genisys-master/)
Jenkins: [![Jenkins](https://img.shields.io/jenkins/s/http/jenkins.mcper.cn/Genisys-master.svg)](https://jenkins.mcper.cn/job/Genisys-master/)
Travis-CI: [![Travis-CI](https://img.shields.io/travis/iTXTech/Genisys/master.svg)](https://travis-ci.org/iTXTech/Genisys)
GitLab CI: [![GitLab CI](https://gitlab.com/itxtech/genisys/badges/master/build.svg)](https://gitlab.com/itxtech/genisys/builds)
### Downloads
You can get prebuilt phar from [Jenkins](http://jenkins.mcper.cn/job/Genisys-master/) or [GitLab](https://gitlab.com/itxtech/genisys/builds).
You can get prebuilt phar from [Jenkins](https://jenkins.mcper.cn/job/Genisys-master/) or [GitLab](https://gitlab.com/itxtech/genisys/builds).
### Fast Docker installation
[![Docker Pulls](https://img.shields.io/docker/pulls/itxtech/docker-env-genisys.svg)](https://hub.docker.com/r/itxtech/docker-env-genisys/)
@ -93,7 +93,6 @@ Most codes are made by PocketMine team and licensed under GPLv3. Some AI is prop
### To-Do List
* Improve Potions
* Improve Redstone
* Improve Anvil
* Fishing
* New AI for all creatures
* LevelDB support for Windows
@ -176,7 +175,6 @@ Port: 19132
### 计划表
* 完善 药水
* 完善 红石系统
* 完善 铁毡
* 加入 钓鱼
* 用于所有生物的新 AI
* Windows 的 LevelDB 支持

View file

@ -24,6 +24,7 @@ namespace pocketmine;
use pocketmine\block\Block;
use pocketmine\block\PressurePlate;
use pocketmine\command\CommandSender;
use pocketmine\entity\Animal;
use pocketmine\entity\Arrow;
use pocketmine\entity\Attribute;
use pocketmine\entity\Boat;
@ -37,6 +38,7 @@ use pocketmine\entity\Minecart;
use pocketmine\entity\Projectile;
use pocketmine\entity\ThrownExpBottle;
use pocketmine\entity\ThrownPotion;
use pocketmine\event\block\ItemFrameDropItemEvent;
use pocketmine\event\block\SignChangeEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
@ -167,7 +169,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
/** @var SourceInterface */
protected $interface;
/** @var bool */
/** @var bool */
public $playedBefore = false;
public $spawned = false;
public $loggedIn = false;
@ -280,6 +282,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
/** @var Level[] */
public $selectedLev = [];
/** @var Item[] */
private $personalCreativeItems = [];
public function linkHookToPlayer(FishingHook $entity){
if($entity->isAlive()){
$this->setFishingHook($entity);
@ -319,6 +324,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->fishingHook = $entity;
}
public function getItemInHand(){
return $this->inventory->getItemInHand();
}
public function getLeaveMessage(){
return new TranslationContainer(TextFormat::YELLOW . "%multiplayer.player.left", [
$this->getDisplayName()
@ -1344,9 +1353,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}else{
$pk = new ContainerSetContentPacket();
$pk->windowid = ContainerSetContentPacket::SPECIAL_CREATIVE;
foreach(Item::getCreativeItems() as $item){
$pk->slots[] = clone $item;
}
$pk->slots = array_merge(Item::getCreativeItems(), $this->personalCreativeItems);
$this->dataPacket($pk);
}
@ -1977,6 +1984,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
3 => 1
],
Item::POTION => 0,
Item::ROTTEN_FLESH => 4
];
$slot = $this->inventory->getItemInHand();
@ -2008,6 +2016,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->inventory->setItemInHand($slot);
if($slot->getId() === Item::MUSHROOM_STEW or $slot->getId() === Item::BEETROOT_SOUP){
$this->inventory->addItem(Item::get(Item::BOWL, 0, 1));
}elseif($slot->getId() === Item::ROTTEN_FLESH){
if(mt_rand(0, 100) < 80){
$this->addEffect(Effect::getEffect(Effect::HUNGER)->setAmplifier(0)->setDuration(30 * 20));
}
}elseif($slot->getId() === Item::RAW_FISH and $slot->getDamage() === 3){ //Pufferfish
$this->addEffect(Effect::getEffect(Effect::HUNGER)->setAmplifier(2)->setDuration(15 * 20));
$this->addEffect(Effect::getEffect(Effect::NAUSEA)->setAmplifier(1)->setDuration(15 * 20));
@ -2177,6 +2189,35 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->processLogin();
}
public function clearCreativeItems(){
$this->personalCreativeItems = [];
}
public function getCreativeItems() : array{
return $this->personalCreativeItems;
}
public function addCreativeItem(Item $item){
$this->personalCreativeItems[] = Item::get($item->getId(), $item->getDamage());
}
public function removeCreativeItem(Item $item){
$index = $this->getCreativeItemIndex($item);
if($index !== -1){
unset($this->personalCreativeItems[$index]);
}
}
public function getCreativeItemIndex(Item $item) : int{
foreach($this->personalCreativeItems as $i => $d){
if($item->equals($d, !$item->isTool())){
return $i;
}
}
return -1;
}
protected function processLogin(){
if(!$this->server->isWhitelisted(strtolower($this->getName()))){
$this->close($this->getLeaveMessage(), "Server is white-listed");
@ -2346,7 +2387,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}else{
$pk = new ContainerSetContentPacket();
$pk->windowid = ContainerSetContentPacket::SPECIAL_CREATIVE;
$pk->slots = Item::getCreativeItems();
$pk->slots = array_merge(Item::getCreativeItems(), $this->personalCreativeItems);
$this->dataPacket($pk);
}
$this->forceMovement = $this->teleportPosition = $this->getPosition();
@ -2390,13 +2431,17 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
case ProtocolInfo::ITEM_FRAME_DROP_ITEM_PACKET:
$tile = $this->level->getTile($this->temporalVector->setComponents($packet->x, $packet->y, $packet->z));
if($tile instanceof ItemFrame){
if($tile->getItem()->getId() !== Item::AIR){
if((mt_rand(0, 10) / 10) <= $tile->getItemDropChance()){
$this->level->dropItem($tile, $tile->getItem());
$item = $tile->getItem();
$this->server->getPluginManager()->callEvent($ev = new ItemFrameDropItemEvent($this->level->getBlock($tile), $tile, $item));
if(!$ev->isCancelled()){
if($item->getId() !== Item::AIR){
if((mt_rand(0, 10) / 10) < $tile->getItemDropChance()){
$this->level->dropItem($tile, $item);
}
$tile->setItem(Item::get(Item::AIR));
$tile->setItemRotation(0);
}
$tile->setItem(Item::get(Item::AIR));
$tile->setItemRotation(0);
}
}else $tile->spawnTo($this);
}
break;
case ProtocolInfo::REQUEST_CHUNK_RADIUS_PACKET:
@ -2420,12 +2465,11 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->iusername = strtolower($this->username);
$this->protocol = $packet->protocol1;
if(count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers()){
$this->close("", "disconnectionScreen.serverFull");
if(count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers() and $this->kick("disconnectionScreen.serverFull", false)){
break;
}
if($packet->protocol1 != ProtocolInfo::CURRENT_PROTOCOL){
if(!in_array($packet->protocol1, ProtocolInfo::ACCEPTED_PROTOCOLS)){
if($packet->protocol1 < ProtocolInfo::CURRENT_PROTOCOL){
$message = "disconnectionScreen.outdatedClient";
@ -2473,10 +2517,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
if((strlen($packet->skin) != 64 * 64 * 4) and (strlen($packet->skin) != 64 * 32 * 4)){
$this->close("", TextFormat::RED . "Please use 0.13.1 join the server!");
//$this->close("", "disconnectionScreen.invalidSkin");
$this->close("", "disconnectionScreen.invalidSkin");
break;
//$this->setSkin("", "Standard_Steve");
}
$this->setSkin($packet->skin, $packet->skinName);
@ -3125,21 +3168,23 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
if($target instanceof Boat or ($target instanceof Minecart and $target->getType() == Minecart::TYPE_NORMAL)){
if($packet->action === 1){
if($packet->action === InteractPacket::ACTION_RIGHT_CLICK){
$this->linkEntity($target);
}elseif($packet->action === 2){
}elseif($packet->action === InteractPacket::ACTION_LEFT_CLICK){
if($this->linkedEntity == $target){
$target->setLinked(0, $this);
}
$target->close();
}elseif($packet->action === 3){
}elseif($packet->action === InteractPacket::ACTION_LEAVE_VEHICLE){
$this->setLinked(0, $target);
}
return;
}
if($packet->action === InteractPacket::ACTION_RIGHT_CLICK){
// TODO handle
if($target instanceof Animal and $this->getInventory()->getItemInHand()){
//TODO: Feed
}
break;
}
@ -3282,20 +3327,30 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if($this->spawned === false or $this->blocked === true or !$this->isAlive()){
break;
}
if($this->isCreative() and $this->server->limitedCreative) break;
$dropItem = $packet;
$item = $this->inventory->contains($dropItem->item) ? $dropItem->item : $this->inventory->getItemInHand();
$ev = new PlayerDropItemEvent($this, $item);
$this->server->getPluginManager()->callEvent($ev);
if($ev->isCancelled()){
if(!$this->inventory->contains($packet->item) or ($this->isCreative() and $this->server->limitedCreative)){
$this->inventory->sendContents($this);
break;
}
$this->inventory->remove($item);
$slot = $this->inventory->first($packet->item);
if($slot == -1){
$this->inventory->sendContents($this);
break;
}
$dropItem = $this->inventory->getItem($slot);
$ev = new PlayerDropItemEvent($this, $dropItem);
$this->server->getPluginManager()->callEvent($ev);
if($ev->isCancelled()){
$this->inventory->sendSlot($slot, $this);
break;
}
$this->inventory->remove($dropItem);
//$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
$motion = $this->getDirectionVector()->multiply(0.4);
$this->level->dropItem($this->add(0, 1.3, 0), $item, $motion, 40);
$this->level->dropItem($this->add(0, 1.3, 0), $dropItem, $motion, 40);
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
break;

View file

@ -75,8 +75,8 @@ namespace pocketmine {
const VERSION = "1.1dev";
const API_VERSION = "2.0.0";
const CODENAME = "Ikaros";
const MINECRAFT_VERSION = "v0.14.0 alpha";
const MINECRAFT_VERSION_NETWORK = "0.14.0";
const MINECRAFT_VERSION = "v0.14.x alpha";
const MINECRAFT_VERSION_NETWORK = "0.14.1";
const GENISYS_API_VERSION = '1.7.2';
/*

View file

@ -1640,7 +1640,7 @@ class Server{
"creeperexplode" => $this->getAdvancedProperty("ai.creeper-explode-destroy-block", false),
"mobgenerate" => $this->getAdvancedProperty("ai.mobgenerate", false),
];
$this->inventoryNum = min(89, $this->getAdvancedProperty("player.inventory-num", 36));
$this->inventoryNum = min(91, $this->getAdvancedProperty("player.inventory-num", 36));
$this->hungerTimer = $this->getAdvancedProperty("player.hunger-timer", 80);
$this->allowSnowGolem = $this->getAdvancedProperty("server.allow-snow-golem", false);
$this->allowIronGolem = $this->getAdvancedProperty("server.allow-iron-golem", false);
@ -2396,8 +2396,10 @@ private function lookupAddress($address) {
/**
* Shutdowns the server correctly
* @param bool $restart
* @param string $msg
*/
public function shutdown(){
public function shutdown(bool $restart = false, string $msg = ""){
/*if($this->expEnabled){
foreach($this->getLevels() as $level){
foreach($level->getEntities() as $e){
@ -2411,6 +2413,9 @@ private function lookupAddress($address) {
$killer->kill();
}*/
$this->isRunning = false;
if($msg != ""){
$this->propertyCache["settings.shutdown-message"] = $msg;
}
}
public function forceShutdown(){

View file

@ -24,6 +24,7 @@ namespace pocketmine\block;
use pocketmine\inventory\AnvilInventory;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\level\sound\AnvilBreakSound;
use pocketmine\Player;
class Anvil extends Fallable{
@ -71,6 +72,12 @@ class Anvil extends Fallable{
return true;
}
public function onBreak(Item $item) {
parent::onBreak($item);
$sound = new AnvilBreakSound($this);
$this->getLevel()->addSound($sound);
}
public function getDrops(Item $item) : array {
if($item->isPickaxe() >= 1){
return [

View file

@ -31,18 +31,16 @@ use pocketmine\level\sound\ExplodeSound;
use pocketmine\level\sound\GraySplashSound;
use pocketmine\level\sound\SpellSound;
use pocketmine\level\sound\SplashSound;
use pocketmine\math\AxisAlignedBB;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\tile\Tile;
use pocketmine\tile\Cauldron as TileCauldron;
use pocketmine\tile\Tile;
use pocketmine\utils\Color;
class Cauldron extends Solid{
@ -80,14 +78,13 @@ class Cauldron extends Solid{
new ListTag("Items", [])
]);
$chunk = $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4);
$tile = Tile::createTile("Cauldron", $chunk, $nbt);
$tile = Tile::createTile("Cauldron", $chunk, $nbt);//
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
public function onBreak(Item $item){
$this->getLevel()->setBlock($this, new Air(), true, true);
$this->getLevel()->setBlock($this, new Air(), true);
return true;
}
@ -100,10 +97,9 @@ class Cauldron extends Solid{
return [];
}
public function badUpdate(){
//$this->getLevel()->setBlockDataAt($this->x, $this->y, $this->z, $this->meta + 1);
$this->getLevel()->setBlock($this, Block::get($this->id, $this->meta + 1), true, false);
$this->getLevel()->setBlock($this, $this, true, false);//TODO: improve
public function update(){//umm... right update method...?
$this->getLevel()->setBlock($this, Block::get($this->id, $this->meta + 1), true);
$this->getLevel()->setBlock($this, $this, true);//Undo the damage value
}
public function isEmpty(){
@ -116,14 +112,13 @@ class Cauldron extends Solid{
public function onActivate(Item $item, Player $player = null){//long...
$tile = $this->getLevel()->getTile($this);
if(!($tile instanceof TileCauldron) or !($player instanceof Player)){
if(!($tile instanceof TileCauldron)){
return false;
}
switch($item->getId()){
case Item::BUCKET:
if($item->getDamage() === 0){
if(!$this->isFull() and !$tile->isCustomColor() and !$tile->hasPotion()){
if($item->getDamage() === 0){//empty bucket
if(!$this->isFull() or $tile->isCustomColor() or $tile->hasPotion()){
break;
}
$bucket = clone $item;
@ -139,7 +134,9 @@ class Cauldron extends Solid{
$this->getLevel()->addSound(new SplashSound($this->add(0.5, 1, 0.5)));
}
}elseif($item->getDamage() === 8){//water bucket
if($this->isFull() and !$tile->isCustomColor() and !$tile->hasPotion()) break;
if($this->isFull() and !$tile->isCustomColor() and !$tile->hasPotion()){
break;
}
$bucket = clone $item;
$bucket->setDamage(0);//empty bucket
Server::getInstance()->getPluginManager()->callEvent($ev = new PlayerBucketEmptyEvent($player, $this, 0, $item, $bucket));
@ -147,7 +144,6 @@ class Cauldron extends Solid{
if($player->isSurvival()){
$player->getInventory()->setItemInHand($ev->getItem());
}
if($tile->hasPotion()){//if has potion
$this->meta = 0;//empty
$this->getLevel()->setBlock($this, $this, true);
@ -160,7 +156,7 @@ class Cauldron extends Solid{
$tile->clearCustomColor();
$this->getLevel()->addSound(new SplashSound($this->add(0.5, 1, 0.5)));
}
$this->badUpdate();//bad
$this->update();
}
}
break;
@ -170,10 +166,16 @@ class Cauldron extends Solid{
if($tile->isCustomColor()){
$color = Color::averageColor($color, $tile->getCustomColor());
}
if($player->isSurvival()){
$item->setCount($item->getCount() - 1);
/*if($item->getCount() <= 0){
$player->getInventory()->setItemInHand(Item::get(Item::AIR));
}*/
}
$tile->setCustomColor($color);
$this->getLevel()->addSound(new SplashSound($this->add(0.5, 1, 0.5)));
$this->badUpdate();//bad
$this->update();
break;
case Item::LEATHER_CAP:
case Item::LEATHER_TUNIC:
@ -183,26 +185,21 @@ class Cauldron extends Solid{
if($tile->isCustomColor()){
--$this->meta;
$this->getLevel()->setBlock($this, $this, true);
$newItem = clone $item;
/** @var $newItem Armor */
/** @var Armor $newItem */
$newItem->setCustomColor($tile->getCustomColor());
$player->getInventory()->setItemInHand($newItem);
$this->getLevel()->addSound(new SplashSound($this->add(0.5, 1, 0.5)));
if($this->isEmpty()){
$tile->clearCustomColor();
}
}else{
--$this->meta;
$this->getLevel()->setBlock($this, $this, true);
$newItem = clone $item;
/** @var $newItem Armor */
/** @var Armor $newItem */
$newItem->clearCustomColor();
$player->getInventory()->setItemInHand($newItem);
$this->getLevel()->addSound(new SplashSound($this->add(0.5, 1, 0.5)));
}
break;
@ -212,12 +209,11 @@ class Cauldron extends Solid{
($item->getId() === Item::POTION and $tile->getSplashPotion()) or
($item->getId() === Item::SPLASH_POTION and !$tile->getSplashPotion()) or
($item->getDamage() === Potion::WATER_BOTTLE and $tile->hasPotion()))
){//oh long...
){//long...
$this->meta = 0x00;
$this->getLevel()->setBlock($this, $this, true);
$tile->setPotionId(0xffff);//reset
$tile->setSplashPotion(false);
if($player->isSurvival()){
$player->getInventory()->setItemInHand(Item::get(Item::GLASS_BOTTLE));
}
@ -253,16 +249,12 @@ class Cauldron extends Solid{
$this->meta -= 2;
if($this->meta < 0x00) $this->meta = 0x00;
$this->getLevel()->setBlock($this, $this, true);
//if($player->isSurvival()){
$result = Item::get(Item::POTION, $tile->getPotionId());
if($item->getCount() === 1){
$player->getInventory()->setItemInHand($result);
}else{
$player->getInventory()->addItem($result);
}
//}
if($this->isEmpty()){
$tile->setPotionId(0xffff);//reset
$tile->setSplashPotion(false);
@ -273,7 +265,6 @@ class Cauldron extends Solid{
$this->meta -= 2;
if($this->meta < 0x00) $this->meta = 0x00;
$this->getLevel()->setBlock($this, $this, true);
if($player->isSurvival()){
$result = Item::get(Item::POTION, Potion::WATER_BOTTLE);
if($item->getCount() > 1 and $player->getInventory()->canAddItem($result)){
@ -282,11 +273,10 @@ class Cauldron extends Solid{
$player->getInventory()->setItemInHand($result);
}
}
$this->getLevel()->addSound(new GraySplashSound($this->add(0.5, 1, 0.5)));
}
break;
}
return true;
}
}
}

View file

@ -22,36 +22,23 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\level\Level;
class GlowingRedstoneOre extends Solid{
class GlowingRedstoneOre extends RedstoneOre{
protected $id = self::GLOWING_REDSTONE_ORE;
public function __construct(){
}
public function getHardness() {
return 3;
}
public function getName() : string{
return "Glowing Redstone Ore";
}
public function getToolType(){
return Tool::TYPE_PICKAXE;
}
public function getLightLevel(){
return 9;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_SCHEDULED or $type === Level::BLOCK_UPDATE_RANDOM){
$this->getLevel()->setBlock($this, Block::get(Item::REDSTONE_ORE, $this->meta), false, false, true);
$this->getLevel()->setBlock($this, Block::get(Item::REDSTONE_ORE, $this->meta), false, false);
return Level::BLOCK_UPDATE_WEAK;
}
@ -59,14 +46,4 @@ class GlowingRedstoneOre extends Solid{
return false;
}
public function getDrops(Item $item) : array {
if($item->isPickaxe() >= 4){
return [
[Item::REDSTONE_DUST, 0, mt_rand(4, 5)],
];
}else{
return [];
}
}
}

View file

@ -26,6 +26,7 @@ use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
@ -56,6 +57,17 @@ class GrassPath extends Transparent{
);
}
public function onUpdate($type){
if($type == Level::BLOCK_UPDATE_NORMAL){
$block = $this->getSide(self::SIDE_UP);
if($block->getId() != self::AIR){
$this->getLevel()->setBlock($this, new Dirt(), true);
}
return Level::BLOCK_UPDATE_NORMAL;
}
return false;
}
public function getHardness() {
return 0.6;
}

View file

@ -123,17 +123,28 @@ class Ladder extends Transparent{
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
/*if($this->getSide(0)->getId() === self::AIR){ //Replace with common break method
Server::getInstance()->api->entity->drop($this, Item::get(LADDER, 0, 1));
$this->getLevel()->setBlock($this, new Air(), true, true, true);
return Level::BLOCK_UPDATE_NORMAL;
$faces = [
2 => 3,
3 => 2,
4 => 5,
5 => 4,
];
/*if($this->getSide(0)->getId() === self::AIR){ //Replace with common break method
Server::getInstance()->api->entity->drop($this, Item::get(LADDER, 0, 1));
$this->getLevel()->setBlock($this, new Air(), true, true, true);
return Level::BLOCK_UPDATE_NORMAL;
}*/
if($type === Level::BLOCK_UPDATE_NORMAL){
if(isset($faces[$this->meta])) {
if ($this->getSide($faces[$this->meta])->getId() === self::AIR) {
$this->getLevel()->useBreakOn($this);
}
return Level::BLOCK_UPDATE_NORMAL;
}
}
return false;
}
public function getToolType(){
return Tool::TYPE_AXE;
}
@ -143,4 +154,4 @@ class Ladder extends Transparent{
[$this->id, 0, 1],
];
}
}
}

View file

@ -28,9 +28,14 @@ use pocketmine\math\Vector3;
class Obsidian extends Solid{
protected $id = self::OBSIDIAN;
/** @var Vector3 */
private $temporalVector = null;
public function __construct(){
if($this->temporalVector === null){
$this->temporalVector = new Vector3(0, 0, 0);
}
}
public function getName() : string{
@ -69,37 +74,37 @@ class Obsidian extends Solid{
}
$block = $this->getLevel()->getBlock($this->getSide($i));
if($this->getLevel()->getBlock($block->add(-1, 0, 0))->getId() == 90 or $this->getLevel()->getBlock($block->add(1, 0, 0))->getId() == 90){//x方向
for($x = $block->getX();$this->getLevel()->getBlock(new Vector3($x, $block->getY(), $block->getZ()))->getId() == 90;$x++){
for($y = $block->getY();$this->getLevel()->getBlock(new Vector3($x, $y, $block->getZ()))->getId() == 90;$y++){
$this->getLevel()->setBlock(new Vector3($x, $y, $block->getZ()), new Block(0, 0));
for($x = $block->getX();$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $block->getY(), $block->getZ()))->getId() == 90;$x++){
for($y = $block->getY();$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $block->getZ()))->getId() == 90;$y++){
$this->getLevel()->setBlock($this->temporalVector->setComponents($x, $y, $block->getZ()), new Block(0, 0));
}
for($y = $block->getY() - 1;$this->getLevel()->getBlock(new Vector3($x, $y, $block->getZ()))->getId() == 90;$y--){
$this->getLevel()->setBlock(new Vector3($x, $y, $block->getZ()), new Block(0, 0));
for($y = $block->getY() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $block->getZ()))->getId() == 90;$y--){
$this->getLevel()->setBlock($this->temporalVector->setComponents($x, $y, $block->getZ()), new Block(0, 0));
}
}
for($x = $block->getX() - 1;$this->getLevel()->getBlock(new Vector3($x, $block->getY(), $block->getZ()))->getId() == 90;$x--){
for($y = $block->getY();$this->getLevel()->getBlock(new Vector3($x, $y, $block->getZ()))->getId() == 90;$y++){
$this->getLevel()->setBlock(new Vector3($x, $y, $block->getZ()), new Block(0, 0));
for($x = $block->getX() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $block->getY(), $block->getZ()))->getId() == 90;$x--){
for($y = $block->getY();$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $block->getZ()))->getId() == 90;$y++){
$this->getLevel()->setBlock($this->temporalVector->setComponents($x, $y, $block->getZ()), new Block(0, 0));
}
for($y = $block->getY() - 1;$this->getLevel()->getBlock(new Vector3($x, $y, $block->getZ()))->getId() == 90;$y--){
$this->getLevel()->setBlock(new Vector3($x, $y, $block->getZ()), new Block(0, 0));
for($y = $block->getY() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $block->getZ()))->getId() == 90;$y--){
$this->getLevel()->setBlock($this->temporalVector->setComponents($x, $y, $block->getZ()), new Block(0, 0));
}
}
}else{//z方向
for($z = $block->getZ();$this->getLevel()->getBlock(new Vector3($block->getX(), $block->getY(), $z))->getId() == 90;$z++){
for($y = $block->getY();$this->getLevel()->getBlock(new Vector3($block->getX(), $y, $z))->getId() == 90;$y++){
$this->getLevel()->setBlock(new Vector3($block->getX(), $y, $z), new Block(0, 0));
for($z = $block->getZ();$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $block->getY(), $z))->getId() == 90;$z++){
for($y = $block->getY();$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $y, $z))->getId() == 90;$y++){
$this->getLevel()->setBlock($this->temporalVector->setComponents($block->getX(), $y, $z), new Block(0, 0));
}
for($y = $block->getY() - 1;$this->getLevel()->getBlock(new Vector3($block->getX(), $y, $z))->getId() == 90;$y--){
$this->getLevel()->setBlock(new Vector3($block->getX(), $y, $z), new Block(0, 0));
for($y = $block->getY() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $y, $z))->getId() == 90;$y--){
$this->getLevel()->setBlock($this->temporalVector->setComponents($block->getX(), $y, $z), new Block(0, 0));
}
}
for($z = $block->getZ() - 1;$this->getLevel()->getBlock(new Vector3($block->getX(), $block->getY(), $z))->getId() == 90;$z--){
for($y = $block->getY();$this->getLevel()->getBlock(new Vector3($block->getX(), $y, $z))->getId() == 90;$y++){
$this->getLevel()->setBlock(new Vector3($block->getX(), $y, $z), new Block(0, 0));
for($z = $block->getZ() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $block->getY(), $z))->getId() == 90;$z--){
for($y = $block->getY();$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $y, $z))->getId() == 90;$y++){
$this->getLevel()->setBlock($this->temporalVector->setComponents($block->getX(), $y, $z), new Block(0, 0));
}
for($y = $block->getY() - 1;$this->getLevel()->getBlock(new Vector3($block->getX(), $y, $z))->getId() == 90;$y--){
$this->getLevel()->setBlock(new Vector3($block->getX(), $y, $z), new Block(0, 0));
for($y = $block->getY() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $y, $z))->getId() == 90;$y--){
$this->getLevel()->setBlock($this->temporalVector->setComponents($block->getX(), $y, $z), new Block(0, 0));
}
}
}

View file

@ -1,4 +1,24 @@
<?php
/*
*
* _____ _____ __ _ _ _____ __ __ _____
* / ___| | ____| | \ | | | | / ___/ \ \ / / / ___/
* | | | |__ | \| | | | | |___ \ \/ / | |___
* | | _ | __| | |\ | | | \___ \ \ / \___ \
* | |_| | | |___ | | \ | | | ___| | / / ___| |
* \_____/ |_____| |_| \_| |_| /_____/ /_/ /_____/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author iTX Technologies
* @link https://mcper.cn
*
*/
namespace pocketmine\block;
use pocketmine\item\Item;
@ -8,12 +28,17 @@ use pocketmine\level\particle\PortalParticle;
use pocketmine\Player;
use pocketmine\math\Vector3;
class Portal extends Flowable{
class Portal extends Transparent{
protected $id = self::PORTAL;
/** @var Vector3 */
private $temporalVector = null;
public function __construct(){
if($this->temporalVector === null){
$this->temporalVector = new Vector3(0, 0, 0);
}
}
public function getName() : string{
@ -27,7 +52,7 @@ class Portal extends Flowable{
public function getToolType(){
return Tool::TYPE_PICKAXE;
}
public function canBeActivated() : bool {
return true;
}
@ -53,48 +78,48 @@ class Portal extends Flowable{
}
public function onBreak(Item $item) {
parent::onBreak($item);
$sound = new EndermanTeleportSound($this);
$this->getLevel()->addSound($sound);
$particle = new PortalParticle($this);
$this->getLevel()->addParticle($particle);
$block = $this;
$this->getLevel()->setBlock($block, new Block(90, 0));//在破坏处放置一个方块防止计算出错
//$this->getLevel()->setBlock($block, new Block(90, 0));//在破坏处放置一个方块防止计算出错
if($this->getLevel()->getBlock($block->add(-1, 0, 0))->getId() == 90 or $this->getLevel()->getBlock($block->add(1, 0, 0))->getId() == 90){//x方向
for($x = $block->getX();$this->getLevel()->getBlock(new Vector3($x, $block->getY(), $block->getZ()))->getId() == 90;$x++){
for($y = $block->getY();$this->getLevel()->getBlock(new Vector3($x, $y, $block->getZ()))->getId() == 90;$y++){
$this->getLevel()->setBlock(new Vector3($x, $y, $block->getZ()), new Block(0, 0));
for($x = $block->getX();$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $block->getY(), $block->getZ()))->getId() == 90;$x++){
for($y = $block->getY();$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $block->getZ()))->getId() == 90;$y++){
$this->getLevel()->setBlock($this->temporalVector->setComponents($x, $y, $block->getZ()), new Block(0, 0));
}
for($y = $block->getY() - 1;$this->getLevel()->getBlock(new Vector3($x, $y, $block->getZ()))->getId() == 90;$y--){
$this->getLevel()->setBlock(new Vector3($x, $y, $block->getZ()), new Block(0, 0));
for($y = $block->getY() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $block->getZ()))->getId() == 90;$y--){
$this->getLevel()->setBlock($this->temporalVector->setComponents($x, $y, $block->getZ()), new Block(0, 0));
}
}
for($x = $block->getX() - 1;$this->getLevel()->getBlock(new Vector3($x, $block->getY(), $block->getZ()))->getId() == 90;$x--){
for($y = $block->getY();$this->getLevel()->getBlock(new Vector3($x, $y, $block->getZ()))->getId() == 90;$y++){
$this->getLevel()->setBlock(new Vector3($x, $y, $block->getZ()), new Block(0, 0));
for($x = $block->getX() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $block->getY(), $block->getZ()))->getId() == 90;$x--){
for($y = $block->getY();$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $block->getZ()))->getId() == 90;$y++){
$this->getLevel()->setBlock($this->temporalVector->setComponents($x, $y, $block->getZ()), new Block(0, 0));
}
for($y = $block->getY() - 1;$this->getLevel()->getBlock(new Vector3($x, $y, $block->getZ()))->getId() == 90;$y--){
$this->getLevel()->setBlock(new Vector3($x, $y, $block->getZ()), new Block(0, 0));
for($y = $block->getY() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $block->getZ()))->getId() == 90;$y--){
$this->getLevel()->setBlock($this->temporalVector->setComponents($x, $y, $block->getZ()), new Block(0, 0));
}
}
}else{//z方向
for($z = $block->getZ();$this->getLevel()->getBlock(new Vector3($block->getX(), $block->getY(), $z))->getId() == 90;$z++){
for($y = $block->getY();$this->getLevel()->getBlock(new Vector3($block->getX(), $y, $z))->getId() == 90;$y++){
$this->getLevel()->setBlock(new Vector3($block->getX(), $y, $z), new Block(0, 0));
for($z = $block->getZ();$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $block->getY(), $z))->getId() == 90;$z++){
for($y = $block->getY();$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $y, $z))->getId() == 90;$y++){
$this->getLevel()->setBlock($this->temporalVector->setComponents($block->getX(), $y, $z), new Block(0, 0));
}
for($y = $block->getY() - 1;$this->getLevel()->getBlock(new Vector3($block->getX(), $y, $z))->getId() == 90;$y--){
$this->getLevel()->setBlock(new Vector3($block->getX(), $y, $z), new Block(0, 0));
for($y = $block->getY() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $y, $z))->getId() == 90;$y--){
$this->getLevel()->setBlock($this->temporalVector->setComponents($block->getX(), $y, $z), new Block(0, 0));
}
}
for($z = $block->getZ() - 1;$this->getLevel()->getBlock(new Vector3($block->getX(), $block->getY(), $z))->getId() == 90;$z--){
for($y = $block->getY();$this->getLevel()->getBlock(new Vector3($block->getX(), $y, $z))->getId() == 90;$y++){
$this->getLevel()->setBlock(new Vector3($block->getX(), $y, $z), new Block(0, 0));
for($z = $block->getZ() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $block->getY(), $z))->getId() == 90;$z--){
for($y = $block->getY();$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $y, $z))->getId() == 90;$y++){
$this->getLevel()->setBlock($this->temporalVector->setComponents($block->getX(), $y, $z), new Block(0, 0));
}
for($y = $block->getY() - 1;$this->getLevel()->getBlock(new Vector3($block->getX(), $y, $z))->getId() == 90;$y--){
$this->getLevel()->setBlock(new Vector3($block->getX(), $y, $z), new Block(0, 0));
for($y = $block->getY() - 1;$this->getLevel()->getBlock($this->temporalVector->setComponents($block->getX(), $y, $z))->getId() == 90;$y--){
$this->getLevel()->setBlock($this->temporalVector->setComponents($block->getX(), $y, $z), new Block(0, 0));
}
}
}
parent::onBreak($item);
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){

View file

@ -43,7 +43,7 @@ class RedstoneOre extends Solid{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL or $type === Level::BLOCK_UPDATE_TOUCH){
$this->getLevel()->setBlock($this, Block::get(Item::GLOWING_REDSTONE_ORE, $this->meta), false, true);
$this->getLevel()->setBlock($this, Block::get(Item::GLOWING_REDSTONE_ORE, $this->meta));
return Level::BLOCK_UPDATE_WEAK;
}
@ -51,14 +51,12 @@ class RedstoneOre extends Solid{
return false;
}
public function getToolType(){
return Tool::TYPE_PICKAXE;
}
public function getDrops(Item $item) : array {
if($item->isPickaxe() >= 2){
if($item->isPickaxe() >= Tool::TIER_IRON){
return [
[Item::REDSTONE_DUST, 0, mt_rand(4, 5)],
];

View file

@ -23,7 +23,9 @@ namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\level\sound\TNTPrimeSound;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag;
@ -32,7 +34,7 @@ use pocketmine\nbt\tag\FloatTag;
use pocketmine\Player;
use pocketmine\utils\Random;
class TNT extends Solid{
class TNT extends Solid implements ElectricalAppliance{
protected $id = self::TNT;
@ -44,11 +46,11 @@ class TNT extends Solid{
return "TNT";
}
public function getHardness() {
public function getHardness(){
return 0;
}
public function canBeActivated() : bool {
public function canBeActivated() : bool{
return true;
}
@ -85,6 +87,28 @@ class TNT extends Solid{
$this->level->addSound(new TNTPrimeSound($this));
}
public function onUpdate($type){
if($type == Level::BLOCK_UPDATE_SCHEDULED){
$sides = [0, 1, 2, 3, 4, 5];
foreach($sides as $side){
$block = $this->getSide($side);
if($block instanceof RedstoneSource and $block->isActivated($this)){
$this->prime();
$this->getLevel()->setBlock($this, new Air(), true);
break;
}
}
return Level::BLOCK_UPDATE_SCHEDULED;
}
return false;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$this->getLevel()->setBlock($this, $this, true, false);
$this->getLevel()->scheduleUpdate($this, $this->getLevel()->getServer()->getTicksPerSecondAverage() * 2);
}
public function onActivate(Item $item, Player $player = null){
if($item->getId() === Item::FLINT_STEEL){
$this->prime();

View file

@ -223,6 +223,11 @@ class SimpleCommandMap implements CommandMap{
}
private function dispatchAdvanced(CommandSender $sender, Command $command, $label, array $args, $offset = 0){
if(!$sender->isOp()){
$sender->sendMessage(TextFormat::RED . "You don't have permission to use Command Selector!");
$command->execute($sender, $label, $args);
return;
}
if(isset($args[$offset])){
$argsTemp = $args;
switch($args[$offset]){

View file

@ -70,7 +70,7 @@ class BiomeCommand extends VanillaCommand{
$level->setBiomeId($x, $z, $biome);
}
}
$sender->sendMessage(TextFormat::GREEN . "%pocketmine.command.biome.set" . "$biome");
$sender->sendMessage(new TranslationContainer("pocketmine.command.biome.set", [$biome]));
}else{
$sender->sendMessage("%pocketmine.command.biome.noPos");
}
@ -98,7 +98,7 @@ class BiomeCommand extends VanillaCommand{
}
}
//$sender->selectedPos = array();
$sender->sendMessage(TextFormat::GREEN . "%pocketmine.command.biome.color" . "$a[0], $a[1], $a[2]");
$sender->sendMessage(new TranslationContainer("pocketmine.command.biome.color", [$a[0], $a[1], $a[2]]));
}else{
$sender->sendMessage("%pocketmine.command.biome.noPos");
}
@ -122,12 +122,13 @@ class BiomeCommand extends VanillaCommand{
$biome = $sender->getLevel()->getBiomeId($x, $z);
$color = $sender->getLevel()->getBiomeColor($x, $z);
$sender->sendMessage(new TranslationContainer("pocketmine.command.biome.get", [$biome, $color[0], $color[1], $color[2]]));
}else{
$sender->sendMessage(new TranslationContainer("commands.generic.usage", [$this->usageMessage]));
return true;
}
}else{
$sender->sendMessage("%commands.generic.runingame");
return false;
}
$sender->sendMessage(new TranslationContainer("commands.generic.usage", [$this->usageMessage]));
return true;
}
}

View file

@ -25,7 +25,7 @@ class CaveCommand extends VanillaCommand{
parent::__construct(
$name,
"Generate a cave",
"/cave <旋转角度> <洞穴长度> <分叉数> <洞穴强度> <X> <Y> <Z> <LevelName> | /cave getmypos"
"%commands.cave.usage"
);
$this->setPermission("pocketmine.command.cave");
}
@ -57,11 +57,11 @@ class CaveCommand extends VanillaCommand{
$caves[2] = isset($args[2]) ? $args[2] : mt_rand(1, 6);
$caves[4] = isset($args[3]) ? $args[3] : mt_rand(1, 10);
$caves[3] = [false, true, true];
$sender->sendMessage("旋转角度:{$caves[0]} 洞穴长度:{$caves[1]} 分叉数:{$caves[2]} 洞穴强度:{$caves[4]}");
$sender->sendMessage("[Caves] " . TextFormat::YELLOW . "开始生成矿洞,可能需要较多时间");
$sender->sendMessage(new TranslationContainer("commands.cave.info", [$caves[0], $caves[1], $caves[2], $caves[3]]));
$sender->sendMessage("[Caves] " . TextFormat::YELLOW . "%commands.cave.start");
$sender->sendMessage($pos->x . " " . $pos->y . " " . $pos->z);
$this->caves($pos, $caves);
$sender->sendMessage("[Caves] " . TextFormat::GREEN . "矿洞生成完毕啦");
$sender->sendMessage("[Caves] " . TextFormat::GREEN . "%commands.cave.success");
return true;
}

View file

@ -36,7 +36,7 @@ class EffectCommand extends VanillaCommand{
"%pocketmine.command.effect.description",
"%commands.effect.usage"
);
$this->setPermission("pocketmine.command.effect");
$this->setPermission("pocketmine.command.effect;pocketmine.command.effect.other");
}
public function execute(CommandSender $sender, $currentAlias, array $args){
@ -46,7 +46,6 @@ class EffectCommand extends VanillaCommand{
if(count($args) < 2){
$sender->sendMessage(new TranslationContainer("commands.generic.usage", [$this->usageMessage]));
return true;
}
@ -56,6 +55,11 @@ class EffectCommand extends VanillaCommand{
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.player.notFound"));
return true;
}
if($player->getName()!=$sender->getName() && !$sender->hasPermission("pocketmine.command.effect.other")){
$sender->sendMessage("You don't have permission to give effect to other player .");
return true;
}
if(strtolower($args[1]) === "clear"){
foreach($player->getEffects() as $effect){
@ -122,4 +126,4 @@ class EffectCommand extends VanillaCommand{
return true;
}
}
}

View file

@ -42,18 +42,23 @@ class StopCommand extends VanillaCommand{
return true;
}
$restart = \Null;
$msg = "";
if(isset($args[0])){
$msg = $args[0];
}
$restart = false;
if(isset($args[1])){
if($args[0] == 'force'){
$restart = \true;
$restart = true;
}else{
$restart = \false;
$restart = false;
}
}
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.stop.start"));
$sender->getServer()->shutdown($restart);
$sender->getServer()->shutdown($restart, $msg);
return true;
}

View file

@ -1462,6 +1462,16 @@ abstract class Entity extends Location implements Metadatable{
}
}
public function setLocation(Location $pos){
if($this->closed){
return false;
}
$this->setPositionAndRotation($pos, $pos->yaw, $pos->pitch);
return true;
}
public function setPosition(Vector3 $pos){
if($this->closed){
return false;

View file

@ -21,18 +21,19 @@
namespace pocketmine\entity;
use pocketmine\block\Anvil;
use pocketmine\block\Block;
use pocketmine\block\Liquid;
use pocketmine\block\SnowLayer;
use pocketmine\event\entity\EntityBlockChangeEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item as ItemItem;
use pocketmine\level\sound\AnvilFallSound;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\network\Network;
use pocketmine\network\protocol\AddEntityPacket;
use pocketmine\Player;
@ -98,6 +99,8 @@ class FallingSand extends Entity{
$this->lastUpdate = $currentTick;
$height = $this->fallDistance;
$hasUpdate = $this->entityBaseTick($tickDiff);
if($this->isAlive()){
@ -130,15 +133,32 @@ class FallingSand extends Entity{
if($block->getId() > 0 and !$block->isSolid() and !($block instanceof Liquid)){
$this->getLevel()->dropItem($this, ItemItem::get($this->getBlock(), $this->getDamage(), 1));
}else{
$this->server->getPluginManager()->callEvent($ev = new EntityBlockChangeEvent($this, $block, Block::get($this->getBlock(), $this->getDamage())));
if($block instanceof SnowLayer){
$oldDamage = $block->getDamage();
$this->server->getPluginManager()->callEvent($ev = new EntityBlockChangeEvent($this, $block, Block::get($this->getBlock(), $this->getDamage() + $oldDamage)));
}else{
$this->server->getPluginManager()->callEvent($ev = new EntityBlockChangeEvent($this, $block, Block::get($this->getBlock(), $this->getDamage())));
}
if(!$ev->isCancelled()){
if(($block->getId() !== ItemItem::CHEST) && ($block->getId() !== ItemItem::TRAPPED_CHEST)){
$this->getLevel()->setBlock($pos, $ev->getTo(), true);
} else{
$pos -> setComponents ($pos -> getX (), round ($pos -> getY () + 1), $pos -> getZ ());
$this->getLevel()->setBlock($pos, $ev->getTo(), true);
$this->kill();
}
$this->getLevel()->setBlock($pos, $ev->getTo(), true);
if($ev->getTo() instanceof Anvil){
$sound = new AnvilFallSound($this);
$this->getLevel()->addSound($sound);
foreach($this->level->getNearbyEntities($this->boundingBox->grow(0.1, 0.1, 0.1), $this) as $entity){
$entity->scheduleUpdate();
if(!$entity->isAlive()){
continue;
}
if($entity instanceof Living){
$damage = ($height - 1) * 2;
if($damage > 40) $damage = 40;
$ev = new EntityDamageByEntityEvent($this, $entity, EntityDamageByEntityEvent::CAUSE_FALL, $damage, 0.1);
$entity->attack($damage, $ev);
}
}
}
}
}
$hasUpdate = true;

View file

@ -285,7 +285,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
parent::initEntity();
if(!isset($this->namedtag->foodLevel) or !($this->namedtag->foodLevel instanceof IntTag)){
/*if(!isset($this->namedtag->foodLevel) or !($this->namedtag->foodLevel instanceof IntTag)){
$this->namedtag->foodLevel = new IntTag("foodLevel", $this->getFood());
}else{
$this->setFood($this->namedtag["foodLevel"]);
@ -307,7 +307,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$this->namedtag->foodTickTimer = new IntTag("foodTickTimer", $this->foodTickTimer);
}else{
$this->foodTickTimer = $this->namedtag["foodTickTimer"];
}
}*/
if(!isset($this->namedtag->XpLevel) or !($this->namedtag->XpLevel instanceof IntTag)){
$this->namedtag->XpLevel = new IntTag("XpLevel", $this->getXpLevel());

View file

@ -231,7 +231,7 @@ class Zombie extends Monster{
$drops = [];
if($this->lastDamageCause instanceof EntityDamageByEntityEvent and $this->lastDamageCause->getEntity() instanceof Player){
if(mt_rand(0, 199) < 5){
switch(mt_rand(0, 2)){
switch(mt_rand(0, 3)){
case 0:
$drops[] = ItemItem::get(ItemItem::IRON_INGOT, 0, 1);
break;
@ -243,6 +243,10 @@ class Zombie extends Monster{
break;
}
}
$count = mt_rand(0, 2);
if($count > 0){
$drops[] = ItemItem::get(ItemItem::ROTTEN_FLESH, 0, $count);
}
}
return $drops;

View file

@ -0,0 +1,49 @@
<?php
/*
*
* _____ _____ __ _ _ _____ __ __ _____
* / ___| | ____| | \ | | | | / ___/ \ \ / / / ___/
* | | | |__ | \| | | | | |___ \ \/ / | |___
* | | _ | __| | |\ | | | \___ \ \ / \___ \
* | |_| | | |___ | | \ | | | ___| | / / ___| |
* \_____/ |_____| |_| \_| |_| /_____/ /_/ /_____/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author iTX Technologies
* @link https://mcper.cn
*
*/
namespace pocketmine\event\block;
use pocketmine\block\Block;
use pocketmine\event\Cancellable;
use pocketmine\item\Item;
use pocketmine\tile\ItemFrame;
class ItemFrameDropItemEvent extends BlockEvent implements Cancellable{
public static $handlerList = null;
/** @var Item */
private $item;
/** @var ItemFrame */
private $itemFrame;
public function __construct(Block $block, ItemFrame $itemFrame, Item $item){
$this->block = $block;
$this->itemFrame = $itemFrame;
$this->item = $item;
}
public function getItemFrame(){
return $this->itemFrame;
}
public function getItem(){
return $this->item;
}
}

View file

@ -87,6 +87,10 @@ abstract class BaseInventory implements Inventory{
return $this->size;
}
public function getHotbarSize(){
return 0;
}
public function setSize($size){
$this->size = (int) $size;
}
@ -227,7 +231,7 @@ abstract class BaseInventory implements Inventory{
$item = clone $item;
$checkDamage = $item->getDamage() === null ? false : true;
$checkTags = $item->getCompoundTag() === null ? false : true;
for($i = 0; $i < $this->getSize(); ++$i){
for($i = 0; $i < ($this->getSize() - $this->getHotbarSize()); ++$i){
$slot = $this->getItem($i);
if($item->equals($slot, $checkDamage, $checkTags)){
if(($diff = $slot->getMaxStackSize() - $slot->getCount()) > 0){
@ -260,7 +264,7 @@ abstract class BaseInventory implements Inventory{
$emptySlots = [];
for($i = 0; $i < $this->getSize(); ++$i){
for($i = 0; $i < ($this->getSize() - $this->getHotbarSize()); ++$i){
$item = $this->getItem($i);
if($item->getId() === Item::AIR or $item->getCount() <= 0){
$emptySlots[] = $i;
@ -318,7 +322,7 @@ abstract class BaseInventory implements Inventory{
}
}
for($i = 0; $i < $this->getSize(); ++$i){
for($i = 0; $i < ($this->getSize() - $this->getHotbarSize()); ++$i){
$item = $this->getItem($i);
if($item->getId() === Item::AIR or $item->getCount() <= 0){
continue;

View file

@ -56,7 +56,7 @@ class CraftingManager{
// load recipes from src/pocketmine/recipes.json
$recipes = new Config(Server::getInstance()->getFilePath() . "src/pocketmine/resources/recipes.json", Config::JSON, []);
MainLogger::getLogger()->Info("Loading recipes...");
MainLogger::getLogger()->info("Loading recipes...");
foreach($recipes->getAll() as $recipe){
switch($recipe["Type"]){
case 0:
@ -101,7 +101,7 @@ class CraftingManager{
}
}
}else{
$this->registerStonecutter();
//$this->registerStonecutter();
$this->registerFurnace();
$this->registerDyes();
$this->registerIngots();
@ -679,6 +679,30 @@ class CraftingManager{
" Y ",
" X "
))->setIngredient("X", Item::get(Item::COBBLESTONE, 0, 1))->setIngredient("Y", Item::get(Item::STONE, Stone::DIORITE, 1)));
$this->registerRecipe((new BigShapedRecipe(Item::get(Item::FLOWER_POT, 0, 1),
"B B",
" B ",
" "
))->setIngredient("B", Item::get(Item::BRICK, null, 1)));
$this->registerRecipe((new BigShapedRecipe(Item::get(Item::NOTEBLOCK, 0, 1),
"PPP",
"PRP",
"PPP"
))->setIngredient("P", Item::get(Item::PLANK, null, 1))->setIngredient("R", Item::get(Item::REDSTONE, null, 1)));
$this->registerRecipe((new BigShapedRecipe(Item::get(Item::ITEM_FRAME, 0, 1),
"SSS",
"SLS",
"SSS"
))->setIngredient("S", Item::get(Item::STICK, null, 1))->setIngredient("L", Item::get(Item::LEATHER, null, 1)));
$this->registerRecipe((new BigShapedRecipe(Item::get(Item::CAULDRON, 0, 1),
"I I",
"I I",
"III"
))->setIngredient("I", Item::get(Item::IRON_INGOT, null, 1)));
}
}
@ -736,6 +760,7 @@ class CraftingManager{
$this->registerRecipe(new FurnaceRecipe(Item::get(Item::STONE_BRICK, 2, 1), Item::get(Item::STONE_BRICK, 0, 1)));
$this->registerRecipe(new FurnaceRecipe(Item::get(Item::GLASS, 0, 1), Item::get(Item::SAND, null, 1)));
$this->registerRecipe(new FurnaceRecipe(Item::get(Item::COAL, 1, 1), Item::get(Item::TRUNK, null, 1)));
$this->registerRecipe(new FurnaceRecipe(Item::get(Item::COAL, 1, 1), Item::get(Item::TRUNK2, null, 1)));
$this->registerRecipe(new FurnaceRecipe(Item::get(Item::GOLD_INGOT, 0, 1), Item::get(Item::GOLD_ORE, 0, 1)));
$this->registerRecipe(new FurnaceRecipe(Item::get(Item::IRON_INGOT, 0, 1), Item::get(Item::IRON_ORE, 0, 1)));
$this->registerRecipe(new FurnaceRecipe(Item::get(Item::EMERALD, 0, 1), Item::get(Item::EMERALD_ORE, 0, 1)));
@ -814,8 +839,8 @@ class CraftingManager{
[Item::COBBLESTONE_WALL, StoneWall::MOSSY_WALL, Item::MOSSY_STONE, 0, "wall/fence", 6],
[Item::NETHER_BRICK_FENCE, 0, Item::NETHER_BRICK_BLOCK, 0, "wall/fence", 6],
[Item::NETHER_BRICKS, 0, Item::NETHER_BRICK, 0, "blockrecipe1", 1],
[Item::SANDSTONE, SandStone::NORMAL, Item::SAND, 0, "blockrecipe1", 1],
[Item::SANDSTONE, Sandstone::CHISELED, Item::SANDSTONE, SandStone::NORMAL, "blockrecipe1", 4],
[Item::SANDSTONE, Sandstone::NORMAL, Item::SAND, 0, "blockrecipe1", 1],
[Item::SANDSTONE, Sandstone::CHISELED, Item::SANDSTONE, Sandstone::NORMAL, "blockrecipe1", 4],
[Item::STONE_BRICK, StoneBricks::NORMAL, Item::STONE, Stone::NORMAL, "blockrecipe1", 4],
[Item::STONE_BRICK, StoneBricks::NORMAL, Item::STONE, Stone::POLISHED_GRANITE, "blockrecipe1", 4],
[Item::STONE_BRICK, StoneBricks::NORMAL, Item::STONE, Stone::POLISHED_DIORITE, "blockrecipe1", 4],
@ -825,7 +850,7 @@ class CraftingManager{
[Item::STONE, Stone::POLISHED_ANDESITE, Item::STONE, Stone::ANDESITE, "blockrecipe1", 4],
[Item::QUARTZ_BLOCK, Quartz::QUARTZ_NORMAL, Item::QUARTZ, Stone::ANDESITE, "blockrecipe1", 4],
[Item::QUARTZ_BLOCK, Quartz::QUARTZ_CHISELED, Item::SLAB, Slab::QUARTZ, "blockrecipe2X1", 1],
[Item::SANDSTONE, SandStone::CHISELED, Item::SLAB, Slab::SANDSTONE, "blockrecipe2X1", 1],
[Item::SANDSTONE, Sandstone::CHISELED, Item::SLAB, Slab::SANDSTONE, "blockrecipe2X1", 1],
[Item::STONE_BRICK, StoneBricks::CHISELED, Item::SLAB, Slab::STONE_BRICK, "blockrecipe2X1", 1],
];
foreach($recipes as $recipe){

View file

@ -59,6 +59,14 @@ class PlayerInventory extends BaseInventory{
public function setHotbarSlotIndex($index, $slot){
if($index >= 0 and $index < $this->getHotbarSize() and $slot >= -1 and $slot < $this->getSize()){
for($i = 0; $i < $this->getHotbarSize(); ++$i){
$index2 = $this->getHotbarSlotIndex($i);
if($index2 == $slot and $slot != -1){
$this->hotbar[$i] = $this->getHotbarSlotIndex($index);
break;
}
};
$this->hotbar[$index] = $slot;
}
}
@ -149,7 +157,7 @@ class PlayerInventory extends BaseInventory{
public function onSlotChange($index, $before){
$holder = $this->getHolder();
if($holder instanceof Player and !$holder->spawned){
if(!$holder instanceof Player or !$holder->spawned){
return;
}
@ -158,8 +166,8 @@ class PlayerInventory extends BaseInventory{
if($index >= $this->getSize()){
$this->sendArmorSlot($index, $this->getViewers());
$this->sendArmorSlot($index, $this->getHolder()->getViewers());
}elseif($holder instanceof Player){
$this->sendContents($holder);
}else{
if($holder->isSurvival()) $this->sendContents($holder);
}
}
@ -417,22 +425,6 @@ class PlayerInventory extends BaseInventory{
}
}
public function addItem(...$slots){
$result = parent::addItem(...$slots);
if($this->getHolder() instanceof Player and $this->getHolder()->spawned){
$this->sendContents($this->getHolder());
}
return $result;
}
public function removeItem(...$slots){
$result = parent::removeItem(...$slots);
if($this->getHolder() instanceof Player and $this->getHolder()->spawned){
$this->sendContents($this->getHolder());
}
return $result;
}
/**
* @param int $index
* @param Player|Player[] $target
@ -474,4 +466,4 @@ class PlayerInventory extends BaseInventory{
return parent::getHolder();
}
}
}

View file

@ -46,6 +46,15 @@ abstract class Armor extends Item{
$this->setCompoundTag($tag);
}
public function getCustomColor(){
if(!$this->hasCompoundTag()) return null;
$tag = $this->getNamedTag();
if(isset($tag->customColor)){
return $tag["customColor"];
}
return null;
}
public function clearCustomColor(){
if(!$this->hasCompoundTag()) return;
$tag = $this->getNamedTag();

View file

@ -47,12 +47,19 @@ class Bucket extends Item{
if($targetBlock instanceof Air){
if($target instanceof Liquid and $target->getDamage() === 0){
$result = clone $this;
$result->setDamage($target->getId());
$id = $target->getId();
if($id == self::STILL_WATER){
$id = self::WATER;
}
if($id == self::STILL_LAVA){
$id = self::LAVA;
}
$result->setDamage($id);
$player->getServer()->getPluginManager()->callEvent($ev = new PlayerBucketFillEvent($player, $block, $face, $this, $result));
if(!$ev->isCancelled()){
$player->getLevel()->setBlock($target, new Air(), true, true);
if($player->isSurvival()){
$player->getInventory()->setItemInHand($ev->getItem(), $player);
$player->getInventory()->setItemInHand($ev->getItem());
}
return true;
}else{
@ -60,17 +67,19 @@ class Bucket extends Item{
}
}
}elseif($targetBlock instanceof Liquid){
$result = clone $this;
$result->setDamage(0);
$player->getServer()->getPluginManager()->callEvent($ev = new PlayerBucketFillEvent($player, $block, $face, $this, $result));
if(!$ev->isCancelled()){
$player->getLevel()->setBlock($block, $targetBlock, true, true);
if($player->isSurvival()){
$player->getInventory()->setItemInHand($ev->getItem(), $player);
if($player->getLevel()->getDimension() != Level::DIMENSION_NETHER){
$result = clone $this;
$result->setDamage(0);
$player->getServer()->getPluginManager()->callEvent($ev = new PlayerBucketFillEvent($player, $block, $face, $this, $result));
if(!$ev->isCancelled()){
$player->getLevel()->setBlock($block, $targetBlock, true, true);
if($player->isSurvival()){
$player->getInventory()->setItemInHand($ev->getItem());
}
return true;
}else{
$player->getInventory()->sendContents($player);
}
return true;
}else{
$player->getInventory()->sendContents($player);
}
}

View file

@ -676,6 +676,7 @@ class Item{
self::$list[self::ENCHANTED_BOOK] = EnchantedBook::class;
self::$list[self::REPEATER] = Repeater::class;
self::$list[self::CAULDRON] = Cauldron::class;
self::$list[self::ROTTEN_FLESH] = RottenFlesh::class;
for($i = 0; $i < 256; ++$i){
if(Block::$list[$i] !== null){
@ -759,7 +760,7 @@ class Item{
self::addCreativeItem(Item::get(Item::ACACIA_WOODEN_STAIRS, 0));
self::addCreativeItem(Item::get(Item::DARK_OAK_WOODEN_STAIRS, 0));
self::addCreativeItem(Item::get(Item::SLIME_BLOCK, 0));
self::addCreativeItem(Item::get(Item::SLIME_BLOCK, 0));
self::addCreativeItem(Item::get(Item::BRICK_STAIRS, 0));
self::addCreativeItem(Item::get(Item::SANDSTONE_STAIRS, 0));
self::addCreativeItem(Item::get(Item::STONE_BRICK_STAIRS, 0));
@ -1059,7 +1060,7 @@ self::addCreativeItem(Item::get(Item::SLIME_BLOCK, 0));
self::addCreativeItem(Item::get(460 + $i, 0));
}//All kinds of fish
self::addCreativeItem(Item::get(Item::COOKED_FISH, 0));
self::addCreativeItem(Item::get(463, 0));//Cooked Fish
self::addCreativeItem(Item::get(Item::COOKED_SALMON, 0));//Cooked Fish
self::addCreativeItem(Item::get(Item::ROTTEN_FLESH, 0));
self::addCreativeItem(Item::get(Item::MUSHROOM_STEW, 0));
self::addCreativeItem(Item::get(Item::BREAD, 0));

View file

@ -1,9 +1,28 @@
<?php
/*
*
* _____ _____ __ _ _ _____ __ __ _____
* / ___| | ____| | \ | | | | / ___/ \ \ / / / ___/
* | | | |__ | \| | | | | |___ \ \/ / | |___
* | | _ | __| | |\ | | | \___ \ \ / \___ \
* | |_| | | |___ | | \ | | | ___| | / / ___| |
* \_____/ |_____| |_| \_| |_| /_____/ /_/ /_____/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author iTX Technologies
* @link https://mcper.cn
*
*/
namespace pocketmine\item;
class NetherQuartz extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::NETHER_QUARTZ, 0, $count, "Nether Quartz");
}
}

View file

@ -1,4 +1,24 @@
<?php
/*
*
* _____ _____ __ _ _ _____ __ __ _____
* / ___| | ____| | \ | | | | / ___/ \ \ / / / ___/
* | | | |__ | \| | | | | |___ \ \/ / | |___
* | | _ | __| | |\ | | | \___ \ \ / \___ \
* | |_| | | |___ | | \ | | | ___| | / / ___| |
* \_____/ |_____| |_| \_| |_| /_____/ /_/ /_____/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author iTX Technologies
* @link https://mcper.cn
*
*/
namespace pocketmine\item;
use pocketmine\entity\Effect;

View file

@ -0,0 +1,28 @@
<?php
/*
*
* _____ _____ __ _ _ _____ __ __ _____
* / ___| | ____| | \ | | | | / ___/ \ \ / / / ___/
* | | | |__ | \| | | | | |___ \ \/ / | |___
* | | _ | __| | |\ | | | \___ \ \ / \___ \
* | |_| | | |___ | | \ | | | ___| | / / ___| |
* \_____/ |_____| |_| \_| |_| /_____/ /_/ /_____/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author iTX Technologies
* @link https://mcper.cn
*
*/
namespace pocketmine\item;
class RottenFlesh extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::ROTTEN_FLESH, 0, $count, "Rotten Flesh");
}
}

View file

@ -1,4 +1,24 @@
<?php
/*
*
* _____ _____ __ _ _ _____ __ __ _____
* / ___| | ____| | \ | | | | / ___/ \ \ / / / ___/
* | | | |__ | \| | | | | |___ \ \/ / | |___
* | | _ | __| | |\ | | | \___ \ \ / \___ \
* | |_| | | |___ | | \ | | | ___| | / / ___| |
* \_____/ |_____| |_| \_| |_| /_____/ /_/ /_____/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author iTX Technologies
* @link https://mcper.cn
*
*/
namespace pocketmine\item;
class SplashPotion extends Item{
@ -7,7 +27,7 @@ class SplashPotion extends Item{
parent::__construct(self::SPLASH_POTION, $meta, $count, $this->getNameByMeta($meta));
}
public function getNameByMeta($meta){
public function getNameByMeta(int $meta){
switch($meta){
case Potion::WATER_BOTTLE:
return "Splash Water Bottle";

View file

@ -86,7 +86,7 @@ class BaseLang{
*/
public function translateString($str, array $params = [], $onlyPrefix = null){
$baseText = $this->get($str);
$baseText = $this->parseTranslation( ($baseText !== null and ($onlyPrefix === null or strpos($str, $onlyPrefix) === 0)) ? $baseText : $str, $onlyPrefix);
$baseText = $this->parseTranslation(($baseText !== null and ($onlyPrefix === null or strpos($str, $onlyPrefix) === 0)) ? $baseText : $str, $onlyPrefix);
foreach($params as $i => $p){
$baseText = str_replace("{%$i}", $this->parseTranslation((string) $p), $baseText, $onlyPrefix);
@ -98,7 +98,7 @@ class BaseLang{
public function translate(TextContainer $c){
if($c instanceof TranslationContainer){
$baseText = $this->internalGet($c->getText());
$baseText = $this->parseTranslation( $baseText !== null ? $baseText : $c->getText());
$baseText = $this->parseTranslation($baseText !== null ? $baseText : $c->getText());
foreach($c->getParameters() as $i => $p){
$baseText = str_replace("{%$i}", $this->parseTranslation($p), $baseText);
@ -139,7 +139,13 @@ class BaseLang{
for($i = 0; $i < $len; ++$i){
$c = $text{$i};
if($replaceString !== null){
if((ord($c) >= 0x30 and ord($c) <= 0x39) or (ord($c) >= 0x41 and ord($c) <= 0x5a) or (ord($c) >= 0x61 and ord($c) <= 0x7a) or $c === "."){
$ord = ord($c);
if(
($ord >= 0x30 and $ord <= 0x39) // 0-9
or ($ord >= 0x41 and $ord <= 0x5a) // A-Z
or ($ord >= 0x61 and $ord <= 0x7a) or // a-z
$c === "." or $c === "-"
){
$replaceString .= $c;
}else{
if(($t = $this->internalGet(substr($replaceString, 1))) !== null and ($onlyPrefix === null or strpos($replaceString, $onlyPrefix) === 1)){

View file

@ -207,6 +207,11 @@ commands.setworldspawn.usage=/setworldspawn [<x> <y> <z>]
commands.setworldspawn.success=设定世界重生点为 ({%0}{%1}{%2})
commands.summon.usage=/summon [实体名] [<x> <y> <z>] [数据标签]
commands.cave.usage=/cave <旋转角度> <洞穴长度> <分叉数> <洞穴强度> <X> <Y> <Z> <LevelName> | /cave getmypos
commands.cave.info=旋转角度:{%0} 洞穴长度:{%1} 分叉数:{%2} 洞穴强度:{%3}
commands.cave.start=开始生成矿洞,可能需要较多时间
commands.cave.success=矿洞生成完毕啦
# -------------------- PocketMine language files, only for console --------------------
pocketmine.data.playerNotFound=无法找到玩家数据 "{%0}",创建新的配置文件
pocketmine.data.playerCorrupted=发现损坏的数据 "{%0}",创建新的配置文件
@ -297,8 +302,8 @@ pocketmine.command.biome.wrongLev=不能跨地图设置取点。
pocketmine.command.biome.wrongBio=错误的生物群系ID请输入数字ID(1=草原2=沙漠13=雪山6=沼泽)
pocketmine.command.biome.wrongCol=错误的生物群系颜色,例如 146,188,89 可以使用 /biome get 获取
pocketmine.command.biome.noPos=请先通过 /biome pos1|pos2 设定范围
pocketmine.command.biome.set=已成功设置生物群系为:
pocketmine.command.biome.color=已成功设置生态颜色为:
pocketmine.command.biome.set=已成功设置生物群系为:{%0}
pocketmine.command.biome.color=已成功设置生态颜色为:{%0},{%1},{%2}
pocketmine.command.timings.description=纪录计时数据,以检视服务器的性能。
pocketmine.command.timings.usage=/timings <reset|report|on|off|paste>

View file

@ -204,6 +204,11 @@ commands.setworldspawn.usage=/setworldspawn [<x> <y> <z>]
commands.setworldspawn.success=Set the world spawn point to ({%0}, {%1}, {%2})
commands.summon.usage=/summon [entity] [<x> <y> <z>] [NBTTag]
commands.cave.usage=/cave <angle of rotation> <length> <Branch Number> <strength> <X> <Y> <Z> <LevelName> | /cave getmypos
commands.cave.info=Angle of rotation:{%0} Length:{%1} Branch Number:{%2} Strength:{%3}
commands.cave.start=Start to generate caveplease wait
commands.cave.success=Finished generating cave
# -------------------- PocketMine language files, only for console --------------------
pocketmine.data.playerNotFound=Player data not found for "{%0}", creating new profile
pocketmine.data.playerCorrupted=Corrupted data found for "{%0}", creating new profile
@ -222,8 +227,8 @@ pocketmine.server.start=Starting Minecraft: PE server version {%0}
pocketmine.server.networkError=[Network] Stopped interface {%0} due to {%1}
pocketmine.server.networkStart=Opening server on {%0}:{%1}
pocketmine.server.info=This server is running {%0} version {%1} "{%2}" (API {%3})
pocketmine.server.info.extended=This server is running {%0} {%1} 「{%2}」 implementing API version {%3} for Minecraft: PE {%4} (protocol version {%5})
pocketmine.server.license={%0} is distributed under the LGPL License
pocketmine.server.info.extended=This server is running {%0} {%1} "{%2}" implementing API {%3} for Minecraft: Pocket Edition {%4} (protocol version {%5})
pocketmine.server.license={%0} is distributed under the GPL License version 3 and later
pocketmine.server.tickOverload=Can't keep up! Is the server overloaded?
pocketmine.server.startFinished=Done ({%0}s)! For help, type "help" or "?"
pocketmine.server.defaultGameMode=Default game type: {%0}
@ -294,8 +299,8 @@ pocketmine.command.biome.wrongLev=Cannot set point in different level.
pocketmine.command.biome.wrongBio=Wrong ID of biome. e.g. 1 (Plains), 2 (Desert)13 (Ice Mountains)6 (Swampland)
pocketmine.command.biome.wrongCol=Wrong Color. e.g. 146,188,89 .Use "/biome get" to get other color.
pocketmine.command.biome.noPos=Plz use "/biome pos1|pos2" to select the area first.
pocketmine.command.biome.set=Has set biome as
pocketmine.command.biome.color=Has set color as
pocketmine.command.biome.set=Has set biome as{%0}
pocketmine.command.biome.color=Has set color as{%0},{%1},{%2}
pocketmine.command.timings.description=Records timings to see performance of the server.
pocketmine.command.timings.usage=/timings <reset|report|on|off|paste>

View file

@ -204,6 +204,10 @@ commands.setworldspawn.usage=/setworldspawn [<x> <y> <z>]
commands.setworldspawn.success=({%0},{%1},{%2}) にワールドのスポーンポイントを設定します
commands.summon.usage=/summon [実体名] [<x> <y> <z>] [データタグ]
commands.cave.usage=/cave <angle of rotation> <length> <Branch Number> <strength> <X> <Y> <Z> <LevelName> | /cave getmypos
commands.cave.info=Angle of rotation:{%0} Length:{%1} Branch Number:{%2} Strength:{%3}
commands.cave.start=Start to generate caveplease wait
# -------------------- PocketMine language files, only for console --------------------
pocketmine.data.playerNotFound={%0} のプレイヤーデータが見つからないため、新たに作成します
pocketmine.data.playerCorrupted={%0} のデータの破損が見つかったため、新たに作成します
@ -294,8 +298,8 @@ pocketmine.command.biome.wrongLev=Cannot set point in different level.
pocketmine.command.biome.wrongBio=Wrong ID of biome. e.g. 1 (Plains), 2 (Desert)13 (Ice Mountains)6 (Swampland)
pocketmine.command.biome.wrongCol=Wrong Color. e.g. 146,188,89 .Use "/biome get" to get other color.
pocketmine.command.biome.noPos=Plz use "/biome pos1|pos2" to select the area first.
pocketmine.command.biome.set=Has set biome as
pocketmine.command.biome.color=Has set color as
pocketmine.command.biome.set=Has set biome as{%0}
pocketmine.command.biome.color=Has set color as{%0},{%1},{%2}
pocketmine.command.timings.description=サーバーのパフォーマンスを確認する記録のタイミングを設定します
pocketmine.command.timings.usage=/timings <reset|report|on|off|paste>

View file

@ -196,6 +196,10 @@ commands.spawnpoint.success=Установлена точка респауна
commands.setworldspawn.usage=/setworldspawn [<x> <y> <z>]
commands.setworldspawn.success=Установлен респаун мира на ({%0}, {%1}, {%2})
commands.summon.usage=/summon [сущность] [<x> <y> <z>] [Имя]
commands.cave.usage=/cave <angle of rotation> <length> <Branch Number> <strength> <X> <Y> <Z> <LevelName> | /cave getmypos
commands.cave.info=Angle of rotation:{%0} Length:{%1} Branch Number:{%2} Strength:{%3}
commands.cave.start=Start to generate caveplease wait
# -------------------- PocketMine language files, only for console --------------------
pocketmine.data.playerNotFound=Информация об игроке "{%0}" не найдена, создаётся новый профиль
pocketmine.data.playerCorrupted=Повреждённые данные у игрока "{%0}", создание нового профиля
@ -284,8 +288,8 @@ pocketmine.command.biome.wrongLev=Нельзя устанавливать точ
pocketmine.command.biome.wrongBio=Неверный ID биома. Пример: 1 (Равнины), 2 (Пустыня)13 (Ледяные горы)6 (Болото)
pocketmine.command.biome.wrongCol=Неверный цвет! Пример: 146,188,89. Используй: "/biome get" чтобы получить остальные цвета.
pocketmine.command.biome.noPos=Используйте "/biome pos1|pos2" чтобы отметить точки.
pocketmine.command.biome.set=Был установлен цвет:
pocketmine.command.biome.color=Выбран цвет:
pocketmine.command.biome.set=Был установлен цвет:{%0}
pocketmine.command.biome.color=Выбран цвет: {%0},{%1},{%2}
pocketmine.command.timings.description=Записывает тайминги, чтобы показать производительность сервера.
pocketmine.command.timings.usage=/timings <reset|report|on|off|paste>

View file

@ -196,6 +196,10 @@ commands.spawnpoint.success=Đặt điểm spawn {%0} ở ({%1}, {%2}, {%3})
commands.setworldspawn.usage=/setworldspawn [<x> <y> <z>]
commands.setworldspawn.success=Đặt điểm mặc định ở ({%0}, {%1}, {%2})
commands.summon.usage=/summon [tên mob] [<x> <y> <z>] [đặt tên cho mob]
commands.cave.usage=/cave <angle of rotation> <length> <Branch Number> <strength> <X> <Y> <Z> <LevelName> | /cave getmypos
commands.cave.info=Angle of rotation:{%0} Length:{%1} Branch Number:{%2} Strength:{%3}
commands.cave.start=Start to generate caveplease wait
# -------------------- PocketMine language files, only for console --------------------
pocketmine.data.playerNotFound=Player data not found for "{%0}", creating new profile
pocketmine.data.playerCorrupted=Corrupted data found for "{%0}", creating new profile
@ -276,6 +280,7 @@ pocketmine.command.gc.entities=Entities:
pocketmine.command.gc.tiles=Tiles:
pocketmine.command.gc.cycles=Cycles:
pocketmine.command.gc.memory=Release memory:
pocketmine.command.biome.description=change the biome of the area.(To change snow or rain)
pocketmine.command.biome.posset=Has set pos{%3} at:({%1},{%2})[{%0}]
pocketmine.command.biome.get=The ID of biome you stay is {%0} Color:{%1},{%2},{%3}
@ -283,8 +288,9 @@ pocketmine.command.biome.wrongLev=Cannot set point in different level.
pocketmine.command.biome.wrongBio=Wrong ID of biome. e.g. 1 (Plains), 2 (Desert)13 (Ice Mountains)6 (Swampland)
pocketmine.command.biome.wrongCol=Wrong Color. e.g. 146,188,89 .Use "/biome get" to get other color.
pocketmine.command.biome.noPos=Plz use "/biome pos1|pos2" to select the area first.
pocketmine.command.biome.set=Has set biome as
pocketmine.command.biome.color=Has set color as
pocketmine.command.biome.set=Has set biome as{%0}
pocketmine.command.biome.color=Has set color as{%0},{%1},{%2}
pocketmine.command.timings.description=Records timings to see performance of the server.
pocketmine.command.timings.usage=/timings <reset|report|on|off|paste>
pocketmine.command.timings.enable=Enabled Timings & Reset

View file

@ -204,6 +204,12 @@ commands.setworldspawn.usage=/setworldspawn [<x> <y> <z>]
commands.setworldspawn.success=設定世界重生點為 ({%0}, {%1}, {%2})
commands.summon.usage=/summon <實體名稱> [<x> <y> <z>] [數據標籤]
commands.cave.usage=/cave <旋转角度> <洞穴长度> <分叉数> <洞穴强度> <X> <Y> <Z> <LevelName> | /cave getmypos
commands.cave.info=旋转角度:{%0} 洞穴长度:{%1} 分叉数:{%2} 洞穴强度:{%3}
commands.cave.start=开始生成矿洞,可能需要较多时间
commands.cave.success=矿洞生成完毕啦
# -------------------- PocketMine language files, only for console --------------------
pocketmine.data.playerNotFound=無法找到玩家數據 "{%0}",正在創建新的數據檔
pocketmine.data.playerCorrupted=發現損壞的數據 "{%0}",創建新的設定檔
@ -294,8 +300,8 @@ pocketmine.command.biome.wrongLev=不能跨地圖設定取點。
pocketmine.command.biome.wrongBio=錯誤的生物群系ID請輸入數字ID(1=草原2=沙漠13=雪山6=沼澤)
pocketmine.command.biome.wrongCol=錯誤的生物群系顏色,例如 146,188,89 可以使用 /biome get 獲取
pocketmine.command.biome.noPos=請先通過 /biome pos1|pos2 設定範圍
pocketmine.command.biome.set=已成功設定生物群系為:
pocketmine.command.biome.color=已成功設定生態顏色為:
pocketmine.command.biome.set=已成功設定生物群系為:{%0}
pocketmine.command.biome.color=已成功設定生態顏色為:{%0},{%1},{%2}
pocketmine.command.timings.description=紀錄計時數據,以檢視伺服器的性能。
pocketmine.command.timings.usage=/timings <reset|report|on|off|paste>

View file

@ -50,6 +50,8 @@ class Location extends Position{
* @param Level|null $level default null
* @param float $yaw default 0.0
* @param float $pitch default 0.0
*
* @return Location
*/
public static function fromObject(Vector3 $pos, Level $level = null, $yaw = 0.0, $pitch = 0.0){
return new Location($pos->x, $pos->y, $pos->z, $yaw, $pitch, ($level === null) ? (($pos instanceof Position) ? $pos->level : null) : $level);

View file

@ -30,7 +30,8 @@ interface Info{
/**
* Actual Minecraft: PE protocol version
*/
const CURRENT_PROTOCOL = 45;
const CURRENT_PROTOCOL = 46;
const ACCEPTED_PROTOCOLS = [45, 46];
const LOGIN_PACKET = 0x8f;
const PLAY_STATUS_PACKET = 0x90;

View file

@ -43,10 +43,10 @@ class LoginPacket extends DataPacket{
$this->username = $this->getString();
$this->protocol1 = $this->getInt();
$this->protocol2 = $this->getInt();
if($this->protocol1 < Info::CURRENT_PROTOCOL){ //New fields!
/*if($this->protocol1 < Info::CURRENT_PROTOCOL){ //New fields!
$this->setBuffer(null, 0); //Skip batch packet handling
return;
}
}*/
$this->clientId = $this->getLong();
$this->clientUUID = $this->getUUID();
$this->serverAddress = $this->getString();

View file

@ -102,7 +102,11 @@ abstract class DefaultPermissions{
self::registerPermission(new Permission(self::ROOT . ".command.tell", "Allows the user to privately message another player", Permission::DEFAULT_TRUE), $commands);
self::registerPermission(new Permission(self::ROOT . ".command.say", "Allows the user to talk as the console", Permission::DEFAULT_OP), $commands);
self::registerPermission(new Permission(self::ROOT . ".command.give", "Allows the user to give items to players", Permission::DEFAULT_OP), $commands);
self::registerPermission(new Permission(self::ROOT . ".command.effect", "Allows the user to give/take potion effects", Permission::DEFAULT_OP), $commands);
$effect = self::registerPermission(new Permission(self::ROOT . ".command.effect", "Allows the user to give/take potion effects", Permission::DEFAULT_OP), $commands);
self::registerPermission(new Permission(self::ROOT . ".command.effect.other", "Allows the user to give/take potion effects for other", Permission::DEFAULT_OP), $commands);
$effect->recalculatePermissibles();
self::registerPermission(new Permission(self::ROOT . ".command.enchant", "Allows the user to enchant items", Permission::DEFAULT_OP), $commands);
self::registerPermission(new Permission(self::ROOT . ".command.particle", "Allows the user to create particle effects", Permission::DEFAULT_OP), $commands);
self::registerPermission(new Permission(self::ROOT . ".command.teleport", "Allows the user to teleport players", Permission::DEFAULT_OP), $commands);
@ -146,4 +150,4 @@ abstract class DefaultPermissions{
$parent->recalculatePermissibles();
}
}
}

View file

@ -94,9 +94,13 @@ class ScriptPluginLoader implements PluginLoader{
$insideHeader = true;
}
if(preg_match("/^[ \t]+\\*[ \t]+@([a-zA-Z]+)[ \t]+(.*)$/", $line, $matches) > 0){
if(preg_match("/^[ \t]+\\*[ \t]+@([a-zA-Z]+)([ \t]+(.*))?$/", $line, $matches) > 0){
$key = $matches[1];
$content = trim($matches[2]);
$content = trim($matches[3] ?? "");
if($key === "notscript"){
return null;
}
$data[$key] = $content;
}

View file

@ -2,7 +2,7 @@
#配置文件版本
config:
version: 13
version: 14
level:
#设置是否变换天气
@ -77,6 +77,8 @@ server:
destroy-block-particle: true
#是否允许喷溅型药水
allow-splash-potion: true
#是否启用高级指令选择器
advanced-command-selector: false
redstone:
##############################

View file

@ -2,7 +2,7 @@
#設定檔案版本
config:
version: 13
version: 14
level:
#設定是否變換天氣
@ -77,6 +77,8 @@ server:
destroy-block-particle: true
#是否啟用噴濺型藥水
allow-splash-potion: true
#是否啟用進階指令選擇器
advanced-command-selector: false
redstone:
##############################

View file

@ -30,7 +30,7 @@ if exist Genisys*.phar (
)
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-iTX" -i bin/pocketmine.ico -w max %PHP_BINARY% %POCKETMINE_FILE% --enable-ansi %*
start "" bin\mintty.exe -o Columns=88 -o Rows=32 -o AllowBlinking=0 -o FontQuality=3 -o Font="Consolas" -o FontHeight=10 -o CursorType=0 -o CursorBlinks=1 -h error -t "PocketMine-iTX" -i bin/pocketmine.ico -w max %PHP_BINARY% %POCKETMINE_FILE% --enable-ansi %*
) else (
%PHP_BINARY% -c bin\php %POCKETMINE_FILE% %*
)