Furnaces and Burning items

This commit is contained in:
Shoghi Cervantes 2013-05-25 19:06:31 +02:00
parent 221da1685e
commit f224c26084
10 changed files with 253 additions and 16 deletions

View File

@ -365,7 +365,26 @@ class Player{
public function eventHandler($data, $event){
switch($event){
case "tile.update":
if($data->level === $this->level and $data->class === TILE_FURNACE){
foreach($this->windows as $id => $w){
if($w === $data){
$this->dataPacket(MC_CONTAINER_SET_DATA, array(
"windowid" => $id,
"property" => 0, //Smelting
"value" => floor($data->data["CookTime"]),
));
$this->dataPacket(MC_CONTAINER_SET_DATA, array(
"windowid" => $id,
"property" => 1, //Fire icon
"value" => $data->data["BurnTicks"],
));
}
}
}
break;
case "tile.container.slot":
if($data["tile"]->level === $this->level){
foreach($this->windows as $id => $w){
if($w === $data["tile"]){
$this->dataPacket(MC_CONTAINER_SET_SLOT, array(
@ -377,6 +396,7 @@ class Player{
));
}
}
}
break;
case "player.armor":
if($data["eid"] === $this->eid){
@ -924,6 +944,7 @@ class Player{
$this->evid[] = $this->server->event("player.armor", 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"));
$this->server->schedule(40, array($this, "measureLag"), array(), true);
console("[INFO] \x1b[33m".$this->username."\x1b[0m[/".$this->ip.":".$this->port."] logged in with entity id ".$this->eid." at (".$this->entity->level->getName().", ".round($this->entity->x, 2).", ".round($this->entity->y, 2).", ".round($this->entity->z, 2).")");
break;

View File

@ -87,7 +87,7 @@ 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_DATA", 0xb1);
define("MC_CONTAINER_SET_CONTENT", 0xb2);
//define("MC_CONTAINER_ACK", 0xb3);
define("MC_CLIENT_MESSAGE", 0xb4);

View File

@ -105,6 +105,30 @@ class Item{
return $this->maxStackSize;
}
final public function getFuelTime(){
if(!isset(FuelData::$duration[$this->id])){
return false;
}
return FuelData::$duration[$this->id];
}
final public function getSmeltItem(){
if(!isset(SmeltingData::$product[$this->id])){
return false;
}
if(isset(SmeltingData::$product[$this->id][0]) and !is_array(SmeltingData::$product[$this->id][0])){
return BlockAPI::getItem(SmeltingData::$product[$this->id][0], SmeltingData::$product[$this->id][1]);
}
if(!isset(SmeltingData::$product[$this->id][$this->meta])){
return false;
}
return BlockAPI::getItem(SmeltingData::$product[$this->id][$this->meta][0], SmeltingData::$product[$this->id][$this->meta][1]);
}
final public function isPickaxe(){ //Returns false or level of the pickaxe
switch($this->id){
case IRON_PICKAXE:

View File

@ -96,10 +96,12 @@ class BurningFurnaceBlock extends SolidBlock{
"title" => "Furnace",
));
$slots = array();
for($s = 0; $s < FURNACE_SLOTS; ++$s){
for($s = 0; $s <= FURNACE_SLOTS; ++$s){
$slot = $furnace->getSlot($s);
if($slot->getID() > 0 and $slot->count > 0){
$slots[] = $slot;
}else{
$slots[] = BlockAPI::getItem(AIR, 0, 0);
}
}
$player->dataPacket(MC_CONTAINER_SET_CONTENT, array(

View File

@ -113,10 +113,12 @@ class ChestBlock extends TransparentBlock{
"title" => "Chest",
));
$slots = array();
for($s = 0; $s < CHEST_SLOTS; ++$s){
for($s = 0; $s <= CHEST_SLOTS; ++$s){
$slot = $chest->getSlot($s);
if($slot->getID() > 0 and $slot->count > 0){
$slots[] = $slot;
}else{
$slots[] = BlockAPI::getItem(AIR, 0, 0);
}
}
$player->dataPacket(MC_CONTAINER_SET_CONTENT, array(

View File

@ -27,7 +27,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, 0, $count, "Coal");
parent::__construct(COAL, $meta & 0x01, $count, "Coal");
}
}

View File

@ -718,6 +718,17 @@ class CustomPacketHandler{
}
}
break;
case MC_CONTAINER_SET_DATA:
if($this->c === false){
$this->data["windowid"] = ord($this->get(1));
$this->data["property"] = Utils::readShort($this->get(2));
$this->data["value"] = Utils::readShort($this->get(2));
}else{
$this->raw .= chr($this->data["windowid"]);
$this->raw .= Utils::writeShort($this->data["property"]);
$this->raw .= Utils::writeShort($this->data["value"]);
}
break;
case MC_CLIENT_MESSAGE:
if($this->c === false){
$this->data["message"] = $this->get(Utils::readShort($this->get(2), false));

52
src/recipes/FuelData.php Normal file
View File

@ -0,0 +1,52 @@
<?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 FuelData{
public static $duration = array(
COAL => 80,
TRUNK => 15,
WOODEN_PLANKS => 15,
SAPLING => 5,
WOODEN_AXE => 10,
WOODEN_PICKAXE => 10,
WOODEN_SWORD => 10,
WOODEN_SHOVEL => 10,
WOODEN_HOE => 10,
STICK => 5,
FENCE => 15,
FENCE_GATE => 15,
WOODEN_STAIRS => 15,
TRAPDOOR => 15,
WORKBENCH => 15,
BOOKSHELF => 15,
CHEST => 15,
LAVA_BUCKET => 1000,
);
}

View File

@ -0,0 +1,46 @@
<?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 SmeltingData{
public static $product = array(
COBBLESTONE => array(STONE, 0),
SAND => array(GLASS, 0),
TRUNK => array(COAL, 1), //Charcoal
GOLD_ORE => array(GOLD_INGOT, 0),
IRON_ORE => array(IRON_INGOT, 0),
NETHERRACK => array(NETHER_BRICK, 0),
RAW_PORKCHOP => array(COOKED_PORKCHOP, 0),
CLAY => array(BRICK, 0),
RAW_FISH => array(COOKED_FISH, 0),
CACTUS => array(DYE, 2),
RED_MUSHROOM => array(DYE, 1),
RAW_BEEF => array(STEAK, 0),
RAW_CHICKEN => array(COOKED_CHICKEN, 0),
);
}

View File

@ -49,6 +49,8 @@ class TileEntity extends Position{
$this->closed = true;
}
$this->name = "";
$this->lastUpdate = microtime(true);
$this->scheduledUpdate = false;
$this->id = (int) $id;
$this->x = (int) $x;
$this->y = (int) $y;
@ -57,7 +59,21 @@ class TileEntity extends Position{
switch($this->class){
case TILE_SIGN:
$this->server->query("UPDATE tileentities SET spawnable = 1 WHERE ID = ".$this->id.";");
break;
case TILE_FURNACE:
if(!isset($this->data["BurnTime"]) or $this->data["BurnTime"] < 0){
$this->data["BurnTime"] = 0;
}
if(!isset($this->data["CookTime"]) or $this->data["CookTime"] < 0 or ($this->data["BurnTime"] === 0 and $this->data["CookTime"] > 0)){
$this->data["CookTime"] = 0;
}
if(!isset($this->data["MaxTime"])){
$this->data["MaxTime"] = $this->data["BurnTime"];
$this->data["BurnTicks"] = 0;
}
if($this->data["BurnTime"] > 0){
$this->update();
}
break;
}
}
@ -66,6 +82,66 @@ class TileEntity extends Position{
if($this->closed === true){
return false;
}
if($this->class === TILE_FURNACE){
$fuel = $this->getSlot(1);
$raw = $this->getSlot(0);
$product = $this->getSlot(2);
$smelt = $raw->getSmeltItem();
$canSmelt = $smelt !== false and $raw->count > 0 and (($product->getID() === $smelt->getID() and $product->getMetadata() === $smelt->getMetadata() and $product->count < $product->getMaxStackSize()) or $product->getID() === AIR);
if($this->data["BurnTime"] <= 0 and $canSmelt and $fuel->getFuelTime() !== false and $fuel->count > 0){
$this->lastUpdate = microtime(true);
$this->data["MaxTime"] = $this->data["BurnTime"] = floor($fuel->getFuelTime() * 20);
$this->data["BurnTicks"] = 0;
--$fuel->count;
if($fuel->count === 0){
$fuel = BlockAPI::getItem(AIR, 0, 0);
}
$this->setSlot(1, $fuel, false);
$current = $this->level->getBlock($this);
if($current->getID() === FURNACE){
$this->level->setBlock($this, BlockAPI::get(BURNING_FURNACE, $current->getMetadata()));
}
}
if($this->data["BurnTime"] > 0){
$ticks = (microtime(true) - $this->lastUpdate) * 20;
$this->data["BurnTime"] -= $ticks;
$this->data["BurnTicks"] = ceil(($this->data["BurnTime"] / $this->data["MaxTime"]) * 200);
if($smelt !== false and $canSmelt){
$this->data["CookTime"] += $ticks;
if($this->data["CookTime"] >= 200){ //10 seconds
$product = BlockAPI::getItem($smelt->getID(), $smelt->getMetadata(), $product->count + 1);
$this->setSlot(2, $product, false);
--$raw->count;
if($raw->count === 0){
$raw = BlockAPI::getItem(AIR, 0, 0);
}
$this->setSlot(0, $raw, false);
$this->data["CookTime"] -= 200;
}
}elseif($this->data["BurnTime"] <= 0){
$this->data["BurnTime"] = 0;
$this->data["CookTime"] = 0;
$this->data["BurnTicks"] = 0;
}else{
$this->data["CookTime"] = 0;
}
$this->server->schedule(2, array($this, "update"));
$this->scheduledUpdate = true;
}else{
$current = $this->level->getBlock($this);
if($current->getID() === BURNING_FURNACE){
$this->level->setBlock($this, BlockAPI::get(FURNACE, $current->getMetadata()));
}
$this->data["CookTime"] = 0;
$this->data["BurnTime"] = 0;
$this->data["BurnTicks"] = 0;
$this->scheduledUpdate = false;
}
}
$this->server->handle("tile.update", $this);
$this->lastUpdate = microtime(true);
}
public function getSlotIndex($s){
@ -89,7 +165,7 @@ class TileEntity extends Position{
}
}
public function setSlot($s, Item $item){
public function setSlot($s, Item $item, $update = true){
$i = $this->getSlotIndex($s);
$d = array(
"Count" => $item->count,
@ -113,7 +189,10 @@ class TileEntity extends Position{
"slot" => $s,
"slotdata" => $item,
));
$this->server->handle("tile.update", $this);
if($update === true and $this->scheduledUpdate === false){
$this->update();
}
return true;
}