Fixed Time, Death and more event issues

This commit is contained in:
Shoghi Cervantes Pueyo 2012-12-19 14:23:34 +01:00
parent 11f4096403
commit a833d92d76
6 changed files with 96 additions and 59 deletions

View File

@ -29,12 +29,39 @@ class EntityAPI{
private $server; private $server;
function __construct($server){ function __construct($server){
$this->server = $server; $this->server = $server;
$this->server->addHandler("onPlayerDeath", array($this, "handle"), 1);
} }
public function init(){ public function init(){
$this->server->api->console->register("give", "Give items to a player", array($this, "commandHandler")); $this->server->api->console->register("give", "Give items to a player", array($this, "commandHandler"));
} }
public function handle($data, $event){
switch($event){
case "onPlayerDeath":
$message = $data["name"];
if(is_numeric($data["cause"]) and isset($this->entities[$data["cause"]])){
$e = $this->api->entity->get($data["cause"]);
switch($e->class){
case ENTITY_PLAYER:
$message .= " was killed by ".$e->name;
break;
default:
$message .= " was killed";
break;
}
}else{
switch($data["cause"]){
default:
$message .= " was killed";
break;
}
}
$this->server->chat(false, $message);
break;
}
}
public function commandHandler($cmd, $params){ public function commandHandler($cmd, $params){
switch($cmd){ switch($cmd){
case "give": case "give":

View File

@ -44,7 +44,7 @@ class PlayerAPI{
case "onHealthRegeneration": case "onHealthRegeneration":
$result = $this->server->query("SELECT ip,port FROM players WHERE EID = (SELECT EID FROM entities WHERE health < 20);", true); $result = $this->server->query("SELECT ip,port FROM players WHERE EID = (SELECT EID FROM entities WHERE health < 20);", true);
if($result !== true and $result !== false){ if($result !== true and $result !== false){
while($player = $result->fetchArray()){ while(false !== ($player = $result->fetchArray())){
$player->entity->setHealth(min(20, $player->entity->getHealth() + $data), "regeneration"); $player->entity->setHealth(min(20, $player->entity->getHealth() + $data), "regeneration");
} }
} }

View File

@ -96,13 +96,13 @@ class TimeAPI{
$this->server->time += (int) $time; $this->server->time += (int) $time;
} }
public function getDate(){ public function getDate($time = false){
$time = $this->get(); $time = $time === false ? $this->get():$time;
return str_pad(strval((floor($time /800) + 6) % 24), 2, "0", STR_PAD_LEFT).":".str_pad(strval(floor(($time % 800) / 13.33)), 2, "0", STR_PAD_LEFT); return str_pad(strval((floor($time /800) + 6) % 24), 2, "0", STR_PAD_LEFT).":".str_pad(strval(floor(($time % 800) / 13.33)), 2, "0", STR_PAD_LEFT);
} }
public function getPhase(){ public function getPhase($time = false){
$time = $this->get(); $time = $time === false ? $this->get():$time;
if($time < $this->phase["sunset"]){ if($time < $this->phase["sunset"]){
$time = "day"; $time = "day";
}elseif($time < $this->phase["night"]){ }elseif($time < $this->phase["night"]){

View File

@ -192,10 +192,10 @@ class Entity extends stdClass{
"health" => $this->health, "health" => $this->health,
)); ));
} }
if($this->health <= 0){ if($this->health <= 0 and $this->dead === false){
$this->dead = true; $this->dead = true;
if($this->player !== false){ if($this->player !== false){
$this->server->trigger("onPlayerDeath", array("name" => $this->name, "cause" => $cause)); $this->server->handle("onPlayerDeath", array("name" => $this->name, "cause" => $cause));
} }
}elseif($this->health > 0){ }elseif($this->health > 0){
$this->dead = false; $this->dead = false;

View File

@ -80,15 +80,13 @@ class PocketMinecraftServer extends stdClass{
public function getTPS(){ public function getTPS(){
$v = array_values($this->tickMeasure); $v = array_values($this->tickMeasure);
$tps = 40/($v[39] - $v[0]); $tps = 40 / ($v[39] - $v[0]);
return round($tps, 4); return round($tps, 4);
} }
public function loadEvents(){ public function loadEvents(){
$this->event("onChat", "eventHandler", true); $this->event("onChat", "eventHandler", true);
$this->event("onPlayerDeath", "eventHandler", true);
$this->event("onPlayerAdd", "eventHandler", true); $this->event("onPlayerAdd", "eventHandler", true);
$this->event("onHealthChange", "eventHandler", true);
$this->action(500000, '$this->time += (int) ($this->timePerSecond / 2);$this->trigger("onTimeChange", $this->time);'); $this->action(500000, '$this->time += (int) ($this->timePerSecond / 2);$this->trigger("onTimeChange", $this->time);');
$this->action(5000000, 'if($this->difficulty < 2){$this->trigger("onHealthRegeneration", 1);}'); $this->action(5000000, 'if($this->difficulty < 2){$this->trigger("onHealthRegeneration", 1);}');
@ -103,19 +101,19 @@ class PocketMinecraftServer extends stdClass{
public function startDatabase(){ public function startDatabase(){
$this->preparedSQL = new stdClass(); $this->preparedSQL = new stdClass();
$this->database = new SQLite3(":memory:"); $this->database = new SQLite3(":memory:");
$this->query("PRAGMA journal_mode = OFF;"); //$this->query("PRAGMA journal_mode = OFF;");
$this->query("PRAGMA encoding = \"UTF-8\";"); //$this->query("PRAGMA encoding = \"UTF-8\";");
$this->query("PRAGMA secure_delete = OFF;"); //$this->query("PRAGMA secure_delete = OFF;");
$this->query("CREATE TABLE players (clientID INTEGER PRIMARY KEY, EID NUMERIC, ip TEXT, port NUMERIC, name TEXT UNIQUE);"); $this->query("CREATE TABLE players (clientID INTEGER PRIMARY KEY, EID NUMERIC, ip TEXT, port NUMERIC, name TEXT UNIQUE);");
$this->query("CREATE TABLE entities (EID INTEGER PRIMARY KEY, type NUMERIC, class NUMERIC, name TEXT, x NUMERIC, y NUMERIC, z NUMERIC, yaw NUMERIC, pitch NUMERIC, health NUMERIC);"); $this->query("CREATE TABLE entities (EID INTEGER PRIMARY KEY, type NUMERIC, class NUMERIC, name TEXT, x NUMERIC, y NUMERIC, z NUMERIC, yaw NUMERIC, pitch NUMERIC, health NUMERIC);");
$this->query("CREATE TABLE metadata (EID INTEGER PRIMARY KEY, name TEXT, value TEXT);"); $this->query("CREATE TABLE metadata (EID INTEGER PRIMARY KEY, name TEXT, value TEXT);");
$this->query("CREATE TABLE actions (ID INTEGER PRIMARY KEY, interval NUMERIC, last NUMERIC, code TEXT, repeat NUMERIC);"); $this->query("CREATE TABLE actions (ID INTEGER PRIMARY KEY, interval NUMERIC, last NUMERIC, code TEXT, repeat NUMERIC);");
$this->query("CREATE TABLE events (ID INTEGER PRIMARY KEY, name TEXT);"); $this->query("CREATE TABLE events (ID INTEGER PRIMARY KEY, name TEXT);");
$this->query("CREATE TABLE handlers (ID INTEGER PRIMARY KEY, name TEXT, priority NUMERIC);"); $this->query("CREATE TABLE handlers (ID INTEGER PRIMARY KEY, name TEXT, priority NUMERIC);");
$this->query("PRAGMA synchronous = OFF;"); //$this->query("PRAGMA synchronous = OFF;");
$this->preparedSQL->selectHandlers = $this->database->prepare("SELECT ID FROM handlers WHERE name = ? ORDER BY priority DESC;"); $this->preparedSQL->selectHandlers = $this->database->prepare("SELECT ID FROM handlers WHERE name = :name ORDER BY priority DESC;");
$this->preparedSQL->selectEvents = $this->database->prepare("SELECT ID FROM events WHERE name = ?;"); $this->preparedSQL->selectEvents = $this->database->prepare("SELECT ID FROM events WHERE name = :name;");
$this->preparedSQL->selectActions = $this->database->prepare("SELECT ID,code,repeat FROM actions WHERE last <= (? - interval);"); $this->preparedSQL->selectActions = $this->database->prepare("SELECT ID,code,repeat FROM actions WHERE last <= (:time - interval);");
$this->preparedSQL->updateActions = $this->database->prepare("UPDATE actions SET last = :time WHERE last <= (:time - interval);"); $this->preparedSQL->updateActions = $this->database->prepare("UPDATE actions SET last = :time WHERE last <= (:time - interval);");
} }
@ -193,43 +191,24 @@ class PocketMinecraftServer extends stdClass{
return $this->handCnt++; return $this->handCnt++;
} }
public function handle($event, &$data){ public function handle($event, $data){
$this->preparedSQL->selectHandlers->reset();
$this->preparedSQL->selectHandlers->clear(); $this->preparedSQL->selectHandlers->clear();
$this->preparedSQL->selectHandlers->bindValue(1, $event, SQLITE3_TEXT); $this->preparedSQL->selectHandlers->bindValue(":name", $event, SQLITE3_TEXT);
$handlers = $this->preparedSQL->selectHandlers->execute(); $handlers = $this->preparedSQL->selectHandlers->execute();
if($handlers === false or $handlers === true){ if($handlers === false or $handlers === true){
return $this->trigger($event, $data); return $this->trigger($event, $data);
} }
while($hn = $handlers->fetchArray(SQLITE3_ASSOC)){ while(false !== ($hn = $handlers->fetchArray(SQLITE3_ASSOC))){
$hnid = (int) $hn["ID"]; $hnid = (int) $hn["ID"];
call_user_func($this->handlers[$hnid], $data, $event); call_user_func($this->handlers[$hnid], $data, $event);
} }
$handlers->finalize();
return true; return true;
} }
public function eventHandler($data, $event){ public function eventHandler($data, $event){
switch($event){ switch($event){
case "onPlayerDeath":
$message = $data["name"];
if(is_numeric($data["cause"]) and isset($this->entities[$data["cause"]])){
$e = $this->api->entity->get($data["cause"]);
switch($e->class){
case ENTITY_PLAYER:
$message .= " was killed by ".$e->name;
break;
default:
$message .= " was killed";
break;
}
}else{
switch($data["cause"]){
default:
$message .= " was killed";
break;
}
}
$this->chat(false, $message);
break;
case "onPlayerAdd": case "onPlayerAdd":
console("[DEBUG] Player \"".$data["username"]."\" EID ".$data["eid"]." spawned at X ".$data["x"]." Y ".$data["y"]." Z ".$data["z"], true, true, 2); console("[DEBUG] Player \"".$data["username"]."\" EID ".$data["eid"]." spawned at X ".$data["x"]." Y ".$data["y"]." Z ".$data["z"], true, true, 2);
break; break;
@ -357,17 +336,29 @@ class PocketMinecraftServer extends stdClass{
$this->custom["times_".$CID] = ($this->custom["times_".$CID] + 1) % strlen($this->description); $this->custom["times_".$CID] = ($this->custom["times_".$CID] + 1) % strlen($this->description);
break; break;
case 0x05: case 0x05:
if(in_array($packet["ip"], $this->bannedIPs)){ if(in_array($packet["ip"], $this->bannedIPs) or count($this->clients) >= $this->maxClients){
break; $this->send(0x80, array(
} 0,
if(count($this->clients) >= $this->maxClients){ 0x00,
array(
"id" => MC_LOGIN_STATUS,
"status" => 1,
),
), false, $packet["ip"], $packet["port"]);
$this->send(0x80, array(
1,
0x00,
array(
"id" => MC_DISCONNECT,
),
), false, $packet["ip"], $packet["port"]);
break; break;
} }
$version = $data[1]; $version = $data[1];
$size = strlen($data[2]); $size = strlen($data[2]);
if($version !== $this->protocol){ if($version !== $this->protocol){
$this->send(0x1a, array( $this->send(0x1a, array(
5, $this->protocol,
MAGIC, MAGIC,
$this->serverID, $this->serverID,
), false, $packet["ip"], $packet["port"]); ), false, $packet["ip"], $packet["port"]);
@ -381,10 +372,22 @@ class PocketMinecraftServer extends stdClass{
} }
break; break;
case 0x07: case 0x07:
if(in_array($packet["ip"], $this->bannedIPs)){ if(in_array($packet["ip"], $this->bannedIPs) or count($this->clients) >= $this->maxClients){
break; $this->send(0x80, array(
} 0,
if(count($this->clients) >= $this->maxClients){ 0x00,
array(
"id" => MC_LOGIN_STATUS,
"status" => 1,
),
), false, $packet["ip"], $packet["port"]);
$this->send(0x80, array(
1,
0x00,
array(
"id" => MC_DISCONNECT,
),
), false, $packet["ip"], $packet["port"]);
break; break;
} }
$port = $data[2]; $port = $data[2];
@ -413,16 +416,18 @@ class PocketMinecraftServer extends stdClass{
} }
public function trigger($event, $data = ""){ public function trigger($event, $data = ""){
$this->preparedSQL->selectEvents->reset();
$this->preparedSQL->selectEvents->clear(); $this->preparedSQL->selectEvents->clear();
$this->preparedSQL->selectEvents->bindValue(1, $event, SQLITE3_TEXT); $this->preparedSQL->selectEvents->bindValue(":name", $event, SQLITE3_TEXT);
$events = $this->preparedSQL->selectEvents->execute(); $events = $this->preparedSQL->selectEvents->execute();
if($events === false or $events === true){ if($events === false or $events === true){
return; return;
} }
while($evn = $events->fetchArray(SQLITE3_ASSOC)){ while(false !== ($evn = $events->fetchArray(SQLITE3_ASSOC))){
$evid = (int) $evn["ID"]; $evid = (int) $evn["ID"];
$this->responses[$evid] = call_user_func($this->events[$evid], $data, $event, $this); $this->responses[$evid] = call_user_func($this->events[$evid], $data, $event, $this);
} }
$events->finalize();
return true; return true;
} }
@ -442,19 +447,22 @@ class PocketMinecraftServer extends stdClass{
public function tickerFunction($time){ public function tickerFunction($time){
//actions that repeat every x time will go here //actions that repeat every x time will go here
$this->preparedSQL->selectActions->reset();
$this->preparedSQL->selectActions->clear(); $this->preparedSQL->selectActions->clear();
$this->preparedSQL->selectActions->bindValue(1, $time, SQLITE3_FLOAT); $this->preparedSQL->selectActions->bindValue(":time", $time, SQLITE3_FLOAT);
$actions = $this->preparedSQL->selectActions->execute(); $actions = $this->preparedSQL->selectActions->execute();
if($actions === false or $actions === true){ if($actions === false or $actions === true){
return; return;
} }
while($action = $actions->fetchArray(SQLITE3_ASSOC)){ while(false !== ($action = $actions->fetchArray(SQLITE3_ASSOC))){
eval($action["code"]); eval($action["code"]);
if($action["repeat"] === 0){ if($action["repeat"] === 0){
$this->query("DELETE FROM actions WHERE ID = ".$action["ID"].";"); $this->query("DELETE FROM actions WHERE ID = ".$action["ID"].";");
} }
} }
$actions->finalize();
$this->preparedSQL->updateActions->reset();
$this->preparedSQL->updateActions->clear(); $this->preparedSQL->updateActions->clear();
$this->preparedSQL->updateActions->bindValue(":time", $time, SQLITE3_FLOAT); $this->preparedSQL->updateActions->bindValue(":time", $time, SQLITE3_FLOAT);
$this->preparedSQL->updateActions->execute(); $this->preparedSQL->updateActions->execute();

View File

@ -28,7 +28,7 @@ the Free Software Foundation, either version 3 of the License, or
class Session{ class Session{
private $server, $timeout, $connected, $evid, $queue, $buffer; private $server, $timeout, $connected, $evid, $queue, $buffer;
var $clientID, $ip, $port, $counter, $username, $eid, $data, $entity, $auth, $CID, $MTU; var $clientID, $ip, $port, $counter, $username, $eid, $data, $entity, $auth, $CID, $MTU, $spawned;
function __construct($server, $clientID, $ip, $port, $MTU){ function __construct($server, $clientID, $ip, $port, $MTU){
$this->queue = array(); $this->queue = array();
$this->buffer = array(); $this->buffer = array();
@ -43,6 +43,7 @@ class Session{
$this->port = $port; $this->port = $port;
$this->timeout = microtime(true) + 25; $this->timeout = microtime(true) + 25;
$this->evid = array(); $this->evid = array();
$this->spawned = false;
$this->evid[] = $this->server->event("onTick", array($this, "onTick")); $this->evid[] = $this->server->event("onTick", array($this, "onTick"));
$this->evid[] = $this->server->event("onClose", array($this, "close")); $this->evid[] = $this->server->event("onClose", array($this, "close"));
console("[DEBUG] New Session started with ".$ip.":".$port.". MTU ".$this->MTU.", Client ID ".$this->clientID, true, true, 2); console("[DEBUG] New Session started with ".$ip.":".$port.". MTU ".$this->MTU.", Client ID ".$this->clientID, true, true, 2);
@ -219,6 +220,7 @@ class Session{
} }
switch($data["id"]){ switch($data["id"]){
case MC_DISCONNECT: case MC_DISCONNECT:
$this->connected = false;
$this->close("client disconnect"); $this->close("client disconnect");
break; break;
case MC_CLIENT_CONNECT: case MC_CLIENT_CONNECT:
@ -263,9 +265,10 @@ class Session{
)); ));
break; break;
case MC_READY: case MC_READY:
if(is_object($this->entity)){ if($this->spawned !== false){
break; break;
} }
$this->spawned = true;
$this->entity = $this->server->api->entity->add(ENTITY_PLAYER, 0, array("player" => $this)); $this->entity = $this->server->api->entity->add(ENTITY_PLAYER, 0, array("player" => $this));
$this->eid = $this->entity->eid; $this->eid = $this->entity->eid;
$this->server->query("UPDATE players SET EID = ".$this->eid." WHERE clientID = ".$this->clientID.";"); $this->server->query("UPDATE players SET EID = ".$this->eid." WHERE clientID = ".$this->clientID.";");
@ -320,10 +323,9 @@ class Session{
case MC_INTERACT: case MC_INTERACT:
if(isset($this->server->entities[$data["target"]]) and Utils::distance($this->entity->position, $this->server->entities[$data["target"]]->position) <= 8){ if(isset($this->server->entities[$data["target"]]) and Utils::distance($this->entity->position, $this->server->entities[$data["target"]]->position) <= 8){
console("[DEBUG] EID ".$this->eid." attacked EID ".$data["target"], true, true, 2); console("[DEBUG] EID ".$this->eid." attacked EID ".$data["target"], true, true, 2);
if($this->server->gamemode !== 1 and $this->server->difficulty > 0){ if($this->server->gamemode !== 1 and $this->server->difficulty > 0){
$this->server->api->entity->harm($data["target"], $this->server->difficulty, $this->eid);
} }
$this->server->trigger("onHealthChange", array("eid" => $data["target"], "health" => $this->server->entities[$data["target"]]->getHealth() - $this->server->difficulty, "cause" => $this->eid));
} }
break; break;
case MC_ANIMATE: case MC_ANIMATE: