Minecraft: Pocket Edition 0.7.0 dev. release

* Crafting enabled, report bugs
* Chat handler
This commit is contained in:
Shoghi Cervantes 2013-06-06 17:14:09 +02:00
parent 1f4df559e0
commit 4b408675cf
25 changed files with 652 additions and 420 deletions

View File

@ -100,6 +100,9 @@ class BlockAPI{
array(LADDER, 0),
array(TORCH, 0),
array(GLASS_PANE, 0),
array(BUCKET, 0),
array(BUCKET, 8),
array(BUCKET, 10),
array(WOODEN_DOOR, 0),
array(TRAPDOOR, 0),
array(FENCE, 0),
@ -129,9 +132,15 @@ class BlockAPI{
array(MELON_SEEDS, 0),
array(DYE, 15), //Bonemeal
array(IRON_HOE, 0),
array(CAKE, 0),
array(EGG, 0),
array(IRON_SWORD, 0),
array(BOW, 0),
array(SIGN, 0),
array(SPAWN_EGG, MOB_CHICKEN),
array(SPAWN_EGG, MOB_COW),
array(SPAWN_EGG, MOB_PIG),
array(SPAWN_EGG, MOB_SHEEP),
);
public static function fromString($str, $multiple = false){
@ -217,11 +226,7 @@ class BlockAPI{
$output .= "Player is in creative mode.\n";
break;
}
if($this->server->api->getProperty("item-enforcement") === false){
$this->server->api->entity->drop(new Position($player->entity->x - 0.5, $player->entity->y, $player->entity->z - 0.5, $player->level), $item, true);
}else{
$player->addItem($item->getID(), $item->getMetadata(), $item->count);
}
$player->addItem($item->getID(), $item->getMetadata(), $item->count);
$output .= "Giving ".$item->count." of ".$item->getName()." (".$item->getID().":".$item->getMetadata().") to ".$player->username."\n";
}else{
$output .= "Unknown player.\n";
@ -240,16 +245,14 @@ class BlockAPI{
"block" => $block->getID(),
"meta" => $block->getMetadata()
));
if($player->itemEnforcement === true){
$player->sendInventory();
}
$player->sendInventorySlot($player->slot);
return false;
}
public function playerBlockBreak(Player $player, Vector3 $vector){
$target = $player->level->getBlock($vector);
$item = $player->equipment;
$item = $player->getSlot($player->slot);
if($this->server->api->dhandle("player.block.touch", array("type" => "break", "player" => $player, "target" => $target, "item" => $item)) === false){
return $this->cancelAction($target, $player);
@ -287,7 +290,7 @@ class BlockAPI{
$target = $player->level->getBlock($vector);
$block = $target->getSide($face);
$item = $player->equipment;
$item = $player->getSlot($player->slot);
if($target->getID() === AIR and $this->server->api->dhandle("player.block.place.invalid", array("player" => $player, "block" => $block, "target" => $target, "item" => $item)) !== true){ //If no block exists or not allowed in CREATIVE
$this->cancelAction($target, $player);
@ -343,7 +346,10 @@ class BlockAPI{
}
if(($player->gamemode & 0x01) === 0x00){
$player->removeItem($item->getID(), $item->getMetadata(), 1);
--$item->count;
if($item->count <= 0){
$player->setSlot($player->slot, BlockAPI::getItem(AIR, 0, 0));
}
}
return false;

View File

@ -419,7 +419,7 @@ class PlayerAPI{
"y" => $this->server->spawn->y,
"z" => $this->server->spawn->z,
),
"inventory" => array_fill(0, 36, array(AIR, 0, 0)),
"inventory" => array_fill(0, PLAYER_SURVIVAL_SLOTS, array(AIR, 0, 0)),
"armor" => array_fill(0, 4, array(AIR, 0, 0)),
"gamemode" => $this->server->gamemode,
"health" => 20,

View File

@ -72,7 +72,6 @@ class ServerAPI{
"view-distance" => 10,
"max-players" => 20,
"allow-flight" => false,
"item-enforcement" => false,
"gamemode" => SURVIVAL,
"hardcore" => false,
"pvp" => true,
@ -289,7 +288,7 @@ class ServerAPI{
if($this->getProperty("enable-query") === true){
$this->query = new Query();
}
CraftingRecipes::init();
$this->server->init();
unregister_tick_function(array($this->server, "tick"));
$this->console->__destruct();

View File

@ -1,122 +0,0 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
class TileEntityAPI{
private $server;
private $tileEntities;
private $tCnt = 1;
function __construct(){
$this->tileEntities = array();
$this->server = ServerAPI::request();
}
public function get(Position $pos){
$tile = $this->server->query("SELECT * FROM tileentities WHERE level = '".$pos->level->getName()."' AND x = {$pos->x} AND y = {$pos->y} AND z = {$pos->z};", true);
if($tile !== false and $tile !== true and ($tile = $this->getByID($tile["ID"])) !== false){
return $tile;
}
return false;
}
public function getByID($id){
if($id instanceof TileEntity){
return $id;
}elseif(isset($this->tileEntities[$id])){
return $this->tileEntities[$id];
}
return false;
}
public function init(){
}
public function getAll($level = null){
if($level instanceof Level){
$tileEntities = array();
$l = $this->server->query("SELECT ID FROM tileentities WHERE level = '".$level->getName()."';");
if($l !== false and $l !== true){
while(($t = $l->fetchArray(SQLITE3_ASSOC)) !== false){
$t = $this->getByID($t["ID"]);
if($t instanceof TileEntity){
$tileEntities[$t->id] = $t;
}
}
}
return $tileEntities;
}
return $this->tileEntities;
}
public function add(Level $level, $class, $x, $y, $z, $data = array()){
$id = $this->tCnt++;
$this->tileEntities[$id] = new TileEntity($level, $id, $class, $x, $y, $z, $data);
$this->spawnToAll($this->tileEntities[$id]);
return $this->tileEntities[$id];
}
public function addSign(Level $level, $x, $y, $z, $lines = array("", "", "", "")){
return $this->add($level, TILE_SIGN, $x, $y, $z, $data = array(
"id" => "Sign",
"x" => $x,
"y" => $y,
"z" => $z,
"Text1" => $lines[0],
"Text2" => $lines[1],
"Text3" => $lines[2],
"Text4" => $lines[3],
));
}
public function spawnToAll(TileEntity $t){
foreach($this->server->api->player->getAll($t->level) as $player){
if($player->eid !== false){
$t->spawn($player);
}
}
}
public function spawnAll(Player $player){
foreach($this->getAll($player->level) as $t){
$t->spawn($player);
}
}
public function remove($id){
if(isset($this->tileEntities[$id])){
$t = $this->tileEntities[$id];
$this->tileEntities[$id] = null;
unset($this->tileEntities[$id]);
$t->closed = true;
$t->close();
$this->server->query("DELETE FROM tileentities WHERE ID = ".$id.";");
$this->server->api->dhandle("tile.remove", $t);
$t = null;
unset($t);
}
}
}

View File

@ -43,6 +43,8 @@ class Player{
private $iusername;
private $eid = false;
private $startAction = false;
private $queue = array();
private $need = array();
public $data;
public $entity = false;
public $auth = false;
@ -50,12 +52,12 @@ class Player{
public $MTU;
public $spawned = false;
public $inventory;
public $equipment;
public $slot;
public $armor;
public $loggedIn = false;
public $gamemode;
public $lastBreak;
public $windowCnt = 0;
public $windowCnt = 2;
public $windows = array();
public $blocked = true;
public $chunksLoaded = array();
@ -67,10 +69,11 @@ class Player{
private $lagStat = 0;
private $spawnPosition;
private $packetLoss = 0;
public $itemEnforcement;
public $lastCorrect;
private $bigCnt;
private $packetStats;
public $craftingItems = array();
public $toCraft = array();
public function __get($name){
if(isset($this->{$name})){
@ -88,14 +91,13 @@ class Player{
$this->CID = $this->server->clientID($ip, $port);
$this->ip = $ip;
$this->port = $port;
$this->itemEnforcement = $this->server->api->getProperty("item-enforcement");
$this->spawnPosition = $this->server->spawn;
$this->timeout = microtime(true) + 20;
$this->inventory = array_fill(0, 36, array(AIR, 0, 0));
$this->inventory = array();
$this->armor = array_fill(0, 4, array(AIR, 0, 0));
$this->gamemode = $this->server->gamemode;
$this->level = $this->server->api->level->getDefault();
$this->equipment = BlockAPI::getItem(AIR);
$this->slot = 0;
$this->packetStats = array(0,0);
$this->server->schedule(2, array($this, "onTick"), array(), true);
$this->evid[] = $this->server->event("server.close", array($this, "close"));
@ -217,7 +219,12 @@ class Player{
"y" => $this->spawnPosition->y,
"z" => $this->spawnPosition->z,
));
$this->data->set("inventory", $this->inventory);
$inv = array();
foreach($this->inventory as $slot => $item){
$inv[$slot] = array($item->getID(), $item->getMetadata(), $item->count);
}
$this->data->set("inventory", $inv);
$this->data->set("armor", $this->armor);
$this->data->set("gamemode", $this->gamemode);
}
@ -254,17 +261,17 @@ class Player{
$inv = $this->inventory;
while($count > 0){
$add = 0;
foreach($inv as $s => $data){
if($data[0] === AIR){
foreach($inv as $s => $item){
if($item->getID() === AIR){
$add = min(64, $count);
$inv[$s] = array($type, $damage, $add);
$inv[$s] = BlockAPI::getItem($type, $damage, $add);
break;
}elseif($data[0] === $type and $data[1] === $damage){
$add = min(64 - $data[2], $count);
}elseif($item->getID() === $type and $item->getMetadata() === $damage){
$add = min(64 - $item->count, $count);
if($add <= 0){
continue;
}
$inv[$s] = array($type, $damage, $data[2] + $add);
$inv[$s] = BlockAPI::getItem($type, $damage, $item->count + $add);
break;
}
}
@ -276,22 +283,26 @@ class Player{
return true;
}
public function addItem($type, $damage, $count){
public function addItem($type, $damage, $count, $send = true){
while($count > 0){
$add = 0;
foreach($this->inventory as $s => $data){
if($data[0] === AIR){
foreach($this->inventory as $s => $item){
if($item->getID() === AIR){
$add = min(64, $count);
$this->inventory[$s] = array($type, $damage, $add);
$this->sendInventorySlot($s);
$this->inventory[$s] = BlockAPI::getItem($type, $damage, $add);
if($send === true){
$this->sendInventorySlot($s);
}
break;
}elseif($data[0] === $type and $data[1] === $damage){
$add = min(64 - $data[2], $count);
}elseif($item->getID() === $type and $item->getMetadata() === $damage){
$add = min(64 - $item->count, $count);
if($add <= 0){
continue;
}
$this->inventory[$s] = array($type, $damage, $data[2] + $add);
$this->sendInventorySlot($s);
$item->count += $add;
if($send === true){
$this->sendInventorySlot($s);
}
break;
}
}
@ -303,18 +314,20 @@ class Player{
return true;
}
public function removeItem($type, $damage, $count){
public function removeItem($type, $damage, $count, $send = true){
while($count > 0){
$remove = 0;
foreach($this->inventory as $s => $data){
if($data[0] === $type and $data[1] === $damage){
$remove = min($count, $data[2]);
if($remove < $data[2]){
$this->inventory[$s][2] -= $remove;
foreach($this->inventory as $s => $item){
if($item->getID() === $type and $item->getMetadata() === $damage){
$remove = min($count, $item->count);
if($remove < $item->count){
$item->count -= $remove;
}else{
$this->inventory[$s] = array(AIR, 0, 0);
$this->inventory[$s] = BlockAPI::getItem(AIR, 0, 0);
}
if($send === true){
$this->sendInventorySlot($s);
}
$this->sendInventorySlot($s);
break;
}
}
@ -327,45 +340,41 @@ class Player{
}
public function setSlot($slot, Item $item){
$this->inventory[(int) $slot] = array($item->getID(), $item->getMetadata(), $item->count);
$this->inventory[(int) $slot] = $item;
$this->sendInventorySlot((int) $slot);
return true;
}
public function getSlot($slot){
$slot = $this->inventory[(int) $slot];
return BlockAPI::getItem($slot[0], $slot[1], $slot[2]);
if(isset($this->inventory[(int) $slot])){
return $this->inventory[(int) $slot];
}else{
return BlockAPI::getItem(AIR, 0, 0);
}
}
public function sendInventorySlot($s){
$this->sendInventory();
return;
$s = (int) $s;
if(!isset($this->inventory[$s]) or $this->itemEnforcement === false){
if(!isset($this->inventory[$s])){
return false;
}
$this->sendInventory(); //Fallback
return true;
//Can't do this :(
/*$slot = BlockAPI::getItem($this->inventory[$s][0], $this->inventory[$s][1], $this->inventory[$s][2]);
$slot = $this->inventory[$s];
$this->dataPacket(MC_CONTAINER_SET_SLOT, array(
"windowid" => 0,
"slot" => (int) $s,
"slot" => ((int) $s) + 9,
"block" => $slot->getID(),
"stack" => $slot->count,
"meta" => $slot->getMetadata(),
));
return true;*/
return true;
}
public function hasItem($type, $damage = false){
if($type === AIR){
return true;
}
foreach($this->inventory as $s => $data){
if($data[0] === $type and ($data[1] === $damage or $damage === false) and $data[2] > 0){
foreach($this->inventory as $s => $item){
if($item->getID() === $type and ($item->getMetadata() === $damage or $damage === false) and $item->count > 0){
return true;
}
}
@ -432,7 +441,7 @@ class Player{
$data["eid"] = 0;
$this->dataPacket(MC_TAKE_ITEM_ENTITY, $data);
if(($this->gamemode & 0x01) === 0x00){
$this->addItem($data["entity"]->type, $data["entity"]->meta, $data["entity"]->stack);
$this->addItem($data["entity"]->type, $data["entity"]->meta, $data["entity"]->stack, false);
}
}elseif($data["entity"]->level === $this->level){
$this->dataPacket(MC_TAKE_ITEM_ENTITY, $data);
@ -444,12 +453,6 @@ class Player{
}
$this->dataPacket(MC_PLAYER_EQUIPMENT, $data);
break;
case "player.action":
if($data["eid"] === $this->eid or $data["player"]->level !== $this->level){
break;
}
$this->dataPacket(MC_USE_ITEM, $data);
break;
case "entity.move":
if($data->eid === $this->eid or $data->level !== $this->level){
@ -609,6 +612,59 @@ class Player{
));
}
public function craftItems(array $craft, array $recipe, $type){
$craftItem = array(0, true, 0);
unset($craft[-1]);
foreach($craft as $slot => $item){
$craftItem[0] = $item->getID();
if($item->getMetadata() !== $craftItem[1] and $craftItem[0] !== true){
$craftItem[1] = false;
}else{
$craftItem[1] = $item->getMetadata();
}
$craftItem[2] += $item->count;
}
$recipeItems = array();
foreach($recipe as $slot => $item){
if(!isset($recipeItems[$item->getID()])){
$recipeItems[$item->getID()] = array($item->getID(), $item->getMetadata(), $item->count);
}else{
if($item->getMetadata() !== $recipeItems[$item->getID()][1]){
$recipeItems[$item->getID()][1] = false;
}
$recipeItems[$item->getID()][2] += $item->count;
}
}
$res = CraftingRecipes::canCraft($craftItem, $recipeItems, $type);
if(!is_array($res) and $type === 1){
$res2 = CraftingRecipes::canCraft($craftItem, $recipeItems, 0);
if(is_array($res2)){
$res = $res2;
}
}
if(is_array($res)){
foreach($craft as $slot => $item){
$s = $this->getSlot($slot);
if($s->count <= 0 or $s->getID() === AIR){
$this->setSlot($slot, BlockAPI::getItem($item->getID(), $item->getMetadata(), $item->count));
}else{
$s->count += $item->count;
}
}
foreach($recipe as $slot => $item){
$s = $this->getSlot($slot);
$s->count -= $item->count;
if($s->count <= 0){
$this->setSlot($slot, BlockAPI::getItem(AIR, 0, 0));
}
}
}
return $res;
}
public function teleport(Vector3 $pos, $yaw = false, $pitch = false, $terrain = true){
if($this->entity instanceof Entity){
$this->entity->check = false;
@ -656,7 +712,7 @@ class Player{
$this->entity->calculateVelocity();
if($terrain === true){
$this->orderChunks();
$this->getNextChunk(false);
$this->getNextChunk();
}
$this->entity->check = true;
}
@ -708,20 +764,15 @@ class Player{
$this->gamemode = $gm;
$this->eventHandler("Your gamemode has been changed to ".$this->getGamemode().".", "server.chat");
}else{
$inv = array_fill(0, 36, array(AIR, 0, 0));
$inv = array_fill(0, ($gamemode & 0x01) > 0 ? PLAYER_CREATIVE_SLOTS:PLAYER_SURVIVAL_SLOTS, array(AIR, 0, 0));
$this->blocked = true;
$this->gamemode = $gm;
$this->eventHandler("Your gamemode has been changed to ".$this->getGamemode().", you've to do a forced reconnect.", "server.chat");
$this->server->schedule(30, array($this, "close"), "gamemode change"); //Forces a kick
if(($gm & 0x01) === 0x01){
$this->itemEnforcement = true;
}
}
$this->inventory = $inv;
$this->sendSettings();
if($this->itemEnforcement === true){
$this->sendInventory();
}
$this->sendInventory();
return true;
}
@ -824,20 +875,24 @@ class Player{
case 0x8e:
case 0x8f:
if(isset($data[0])){
$this->send(0xc0, array(array($data[0])));
$diff = $data[0] - $this->counter[1];
unset($this->need[$data[0]]);
if($diff > 1){ //Packet recovery
$arr = array();
for($i = $this->counter[1]; $i < $data[0]; ++$i){
$arr[] = $i;
++$this->packetStats[1];
$this->need[$i] = true;
}
$this->send(0xa0, array($arr));
$this->counter[1] = $data[0];
$this->send(0xa0, $arr);
$this->queue[$data[0]] = $data;
break;
}elseif($diff === 1){
$this->counter[1] = $data[0];
++$this->packetStats[0];
}else{
break;
}
++$this->packetStats[0];
$this->send(0xc0, array(array($data[0])));
}
if(!isset($data["id"])){
@ -892,7 +947,7 @@ class Player{
"status" => 2,
));
}
$this->close("Incorrect protocol", false);
$this->close("Incorrect protocol #".$data["protocol1"], false);
break;
}
if(preg_match('#[^a-zA-Z0-9_]#', $data["username"]) == 0){
@ -935,22 +990,25 @@ class Player{
$this->auth = true;
if(!$this->data->exists("inventory") or ($this->gamemode & 0x01) === 0x01){
if(($this->gamemode & 0x01) === 0x01){
$this->itemEnforcement = true;
$this->inventory = array();
$inv = array();
if(($this->gamemode & 0x02) === 0x02){
foreach(BlockAPI::$creative as $item){
$this->inventory[] = array(DANDELION, 0, 1);
$inv[] = array(DANDELION, 0, 1);
}
}else{
foreach(BlockAPI::$creative as $item){
$this->inventory[] = array($item[0], $item[1], 1);
$inv[] = array($item[0], $item[1], 1);
}
}
}
$this->data->set("inventory", $this->inventory);
$this->data->set("inventory", $inv);
}
$this->data->set("caseusername", $this->username);
$this->inventory = $this->data->get("inventory");
$this->inventory = array();
foreach($this->data->get("inventory") as $slot => $item){
$this->inventory[$slot] = BlockAPI::getItem($item[0], $item[1], $item[2]);
}
$this->armor = $this->data->get("armor");
$this->data->set("lastIP", $this->ip);
@ -972,7 +1030,9 @@ class Player{
"eid" => 0,
));
if(($this->gamemode & 0x01) === 0x01){
$this->equipment = BlockAPI::getItem($this->inventory[7][0], $this->inventory[7][1], $this->inventory[7][2]);
$this->slot = 7;
}else{
$this->slot = 0;
}
$this->entity = $this->server->api->entity->add($this->level, ENTITY_PLAYER, 0, array("player" => $this));
$this->eid = $this->entity->eid;
@ -992,7 +1052,6 @@ class Player{
$this->evid[] = $this->server->event("entity.metadata", array($this, "eventHandler"));
$this->evid[] = $this->server->event("player.equipment.change", array($this, "eventHandler"));
$this->evid[] = $this->server->event("player.armor", array($this, "eventHandler"));
$this->evid[] = $this->server->event("player.action", array($this, "eventHandler"));
$this->evid[] = $this->server->event("player.pickup", array($this, "eventHandler"));
$this->evid[] = $this->server->event("tile.container.slot", array($this, "eventHandler"));
$this->evid[] = $this->server->event("tile.update", array($this, "eventHandler"));
@ -1056,13 +1115,26 @@ class Player{
if($this->spawned === false){
break;
}
if($data["slot"] === 0){
$this->slot = -1;
break;
}else{
$data["slot"] -= 9;
}
$data["eid"] = $this->eid;
$data["player"] = $this;
$data["item"] = BlockAPI::getItem($data["block"], $data["meta"]);
if(($this->hasItem($data["block"], $data["meta"]) or $this->itemEnforcement !== true) and $this->server->handle("player.equipment.change", $data) !== false){
$this->equipment = $data["item"];
}elseif($this->itemEnforcement === true){
$this->sendInventory();
$data["item"] = $this->getSlot($data["slot"]);
if(!($data["item"] instanceof Item)){
break;
}
$data["block"] = $data["item"]->getID();
$data["meta"] = $data["item"]->getMetadata();
if($this->server->handle("player.equipment.change", $data) !== false){
$this->slot = $data["slot"];
}else{
$this->sendInventorySlot($data["slot"]);
}
if($this->entity->inAction === true){
$this->entity->inAction = false;
@ -1078,6 +1150,8 @@ class Player{
if($this->spawned === false){
break;
}
$this->craftingItems = array();
$this->toCraft = array();
$data["eid"] = $this->eid;
$data["player"] = $this;
if($data["face"] >= 0 and $data["face"] <= 5){ //Use Block, place
@ -1086,12 +1160,29 @@ class Player{
$this->entity->updateMetadata();
}
if($this->blocked === true or Utils::distance($this->entity->position, $data) > 10){
break;
}elseif(!$this->hasItem($data["block"], $data["meta"]) and $this->itemEnforcement === true){
$this->sendInventory();
}elseif($this->getSlot($this->slot)->getID() !== $data["block"] or $this->getSlot($this->slot)->getMetadata() !== $data["meta"]){
$this->sendInventorySlot($this->slot);
}else{
$this->server->api->block->playerBlockAction($this, new Vector3($data["x"], $data["y"], $data["z"]), $data["face"], $data["fx"], $data["fy"], $data["fz"]);
break;
}
$this->server->api->block->playerBlockAction($this, new Vector3($data["x"], $data["y"], $data["z"]), $data["face"], $data["fx"], $data["fy"], $data["fz"]);
$target = $this->level->getBlock(new Vector3($data["x"], $data["y"], $data["z"]));
$block = $target->getSide($data["face"]);
$this->dataPacket(MC_UPDATE_BLOCK, array(
"x" => $target->x,
"y" => $target->y,
"z" => $target->z,
"block" => $target->getID(),
"meta" => $target->getMetadata()
));
$this->dataPacket(MC_UPDATE_BLOCK, array(
"x" => $block->x,
"y" => $block->y,
"z" => $block->z,
"block" => $block->getID(),
"meta" => $block->getMetadata()
));
break;
}elseif($data["face"] === 0xFF and $this->server->handle("player.action", $data) !== false){
$this->entity->inAction = true;
$this->startAction = microtime(true);
@ -1102,10 +1193,12 @@ class Player{
if($this->spawned === false){
break;
}
$this->craftingItems = array();
$this->toCraft = array();
if($this->entity->inAction === true){
switch($data["action"]){
case 5: //Shot arrow
if($this->equipment->getID() === BOW){
if($this->getSlot($this->slot)->getID() === BOW){
if($this->startAction !== false){
$time = microtime(true) - $this->startAction;
$d = array(
@ -1131,12 +1224,16 @@ class Player{
if($this->blocked === true or $this->entity->distance(new Vector3($data["x"], $data["y"], $data["z"])) > 8){
break;
}
$this->craftingItems = array();
$this->toCraft = array();
$this->server->api->block->playerBlockBreak($this, new Vector3($data["x"], $data["y"], $data["z"]));
break;
case MC_PLAYER_ARMOR_EQUIPMENT:
if($this->spawned === false){
break;
}
$this->craftingItems = array();
$this->toCraft = array();
$data["eid"] = $this->eid;
$data["player"] = $this;
$this->server->handle("player.armor", $data);
@ -1149,6 +1246,8 @@ class Player{
if($this->spawned === false){
break;
}
$this->craftingItems = array();
$this->toCraft = array();
$target = $this->server->api->entity->get($data["target"]);
if($this->gamemode !== VIEW and $this->blocked === false and ($target instanceof Entity) and $this->entity->distance($target) <= 8){
$data["targetentity"] = $target;
@ -1158,7 +1257,7 @@ class Player{
}elseif($target->class === ENTITY_PLAYER and ($this->server->api->getProperty("pvp") == false or $this->server->difficulty <= 0 or ($target->player->gamemode & 0x01) === 0x01)){
break;
}elseif($this->server->handle("player.interact", $data) !== false){
switch($this->equipment->getID()){
switch($this->getSlot($this->slot)->getID()){
case WOODEN_SWORD:
case GOLD_SWORD:
$damage = 4;
@ -1235,6 +1334,8 @@ class Player{
if($this->entity->dead === false){
break;
}
$this->craftingItems = array();
$this->toCraft = array();
$this->entity->fire = 0;
$this->entity->air = 300;
$this->entity->setHealth(20, "respawn");
@ -1250,6 +1351,8 @@ class Player{
if($this->spawned === false){
break;
}
$this->craftingItems = array();
$this->toCraft = array();
$data["eid"] = $this->eid;
if($this->entity->inAction === true){
$this->entity->inAction = false;
@ -1274,13 +1377,13 @@ class Player{
RAW_FISH => 2,
);
if(isset($items[$this->equipment->getID()])){
if($this->removeItem($this->equipment->getID(), $this->equipment->getMetadata(), 1) === true or $this->itemEnforcement !== true){
if(isset($items[$this->getSlot($this->slot)->getID()])){
if($this->removeItem($this->getSlot($this->slot)->getID(), $this->getSlot($this->slot)->getMetadata(), 1, false) === true){
$this->dataPacket(MC_ENTITY_EVENT, array(
"eid" => 0,
"event" => 9,
));
$this->entity->heal($items[$this->equipment->getID()], "eating");
$this->entity->heal($items[$this->getSlot($this->slot)->getID()], "eating");
}
}
break;
@ -1290,12 +1393,12 @@ class Player{
if($this->spawned === false){
break;
}
$item = BlockAPI::getItem($data["block"], $data["meta"], $data["stack"]);
$data["item"] = $item;
$this->craftingItems = array();
$this->toCraft = array();
$data["item"] = $this->getSlot($this->slot);
if($this->blocked === false and $this->server->handle("player.drop", $data) !== false){
if($this->removeItem($item->getID(), $item->getMetadata(), $item->count) === true or $this->itemEnforcement !== true){
$this->server->api->entity->drop(new Position($this->entity->x - 0.5, $this->entity->y, $this->entity->z - 0.5, $this->level), $item);
}
$this->server->api->entity->drop(new Position($this->entity->x - 0.5, $this->entity->y, $this->entity->z - 0.5, $this->level), $data["item"]);
$this->setSlot($this->slot, BlockAPI::getItem(AIR, 0, 0));
}
if($this->entity->inAction === true){
$this->entity->inAction = false;
@ -1306,6 +1409,8 @@ class Player{
if($this->spawned === false){
break;
}
$this->craftingItems = array();
$this->toCraft = array();
$t = $this->server->api->tile->get(new Position($data["x"], $data["y"], $data["z"], $this->level));
if(($t instanceof Tile) and $t->class === TILE_SIGN){
if($t->data["creator"] !== $this->username){
@ -1319,7 +1424,9 @@ class Player{
if($this->spawned === false){
break;
}
$message = $data["message"];
$this->craftingItems = array();
$this->toCraft = array();
$message = preg_replace('#^<.*> #', "", $data["message"]);
if(trim($data["message"]) != "" and strlen($data["message"]) <= 100 and preg_match('#[^\\x20-\\xff]#', $message) == 0){
if($message{0} === "/"){ //Command
$this->server->api->console->run(substr($message, 1), $this);
@ -1334,6 +1441,8 @@ class Player{
if($this->spawned === false){
break;
}
$this->craftingItems = array();
$this->toCraft = array();
unset($this->windows[$data["windowid"]]);
$this->dataPacket(MC_CONTAINER_CLOSE, array(
"windowid" => $data["windowid"],
@ -1343,6 +1452,35 @@ class Player{
if($this->spawned === false){
break;
}
if($data["windowid"] === 0){
$craft = false;
$slot = $this->getSlot($data["slot"]);
if($slot->count >= $data["stack"] and $slot->getID() === $data["block"] and $slot->getMetadata() === $data["meta"] and !isset($this->craftingItems[$data["slot"]])){ //Crafting recipe
$use = BlockAPI::getItem($slot->getID(), $slot->getMetadata(), $slot->count - $data["stack"]);
$this->craftingItems[$data["slot"]] = $use;
$craft = true;
}elseif($slot->count <= $data["stack"] and ($slot->getID() === AIR or $slot->getID() === $data["block"])){ //Crafting final
$craftItem = BlockAPI::getItem($data["block"], $data["meta"], $data["stack"] - $slot->count);
if(count($this->toCraft) === 0){
$this->toCraft[-1] = 0;
}
$this->toCraft[$data["slot"]] = $craftItem;
$craft = true;
}
if($craft === true and count($this->craftingItems) > 0 and count($this->toCraft) > 0 and ($recipe = $this->craftItems($this->toCraft, $this->craftingItems, $this->toCraft[-1])) !== true){
if($recipe === false){
$this->dataPacket(MC_CONTAINER_CLOSE, array(
"windowid" => 0,
));
$this->sendInventory();
$this->toCraft[-1] = 0;
}
$this->toCraft = array(-1 => $this->toCraft[-1]);
$this->craftingItems = array();
}
}
if(!isset($this->windows[$data["windowid"]])){
break;
}
@ -1373,14 +1511,14 @@ class Player{
}
if($item->getID() !== AIR and $slot->getID() == $item->getID()){
if($slot->count < $item->count){
if($this->removeItem($item->getID(), $item->getMetadata(), $item->count - $slot->count) === false and $this->itemEnforcement === true){
if($this->removeItem($item->getID(), $item->getMetadata(), $item->count - $slot->count) === false){
break;
}
}elseif($slot->count > $item->count){
$this->addItem($item->getID(), $item->getMetadata(), $slot->count - $item->count);
}
}else{
if($this->removeItem($item->getID(), $item->getMetadata(), $item->count) === false and $this->itemEnforcement === true){
if($this->removeItem($item->getID(), $item->getMetadata(), $item->count) === false){
break;
}
$this->addItem($slot->getID(), $slot->getMetadata(), $slot->count);
@ -1396,6 +1534,12 @@ class Player{
console("[DEBUG] Unhandled 0x".dechex($data["id"])." Data Packet for Client ID ".$this->clientID.": ".print_r($data, true), true, true, 2);
break;
}
if(isset($this->queue[$this->counter[1] + 1])){
$d = $this->queue[$this->counter[1] + 1];
unset($this->queue[$this->counter[1] + 1]);
$this->handle($d["pid"], $d);
}
break;
}
}
@ -1406,58 +1550,11 @@ class Player{
}
public function sendInventory(){
/*
//OLD WAY
foreach($this->inventory as $s => $data){
if($data[0] > 0 and $data[2] >= 0){
$e = $this->server->api->entity->add(ENTITY_ITEM, $data[0], array(
"x" => $this->entity->x + 0.5,
"y" => $this->entity->y + 0.19,
"z" => $this->entity->z + 0.5,
"meta" => $data[1],
"stack" => $data[2],
));
$e->spawn($this);
}
$this->inventory[$s] = array(AIR, 0, 0);
}*/
$inv = array();
foreach($this->inventory as $s => $data){
if($data[0] > AIR and $data[2] >= 0){
$inv[] = BlockAPI::getItem($data[0], $data[1], $data[2]);
}else{
$inv[] = BlockAPI::getItem(AIR, 0, 0);
$this->inventory[$s] = array(AIR, 0, 0);
}
}
$this->dataPacket(MC_CONTAINER_SET_CONTENT, array(
"windowid" => 0,
"count" => count($inv),
"slots" => $inv
"count" => count($this->inventory),
"slots" => $this->inventory
));
/*
//Future
$inv = array();
foreach($this->inventory as $s => $data){
if($data[0] > 0 and $data[2] >= 0){
$inv[] = BlockAPI::getItem($data[0], $data[1], $data[2]);
}else{
$inv[] = BlockAPI::getItem(AIR, 0, 0);
$this->inventory[$s] = array(AIR, 0, 0);
}
}
$this->dataPacket(MC_SEND_INVENTORY, array(
"eid" => 0,
"windowid" => 0,
"slots" => $inv,
"armor" => array(
0 => BlockAPI::getItem($this->armor[0][0], $this->armor[0][1], $this->armor[0][2], $this->armor[0][3]),
1 => BlockAPI::getItem($this->armor[1][0], $this->armor[1][1], $this->armor[1][2], $this->armor[1][3]),
2 => BlockAPI::getItem($this->armor[2][0], $this->armor[2][1], $this->armor[2][2], $this->armor[2][3]),
3 => BlockAPI::getItem($this->armor[3][0], $this->armor[3][1], $this->armor[3][2], $this->armor[3][3]),
),
));
*/
}
public function send($pid, $data = array(), $raw = false){

View File

@ -123,6 +123,7 @@ class PocketMinecraftServer{
$this->query("CREATE TABLE actions (ID INTEGER PRIMARY KEY, interval NUMERIC, last NUMERIC, code TEXT, repeat NUMERIC);");
$this->query("CREATE TABLE handlers (ID INTEGER PRIMARY KEY, name TEXT, priority NUMERIC);");
$this->query("CREATE TABLE blockUpdates (level TEXT, x INTEGER, y INTEGER, z INTEGER, type INTEGER, delay NUMERIC);");
$this->query("CREATE TABLE recipes (id INTEGER PRIMARY KEY, type NUMERIC, recipe TEXT);");
//$this->query("PRAGMA synchronous = OFF;");
$this->preparedSQL->selectHandlers = $this->database->prepare("SELECT DISTINCT ID FROM handlers WHERE name = :name ORDER BY priority DESC;");
$this->preparedSQL->selectActions = $this->database->prepare("SELECT ID,code,repeat FROM actions WHERE last <= (:time - interval);");

View File

@ -66,9 +66,7 @@ ini_set("memory_limit", "128M"); //Default
define("LOG", true);
define("START_TIME", microtime(true));
define("MAJOR_VERSION", "Alpha_1.3.1dev");
define("CURRENT_STRUCTURE", 5);
define("CURRENT_PROTOCOL", 9);
define("CURRENT_MINECRAFT_VERSION", "0.6.1 alpha");
define("CURRENT_MINECRAFT_VERSION", "0.7.0 alpha");
define("CURRENT_API_VERSION", 8);
define("CURRENT_PHP_VERSION", "5.5");
$gitsha1 = false;

View File

@ -150,6 +150,7 @@ define("BRICK_STAIRS", 108);
define("STONE_BRICK_STAIRS", 109);
define("NETHER_BRICKS", 112);
define("NETHER_BRICK_BLOCK", 112);
define("NETHER_BRICKS_STAIRS", 114);

View File

@ -37,6 +37,9 @@ define("VIEWER", 3);
define("PLAYER_RECOVERY_BUFFER", 2048);
define("PLAYER_MAX_PACKET_LOSS", 0.20);
define("PLAYER_SURVIVAL_SLOTS", 36);
define("PLAYER_CREATIVE_SLOTS", 111);
//Block Updates
define("BLOCK_UPDATE_NORMAL", 1);

View File

@ -50,12 +50,17 @@ define("DIAMOND_SHOVEL", 277);
define("DIAMOND_PICKAXE", 278);
define("DIAMOND_AXE", 279);
define("STICK", 280);//Implemented
define("STICKS", 280);
define("BOWL", 281);//Implemented
define("MUSHROOM_STEW", 282);
define("GOLD_SWORD", 283);
define("GOLD_SHOVEL", 284);
define("GOLD_PICKAXE", 285);
define("GOLD_AXE", 286);
define("GOLDEN_SWORD", 283);
define("GOLDEN_SHOVEL", 284);
define("GOLDEN_PICKAXE", 285);
define("GOLDEN_AXE", 286);
define("STRING", 287);
define("FEATHER", 288);//Implemented
define("GUNPOWDER", 289);
@ -64,6 +69,7 @@ define("STONE_HOE", 291);
define("IRON_HOE", 292);//Implemented
define("DIAMOND_HOE", 293);
define("GOLD_HOE", 294);
define("GOLDEN_HOE", 294);
define("SEEDS", 295);
define("WHEAT_SEEDS", 295);
define("WHEAT", 296);
@ -74,19 +80,19 @@ define("LEATHER_PANTS", 300);
define("LEATHER_BOOTS", 301);
define("CHAIN_HELMET", 302);
define("CHAIN_CHESTPLATE", 303);
define("CHAIN_LEGGINS", 304);
define("CHAIN_LEGGINGS", 304);
define("CHAIN_BOOTS", 305);
define("IRON_HELMET", 306);
define("IRON_CHESTPLATE", 307);
define("IRON_LEGGINS", 308);
define("IRON_LEGGINGS", 308);
define("IRON_BOOTS", 309);
define("DIAMOND_HELMET", 310);
define("DIAMOND_CHESTPLATE", 311);
define("DIAMOND_LEGGINS", 312);
define("DIAMOND_LEGGINGS", 312);
define("DIAMOND_BOOTS", 313);
define("GOLD_HELMET", 314);
define("GOLD_CHESTPLATE", 315);
define("GOLD_LEGGINS", 316);
define("GOLD_LEGGINGS", 316);
define("GOLD_BOOTS", 317);
define("FLINT", 318);
define("RAW_PORKCHOP", 319);
@ -96,8 +102,6 @@ define("GOLDEN_APPLE", 322);
define("SIGN", 323);
define("WOODEN_DOOR", 324);
define("BUCKET", 325);
define("WATER_BUCKET", 326);
define("LAVA_BUCKET", 327);
define("IRON_DOOR", 330);
@ -142,6 +146,8 @@ define("COOKED_BEEF", 364);
define("RAW_CHICKEN", 365);
define("COOKED_CHICKEN", 366);
define("SPAWN_EGG", 383);
define("NETHER_BRICK", 405);
define("QUARTZ", 406);
define("NETHER_QUARTZ", 406);

View File

@ -25,6 +25,10 @@ the Free Software Foundation, either version 3 of the License, or
*/
define("CURRENT_STRUCTURE", 5);
define("CURRENT_PROTOCOL", 11);
define("RAKNET_MAGIC", "\x00\xff\xff\x00\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\x12\x34\x56\x78");
define("MC_PING", 0x00);
@ -78,21 +82,22 @@ define("MC_PLAYER_ACTION", 0xa3);
define("MC_HURT_ARMOR", 0xa5);
define("MC_SET_ENTITY_DATA", 0xa6);
define("MC_SET_ENTITY_MOTION", 0xa7);
define("MC_SET_HEALTH", 0xa8);
define("MC_SET_SPAWN_POSITION", 0xa9);
define("MC_ANIMATE", 0xaa);
define("MC_RESPAWN", 0xab);
define("MC_SEND_INVENTORY", 0xac);
define("MC_DROP_ITEM", 0xad);
define("MC_CONTAINER_OPEN", 0xae);
define("MC_CONTAINER_CLOSE", 0xaf);
define("MC_CONTAINER_SET_SLOT", 0xb0);
define("MC_CONTAINER_SET_DATA", 0xb1);
define("MC_CONTAINER_SET_CONTENT", 0xb2);
//define("MC_CONTAINER_ACK", 0xb3);
define("MC_CLIENT_MESSAGE", 0xb4);
define("MC_SIGN_UPDATE", 0xb5);
define("MC_ADVENTURE_SETTINGS", 0xb6);
//define("MC_SET_RIDING_PACKET", 0xa8);
define("MC_SET_HEALTH", 0xa9);
define("MC_SET_SPAWN_POSITION", 0xaa);
define("MC_ANIMATE", 0xab);
define("MC_RESPAWN", 0xac);
define("MC_SEND_INVENTORY", 0xad);
define("MC_DROP_ITEM", 0xae);
define("MC_CONTAINER_OPEN", 0xaf);
define("MC_CONTAINER_CLOSE", 0xb0);
define("MC_CONTAINER_SET_SLOT", 0xb1);
define("MC_CONTAINER_SET_DATA", 0xb2);
define("MC_CONTAINER_SET_CONTENT", 0xb3);
//define("MC_CONTAINER_ACK", 0xb4);
define("MC_CLIENT_MESSAGE", 0xb5);
define("MC_SIGN_UPDATE", 0xb6);
define("MC_ADVENTURE_SETTINGS", 0xb7);
class Protocol{

View File

@ -33,8 +33,6 @@ class Item{
SIGN => "SignItem",
WOODEN_DOOR => "WoodenDoorItem",
BUCKET => "BucketItem",
WATER_BUCKET => "WaterBucketItem",
LAVA_BUCKET => "LavaBucketItem",
IRON_DOOR => "IronDoorItem",
CAKE => "CakeItem",
BED => "BedItem",

View File

@ -70,7 +70,7 @@ class BurningFurnaceBlock extends SolidBlock{
return true;
}
$player->windowCnt++;
$player->windowCnt = $id = max(1, $player->windowCnt % 255);
$player->windowCnt = $id = max(2, $player->windowCnt % 255);
$player->windows[$id] = $furnace;
$player->dataPacket(MC_CONTAINER_OPEN, array(
"windowid" => $id,

View File

@ -88,7 +88,7 @@ class ChestBlock extends TransparentBlock{
return true;
}
$player->windowCnt++;
$player->windowCnt = $id = max(1, $player->windowCnt % 255);
$player->windowCnt = $id = max(2, $player->windowCnt % 255);
$player->windows[$id] = $chest;
$player->dataPacket(MC_CONTAINER_OPEN, array(
"windowid" => $id,

View File

@ -31,6 +31,11 @@ class StonecutterBlock extends SolidBlock{
$this->isActivable = true;
}
public function onActivate(Item $item, Player $player){
$player->toCraft[-1] = 2;
return true;
}
public function getDrops(Item $item, Player $player){
return array(
array($this->id, 0, 1),

View File

@ -31,6 +31,11 @@ class WorkbenchBlock extends SolidBlock{
$this->isActivable = true;
}
public function onActivate(Item $item, Player $player){
$player->toCraft[-1] = 1;
return true;
}
public function getDrops(Item $item, Player $player){
return array(
array($this->id, 0, 1),

View File

@ -27,17 +27,31 @@ the Free Software Foundation, either version 3 of the License, or
class BucketItem extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(BUCKET, 0, $count, "Empty Bucket");
parent::__construct(BUCKET, 0, $count, "Bucket");
$this->meta = $meta;
$this->isActivable = true;
$this->maxStackSize = 1;
}
public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($target->getID() === STILL_WATER or $target->getID() === STILL_LAVA){
$level->setBlock($target, new AirBlock());
$player->removeItem($this->getID(), $this->getMetadata(), $this->count);
$player->addItem(($target->getID() === STILL_LAVA ? LAVA_BUCKET:WATER_BUCKET), 0, 1);
return true;
if($this->meta === AIR){
if($block->getID() === STILL_WATER or $block->getID() === STILL_LAVA){
$level->setBlock($block, new AirBlock());
$this->meta = $block->getID();
return true;
}
}elseif($this->meta === STILL_WATER){
if($block->getID() === AIR){
$level->setBlock($block, new StillWaterBLock());
$this->meta = 0;
return true;
}
}elseif($this->meta === STILL_LAVA){
if($block->getID() === AIR){
$level->setBlock($block, new StillLavaBlock());
$this->meta = 0;
return true;
}
}
return false;
}

View File

@ -28,7 +28,7 @@ the Free Software Foundation, either version 3 of the License, or
class CoalItem extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(COAL, $meta & 0x01, $count, "Coal");
if($this->metadata === 1){
if($this->meta === 1){
$this->name = "Charcoal";
}
}

View File

@ -1,44 +0,0 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
class LavaBucketItem extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(LAVA_BUCKET, 0, $count, "Lava Bucket");
$this->isActivable = true;
$this->maxStackSize = 1;
}
public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($target->getID() === AIR){
$level->setBlock($target, new StillLavaBlock());
$player->removeItem($this->getID(), $this->getMetadata(), $this->count);
$player->addItem(BUCKET, 0, 1);
return true;
}
return false;
}
}

View File

@ -1,44 +0,0 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
class WaterBucketItem extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(WATER_BUCKET, 0, $count, "Water Bucket");
$this->isActivable = true;
$this->maxStackSize = 1;
}
public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($target->getID() === AIR){
$level->setBlock($target, new StillWaterBLock());
$player->removeItem($this->getID(), $this->getMetadata(), $this->count);
$player->addItem(BUCKET, 0, 1);
return true;
}
return false;
}
}

View File

@ -159,9 +159,14 @@ class CustomPacketHandler{
$this->data["username"] = $this->get(Utils::readShort($this->get(2), false));
$this->data["protocol1"] = Utils::readInt($this->get(4));
$this->data["protocol2"] = Utils::readInt($this->get(4));
$this->data["unknown1"] = Utils::readInt($this->get(4));
$this->data["unknown2"] = $this->get(Utils::readShort($this->get(2), false));
}else{
$this->raw .= Utils::writeShort(strlen($this->data["username"])).$this->data["username"];
$this->raw .= Utils::writeInt(CURRENT_PROTOCOL).Utils::writeInt(CURRENT_PROTOCOL);
$this->raw .= Utils::writeInt(CURRENT_PROTOCOL).
Utils::writeInt(CURRENT_PROTOCOL).
Utils::writeInt($this->data["unknown1"]);
$this->raw .= Utils::writeShort(strlen($this->data["unknown2"])).$this->data["unknown2"];
}
break;
case MC_LOGIN_STATUS:
@ -187,9 +192,9 @@ class CustomPacketHandler{
break;
case MC_SET_TIME:
if($this->c === false){
$this->data["time"] = Utils::readInt($this->get(4));
$this->data["time"] = Utils::readLong($this->get(4));
}else{
$this->raw .= Utils::writeInt($this->data["time"]);
$this->raw .= Utils::writeLong($this->data["time"]);
}
break;
case MC_START_GAME:
@ -509,10 +514,12 @@ class CustomPacketHandler{
$this->data["eid"] = Utils::readInt($this->get(4));
$this->data["block"] = Utils::readShort($this->get(2), false);
$this->data["meta"] = Utils::readShort($this->get(2), false);
$this->data["slot"] = ord($this->get(1));
}else{
$this->raw .= Utils::writeInt($this->data["eid"]);
$this->raw .= Utils::writeShort($this->data["block"]);
$this->raw .= Utils::writeShort($this->data["meta"]);
$this->raw .= chr($this->data["slot"]);
}
break;
case MC_PLAYER_ARMOR_EQUIPMENT:
@ -553,6 +560,9 @@ class CustomPacketHandler{
$this->data["fx"] = Utils::readFloat($this->get(4));
$this->data["fy"] = Utils::readFloat($this->get(4));
$this->data["fz"] = Utils::readFloat($this->get(4));
$this->data["posX"] = Utils::readFloat($this->get(4));
$this->data["posY"] = Utils::readFloat($this->get(4));
$this->data["posZ"] = Utils::readFloat($this->get(4));
}else{
$this->raw .= Utils::writeInt($this->data["x"]);
$this->raw .= Utils::writeInt($this->data["y"]);
@ -564,6 +574,9 @@ class CustomPacketHandler{
$this->raw .= Utils::writeFloat($this->data["fx"]);
$this->raw .= Utils::writeFloat($this->data["fy"]);
$this->raw .= Utils::writeFloat($this->data["fz"]);
$this->raw .= Utils::writeFloat($this->data["posX"]);
$this->raw .= Utils::writeFloat($this->data["posY"]);
$this->raw .= Utils::writeFloat($this->data["posZ"]);
}
break;
case MC_PLAYER_ACTION:

View File

@ -0,0 +1,289 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
class CraftingRecipes{
private static $small = array(
//Building
"CLAY:?x4=>CLAY_BLOCK:0x1",
"WOODEN_PLANKS:?x4=>WORKBENCH:0x1",
"GLOWSTONE_DUST:?x4=>GLOWSTONE_BLOCK:0x1",
"SNOWBALL:?x4=>SNOW_BLOCK:0x1",
"WOODEN_PLANKS:?x2=>STICK:0x4",
"COBBLESTONE:?x4=>STONECUTTER:0x1",
"WOOD:?x1=>WOODEN_PLANKS:0x4",
"WOOL:0x1,DYE:0x1=>WOOL:15x1",
"WOOL:0x1,DYE:1x1=>WOOL:14x1",
"WOOL:0x1,DYE:2x1=>WOOL:13x1",
"WOOL:0x1,DYE:3x1=>WOOL:12x1",
"WOOL:0x1,DYE:4x1=>WOOL:11x1",
"WOOL:0x1,DYE:5x1=>WOOL:10x1",
"WOOL:0x1,DYE:6x1=>WOOL:9x1",
"WOOL:0x1,DYE:7x1=>WOOL:8x1",
"WOOL:0x1,DYE:8x1=>WOOL:7x1",
"WOOL:0x1,DYE:9x1=>WOOL:6x1",
"WOOL:0x1,DYE:10x1=>WOOL:5x1",
"WOOL:0x1,DYE:11x1=>WOOL:4x1",
"WOOL:0x1,DYE:12x1=>WOOL:3x1",
"WOOL:0x1,DYE:13x1=>WOOL:2x1",
"WOOL:0x1,DYE:14x1=>WOOL:1x1",
"STRING:?x4=>WOOL:0x1",
//Tools
"IRON_INGOT:?x1,FLINT:?x1=>FLINT_STEEL:0x1",
"IRON_INGOT:?x2=>SHEARS:0x1",
"COAL:0x1,STICK:?x1=>TORCH:0x4",
"COAL:1x1,STICK:?x1=>TORCH:0x4",
//Food & protection
"BROWN_MUSHROOM:?x1,RED_MUSHROOM:?x1,BOWL:?x1=>MUSHROOM_STEW:0x1",
"SUGARCANE:?x1=>SUGAR:0x1",
"MELON_SLICE:?x1=>MELON_SEEDS:0x1",
//Items
"DIAMOND_BLOCK:?x1=>DIAMOND:0x9",
"GOLD_BLOCK:?x1=>GOLD_INGOT:0x9",
"IRON_BLOCK:?x1=>IRON_INGOT:0x9",
"LAPIS_BLOCK:?x1=>DYE:4x9",
"DANDELION:?x1=>DYE:11x2",
"BONE:?x1=>DYE:15x3",
"DYE:1x1,DYE:15x1=>DYE:9x2",
"DYE:1x1,DYE:11x1=>DYE:14x2",
"DYE:2x1,DYE:15x1=>DYE:10x2",
"DYE:4x1,DYE:15x1=>DYE:12x2",
"DYE:2x1,DYE:4x1=>DYE:6x2",
"DYE:1x1,DYE:4x1=>DYE:5x2",
"DYE:1x1,DYE:4x1,DYE:15x1=>DYE:13x3",
"DYE:15x1,DYE:1x2,DYE:4x1=>DYE:13x4",//
"DYE:5x1,DYE:9x1=>DYE:13x2",//
"DYE:0x1,DYE:15x1=>DYE:8x2",//
"DYE:0x1,DYE:15x2=>DYE:7x3",//
"DYE:0x1,DYE:8x1=>DYE:7x2",//
);
private static $big = array(
//Building
"WOOL:?x3,WOODEN_PLANKS:?x3=>BED:0x1",
"WOODEN_PLANKS:?x8=>CHEST:0x1",
"STICK:?x6=>FENCE:0x2",
"STICK:?x4,WOODEN_PLANKS:?x2=>FENCE_GATE:0x1",
"COBBLESTONE:?x8=>FURNACE:0x1",
"GLASS:?x6=>GLASS_PANE:0x16",
"STICK:?x7=>LADDER:0x2",
"DIAMOND:?x3,IRON_INGOT:?x6=>NETHER_REACTOR:0x1",
"WOODEN_PLANKS:?x6=>TRAPDOOR:0x2",
"WOODEN_PLANKS:?x6=>WOODEN_DOOR:0x1",
"WOODEN_PLANKS:?x6=>WOODEN_STAIRS:0x4",
"WOODEN_PLANKS:?x3=>SLAB:2x6",
//Tools
"STICK:?x1,FEATHER:?x1,FLINT:?x1=>ARROW:0x4",
"STICK:?x3,STRING:?x3=>BOW:0x1",
"IRON_INGOT:?x3=>BUCKET:0x1",
"DIAMOND:?x3,STICK:?x2=>DIAMOND_AXE:0x1",
"DIAMOND:?x2,STICK:?x2=>DIAMOND_HOE:0x1",
"DIAMOND:?x3,STICK:?x2=>DIAMOND_PICKAXE:0x1",
"DIAMOND:?x1,STICK:?x2=>DIAMOND_SHOVEL:0x1",
"DIAMOND:?x2,STICK:?x1=>DIAMOND_SWORD:0x1",
"GOLD_INGOT:?x3,STICK:?x2=>GOLD_AXE:0x1",
"GOLD_INGOT:?x2,STICK:?x2=>GOLD_HOE:0x1",
"GOLD_INGOT:?x3,STICK:?x2=>GOLD_PICKAXE:0x1",
"GOLD_INGOT:?x1,STICK:?x2=>GOLD_SHOVEL:0x1",
"GOLD_INGOT:?x2,STICK:?x1=>GOLD_SWORD:0x1",
"IRON_INGOT:?x3,STICK:?x2=>IRON_AXE:0x1",
"IRON_INGOT:?x2,STICK:?x2=>IRON_HOE:0x1",
"IRON_INGOT:?x3,STICK:?x2=>IRON_PICKAXE:0x1",
"IRON_INGOT:?x1,STICK:?x2=>IRON_SHOVEL:0x1",
"IRON_INGOT:?x2,STICK:?x1=>IRON_SWORD:0x1",
"COBBLESTONE:?x3,STICK:?x2=>STONE_AXE:0x1",
"COBBLESTONE:?x2,STICK:?x2=>STONE_HOE:0x1",
"COBBLESTONE:?x3,STICK:?x2=>STONE_PICKAXE:0x1",
"COBBLESTONE:?x1,STICK:?x2=>STONE_SHOVEL:0x1",
"COBBLESTONE:?x2,STICK:?x1=>STONE_SWORD:0x1",
"SAND:?x4,GUNPOWDER:?x5=>TNT:0x1",
"WOODEN_PLANKS:?x3,STICK:?x2=>WOODEN_AXE:0x1",
"WOODEN_PLANKS:?x2,STICK:?x2=>WOODEN_HOE:0x1",
"WOODEN_PLANKS:?x3,STICK:?x2=>WOODEN_PICKAXE:0x1",
"WOODEN_PLANKS:?x1,STICK:?x2=>WOODEN_SHOVEL:0x1",
"WOODEN_PLANKS:?x2,STICK:?x1=>WOODEN_SWORD:0x1",
//Food & protection
"WEATH:?x3=>BREAD:0x1",
"WHEATH:?x3,BUCKET:1x3,EGG:?x1,SUGAR:?x2=>CAKE:0x1",
"DIAMOND:?x4=>DIAMOND_BOOTS:0x1",
"DIAMOND:?x8=>DIAMOND_CHESTPLATE:0x1",
"DIAMOND:?x5=>DIAMOND_HELMET:0x1",
"DIAMOND:?x8=>DIAMOND_LEGGINGS:0x1",
"GOLD_INGOT:?x4=>GOLD_BOOTS:0x1",
"GOLD_INGOT:?x8=>GOLD_CHESTPLATE:0x1",
"GOLD_INGOT:?x5=>GOLD_HELMET:0x1",
"GOLD_INGOT:?x8=>GOLD_LEGGINGS:0x1",
"IRON_INGOT:?x4=>IRON_BOOTS:0x1",
"IRON_INGOT:?x8=>IRON_CHESTPLATE:0x1",
"IRON_INGOT:?x5=>IRON_HELMET:0x1",
"IRON_INGOT:?x8=>IRON_LEGGINGS:0x1",
"LEATHER:?x4=>LEATHER_BOOTS:0x1",
"LEATHER:?x8=>LEATHER_TUNIC:0x1",
"LEATHER:?x5=>LEATHER_CAP:0x1",
"LEATHER:?x8=>LEATHER_PANTS:0x1",
"FIRE:?x4=>CHAIN_BOOTS:0x1",
"FIRE:?x8=>CHAIN_CHESTPLATE:0x1",
"FIRE:?x5=>CHAIN_HELMET:0x1",
"FIRE:?x8=>CHAIN_LEGGINGS:0x1",
//Items
"DIAMOND:?x9=>DIAMOND_BLOCK:0x1",
"GOLD_INGOT:?x9=>GOLD_BLOCK:0x1",
"IRON_INGOT:?x9=>IRON_BLOCK:0x1",
"PAPER:?x3=>BOOK:0x1",
"WOODEN_PLANKS:?x6,BOOK:?x3=>BOOKSHELF:0x1",
"DYE:4x9=>LAPIS_BLOCK:0x1",
"WOOL:?x1,STICK:?x8=>PAINTING:0x1",
"SUGARCANE:?x3=>PAPER:0x1",
"WOODEN_PLANKS:?x6,STICK:?x1=>SIGN:0x1",
);
private static $stone = array(
"QUARTZ:?x4=>QUARTZ_BLOCK:0x1",
"BRICKS_BLOCK:?x6=>BRICK_STAIRS:0x4",
"BRICK:?x4=>BRICKS_BLOCK:0x1",
"NETHER_BRICK:?x4=>NETHER_BRICKS:0x1",
"NETHER_BRICKS:?x6=>NETHER_BRICK_STAIRS:0x4",
"SAND:?x4=>SANDSTONE:0x1",
"SANDSTONE:0x4=>SANDSTONE:2x1",
"SLAB:1x2=>SANDSTONE:1x1",
"STONE_BRICK:?x6=>STONE_BRICK_STAIRS:0x4",
"STONE:?x4=>STONE_BRICK:0x1",
"COBBLESTONE:?x6=>COBBLESTONE_STAIRS:0x4",
"COBBLESTONE:?x3=>SLAB:3x6",
"STONE:?x3=>SLAB:0x6",
"SANDSTONE:2x3=>SLAB:1x6",
"BRICKS_BLOCK:?x3=>SLAB:4x6",
"STONE_BRICKS:?x3=>SLAB:5x6",
);
private static $recipes = array();
private static function parseRecipe($recipe){
$recipe = explode("=>", $recipe);
$recipeItems = array();
foreach(explode(",", $recipe[0]) as $item){
$item = explode("x", $item);
$id = explode(":", $item[0]);
$meta = array_pop($id);
$id = $id[0];
$it = BlockAPI::fromString($id);
$recipeItems[$it->getID()] = array($it->getID(), $meta === "?" ? false:intval($meta)&0xFFFF, intval($item[1]));
}
ksort($recipeItems);
$item = explode("x", $recipe[1]);
$id = explode(":", $item[0]);
$meta = array_pop($id);
$id = $id[0];
$it = BlockAPI::fromString($id);
$craftItem = array($it->getID(), intval($meta)&0xFFFF, intval($item[1]));
$recipeString = "";
foreach($recipeItems as $item){
$recipeString .= $item[0]."x".$item[2].",";
}
$recipeString = substr($recipeString, 0, -1)."=>".$craftItem[0]."x".$craftItem[2];
return array($recipeItems, $craftItem, $recipeString);
}
public static function init(){
$server = ServerAPI::request();
$id = 1;
foreach(CraftingRecipes::$small as $recipe){
$recipe = CraftingRecipes::parseRecipe($recipe);
$recipe[3] = 0; //Type
CraftingRecipes::$recipes[$id] = $recipe;
++$id;
}
foreach(CraftingRecipes::$big as $recipe){
$recipe = CraftingRecipes::parseRecipe($recipe);
$recipe[3] = 1;
CraftingRecipes::$recipes[$id] = $recipe;
++$id;
}
foreach(CraftingRecipes::$stone as $recipe){
$recipe = CraftingRecipes::parseRecipe($recipe);
$recipe[3] = 2;
CraftingRecipes::$recipes[$id] = $recipe;
++$id;
}
foreach(CraftingRecipes::$recipes as $id => $recipe){
$server->query("INSERT INTO recipes (id, type, recipe) VALUES (".$id.", ".$recipe[3].", '".$recipe[2]."');");
}
}
public static function canCraft(array $craftItem, array $recipeItems, $type){
ksort($recipeItems);
$recipeString = "";
foreach($recipeItems as $item){
$recipeString .= $item[0]."x".$item[2].",";
}
$recipeString = substr($recipeString, 0, -1)."=>".$craftItem[0]."x".$craftItem[2];
$server = ServerAPI::request();
$result = $server->query("SELECT id FROM recipes WHERE type == ".$type." AND recipe == '".$recipeString."';");
if($result instanceof SQLite3Result){
$continue = true;
while(($r = $result->fetchArray(SQLITE3_NUM)) !== false){
$continue = true;
$recipe = CraftingRecipes::$recipes[$r[0]];
foreach($recipe[0] as $item){
if(!isset($recipeItems[$item[0]])){
$continue = false;
break;
}
$oitem = $recipeItems[$item[0]];
if(($oitem[1] != $item[1] and $item[2] !== false) or $oitem[2] != $item[2]){
$continue = false;
break;
}
}
if($continue === false or $craftItem[0] != $recipe[1][0] or $recipe[1][1] != $recipe[1][1] or $recipe[1][2] != $recipe[1][2]){
$continue = false;
continue;
}
$continue = $recipe;
break;
}
}else{
return true;
}
return $continue;
}
}

View File

@ -41,6 +41,7 @@ class SmeltingData{
RED_MUSHROOM => array(DYE, 1),
RAW_BEEF => array(STEAK, 0),
RAW_CHICKEN => array(COOKED_CHICKEN, 0),
RED_MUSHROOM => array(DYE, 1),
);
}

View File

@ -143,10 +143,10 @@ class Entity extends Position{
}
public function getDrops(){
if($this->class === ENTITY_PLAYER){
if($this->class === ENTITY_PLAYER and ($this->player->gamemode & 0x00) === 0){
$inv = array();
$air = BlockAPI::getItem(AIR, 0, 0);
for($i = 0; $i < 36; ++$i){
for($i = 0; $i < PLAYER_SURVIVAL_SLOTS; ++$i){
$slot = $this->player->getSlot($i);
$this->player->setSlot($i, $air);
if($slot->getID() !== AIR and $slot->count > 0){
@ -562,8 +562,9 @@ class Entity extends Position{
));
$player->dataPacket(MC_PLAYER_EQUIPMENT, array(
"eid" => $this->eid,
"block" => $this->player->equipment->getID(),
"meta" => $this->player->equipment->getMetadata(),
"block" => $this->player->getSlot($this->player->slot)->getID(),
"meta" => $this->player->getSlot($this->player->slot)->getMetadata(),
"slot" => 0,
));
break;
case ENTITY_ITEM:
@ -799,19 +800,19 @@ class Entity extends Position{
LEATHER_BOOTS => 1,
CHAIN_HELMET => 1,
CHAIN_CHESTPLATE => 5,
CHAIN_LEGGINS => 4,
CHAIN_LEGGINGS => 4,
CHAIN_BOOTS => 1,
GOLD_HELMET => 1,
GOLD_CHESTPLATE => 5,
GOLD_LEGGINS => 3,
GOLD_LEGGINGS => 3,
GOLD_BOOTS => 1,
IRON_HELMET => 2,
IRON_CHESTPLATE => 6,
IRON_LEGGINS => 5,
IRON_LEGGINGS => 5,
IRON_BOOTS => 2,
DIAMOND_HELMET => 3,
DIAMOND_CHESTPLATE => 8,
DIAMOND_LEGGINS => 6,
DIAMOND_LEGGINGS => 6,
DIAMOND_BOOTS => 3,
);
foreach($this->player->armor as $part){