Added custom settings, update notification

This commit is contained in:
Shoghi Cervantes 2014-06-16 19:34:47 +02:00
parent 89c61bb05e
commit 73b9b2491f
7 changed files with 292 additions and 72 deletions

1
.gitignore vendored
View File

@ -6,6 +6,7 @@ bin/*
*.txt
*.phar
server.properties
pocketmine.yml
# Common IDEs
.idea/*

View File

@ -592,6 +592,15 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->teleport($ev->getRespawnPosition());
$this->spawnToAll();
$this->server->getPluginManager()->callEvent($ev = new PlayerJoinEvent($this, $this->getName() . " joined the game"));
if(strlen(trim($ev->getJoinMessage())) > 0){
$this->server->broadcastMessage($ev->getJoinMessage());
}
if($this->server->getUpdater()->hasUpdate() and $this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE)){
$this->server->getUpdater()->showPlayerUpdate($this);
}
}
$this->lastChunk = array($X, $Z, $cnt, microtime(true));
@ -1185,11 +1194,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->server->getLogger()->info(TextFormat::AQUA . $this->username . TextFormat::WHITE . "[/" . $this->ip . ":" . $this->port . "] logged in with entity id " . $this->id . " at (" . $this->getLevel()->getName() . ", " . round($this->x, 4) . ", " . round($this->y, 4) . ", " . round($this->z, 4) . ")");
$this->server->getPluginManager()->callEvent($ev = new PlayerJoinEvent($this, $this->getName() . " joined the game"));
if(strlen(trim($ev->getJoinMessage())) > 0){
$this->server->broadcastMessage($ev->getJoinMessage());
}
$this->orderChunks();
$this->tasks[] = $this->server->getScheduler()->scheduleDelayedTask(new CallbackTask(array($this, "orderChunks")), 30);

View File

@ -74,6 +74,7 @@ use pocketmine\scheduler\SendUsageTask;
use pocketmine\scheduler\ServerScheduler;
use pocketmine\scheduler\TickScheduler;
use pocketmine\tile\Tile;
use pocketmine\updater\AutoUpdater;
use pocketmine\utils\Binary;
use pocketmine\utils\Config;
use pocketmine\utils\MainLogger;
@ -109,6 +110,9 @@ class Server{
/** @var PluginManager */
private $pluginManager = null;
/** @var AutoUpdater */
private $updater = null;
/** @var ServerScheduler */
private $scheduler = null;
@ -174,6 +178,9 @@ class Server{
/** @var Config */
private $properties;
/** @var Config */
private $config;
/** @var Player[] */
private $players = [];
@ -471,6 +478,13 @@ class Server{
return $this->levelMetadata;
}
/**
* @return AutoUpdater
*/
public function getUpdater(){
return $this->updater;
}
/**
* @return PluginManager
*/
@ -1049,6 +1063,33 @@ class Server{
return $this->properties->exists($variable) ? $this->properties->get($variable) : $defaultValue;
}
/**
* @param string $variable
* @param mixed $defaultValue
*
* @return mixed
*/
public function getProperty($variable, $defaultValue = null){
$vars = explode(".", $variable);
$base = array_shift($vars);
if($this->config->exists($base)){
$base = $this->config->get($base);
}else{
return $defaultValue;
}
while(count($vars) > 0){
$baseKey = array_shift($vars);
if(is_array($base) and isset($base[$baseKey])){
$base = $base[$baseKey];
}else{
return $defaultValue;
}
}
return $base;
}
/**
* @param string $variable
* @param string $value
@ -1269,10 +1310,14 @@ class Server{
$this->logger->info("Starting Minecraft: PE server version " . TextFormat::AQUA . $this->getVersion());
$this->logger->info("Loading properties...");
if(!file_exists($this->dataPath . "pocketmine.yml")){
@file_put_contents($this->dataPath . "pocketmine.yml", file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml"));
}
$this->config = new Config($this->dataPath . "pocketmine.yml", Config::YAML, []);
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, array(
"motd" => "Minecraft: PE Server",
"server-port" => 19132,
"memory-limit" => "128M",
"memory-limit" => "256M",
"white-list" => false,
"announce-player-achievements" => true,
"spawn-protection" => 16,
@ -1316,12 +1361,12 @@ class Server{
$this->setConfigInt("difficulty", 3);
}
define("pocketmine\\DEBUG", $this->getConfigInt("debug.level", 1));
define("pocketmine\\DEBUG", $this->getProperty("debug.level", 1));
if($this->logger instanceof MainLogger){
$this->logger->setLogDebug(\pocketmine\DEBUG > 1);
}
define("ADVANCED_CACHE", $this->getConfigBoolean("enable-advanced-cache", false));
define("MAX_CHUNK_RATE", 20 / $this->getConfigInt("max-chunks-per-second", 20));
define("ADVANCED_CACHE", $this->getProperty("settings.advanced-cache", false));
define("MAX_CHUNK_RATE", 20 / $this->getProperty("chunk-sending.per-second", 20));
if(ADVANCED_CACHE == true){
$this->logger->info("Advanced cache enabled");
}
@ -1336,7 +1381,7 @@ class Server{
$this->interfaces[] = new RakLibInterface($this);
$this->logger->info("This server is running PocketMine-MP version " . ($version->isDev() ? TextFormat::YELLOW : "") . $this->getPocketMineVersion() . TextFormat::RESET . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
$this->logger->info("This server is running PocketMine-MP version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(false) . TextFormat::RESET . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
$this->logger->info("PocketMine-MP is distributed under the LGPL License", true, true, 0);
$this->consoleSender = new ConsoleCommandSender();
@ -1352,7 +1397,7 @@ class Server{
$this->pluginManager->registerInterface("pocketmine\\plugin\\PharPluginLoader");
$this->pluginManager->loadPlugins($this->pluginPath);
//TODO: update checking (async)
$this->updater = new AutoUpdater($this, $this->getProperty("auto-updater.host", "www.pocketmine.net"));
$this->enablePlugins(PluginLoadOrder::STARTUP);
@ -1383,57 +1428,16 @@ class Server{
$this->properties->save();
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask("pocketmine\\utils\\Cache::cleanup"), 20 * 45, 20 * 45);
if($this->getConfigBoolean("auto-save", true) === true){
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doAutoSave")), 18000, 18000);
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask("pocketmine\\utils\\Cache::cleanup"), $this->getProperty("ticks-per.cache-cleanup", 900), $this->getProperty("ticks-per.cache-cleanup", 900));
if($this->getConfigBoolean("auto-save", true) === true and $this->getProperty("ticks-per.autosave", 6000) > 0){
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doAutoSave")), $this->getProperty("ticks-per.autosave", 6000), $this->getProperty("ticks-per.autosave", 6000));
}
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doLevelGC")), $this->getProperty("chunk-gc.period-in-ticks", 600), $this->getProperty("chunk-gc.period-in-ticks", 600));
$this->enablePlugins(PluginLoadOrder::POSTWORLD);
/*
//TODO
if($this->getProperty("last-update") === false or ($this->getProperty("last-update") + 3600) < time()){
$this->logger->info("Checking for new server version");
$this->logger->info("Last check: " . TextFormat::AQUA . date("Y-m-d H:i:s", $this->getProperty("last-update")));
if($this->server->version->isDev()){
$info = json_decode(Utils::getURL("https://api.github.com/repos/PocketMine/PocketMine-MP/commits"), true);
if($info === false or !isset($info[0])){
console("[ERROR] Github API error");
}else{
$last = new \DateTime($info[0]["commit"]["committer"]["date"]);
$last = $last->getTimestamp();
if($last >= $this->getProperty("last-update") and $this->getProperty("last-update") !== false and \pocketmine\GIT_COMMIT != $info[0]["sha"]){
$this->logger->notice("" . TextFormat::YELLOW . "A new DEVELOPMENT version of PocketMine-MP has been released!");
$this->logger->notice("" . TextFormat::YELLOW . "Commit \"" . $info[0]["commit"]["message"] . "\" [" . substr($info[0]["sha"], 0, 10) . "] by " . $info[0]["commit"]["committer"]["name"]);
$this->logger->notice("" . TextFormat::YELLOW . "Get it at PocketMine.net or at https://github.com/PocketMine/PocketMine-MP/archive/" . $info[0]["sha"] . ".zip");
$this->logger->notice("This message will disappear after issuing the command \"/update-done\"");
}else{
$this->setProperty("last-update", time());
$this->logger->info("" . TextFormat::AQUA . "This is the latest DEVELOPMENT version");
}
}
}else{
$info = json_decode(Utils::getURL("https://api.github.com/repos/PocketMine/PocketMine-MP/tags"), true);
if($info === false or !isset($info[0])){
console("[ERROR] Github API error");
}else{
$newest = new VersionString(VERSION);
$newestN = $newest->getNumber();
$update = new VersionString($info[0]["name"]);
$updateN = $update->getNumber();
if($updateN > $newestN){
$this->logger->notice("" . TextFormat::GREEN . "A new STABLE version of PocketMine-MP has been released!");
$this->logger->notice("" . TextFormat::GREEN . "Version \"" . $info[0]["name"] . "\" #" . $updateN);
$this->logger->notice("Get it at PocketMine.net or at " . $info[0]["zipball_url"]);
$this->logger->notice("This message will disappear as soon as you update");
}else{
$this->setProperty("last-update", time());
$this->logger->info("" . TextFormat::AQUA . "This is the latest STABLE version");
}
}
}
}
*/
}
/**
@ -1551,11 +1555,11 @@ class Server{
$this->properties->reload();
$this->maxPlayers = $this->getConfigInt("max-players", 20);
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "128M")))) !== false){
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "256M")))) !== false){
$value = array("M" => 1, "G" => 1024);
$real = ((int) substr($memory, 0, -1)) * $value[substr($memory, -1)];
if($real < 128){
$this->logger->warning("PocketMine-MP may not work right with less than 128MB of RAM", true, true, 0);
if($real < 256){
$this->logger->warning("PocketMine-MP may not work right with less than 256MB of RAM", true, true, 0);
}
@ini_set("memory_limit", $memory);
}else{
@ -1591,7 +1595,7 @@ class Server{
$this->rcon->stop();
}
if($this->getConfigBoolean("upnp-forwarding", false) === true){
if($this->getProperty("settings.upnp-forwarding", false) === true){
$this->logger->info("[UPnP] Removing port forward...");
UPnP::RemovePortForward($this->getPort());
}
@ -1599,7 +1603,7 @@ class Server{
$this->pluginManager->disablePlugins();
foreach($this->players as $player){
$player->kick("server stop");
$player->kick($this->getProperty("settings.shutdown-message", "Server closed"));
}
foreach($this->getLevels() as $level){
@ -1631,13 +1635,13 @@ class Server{
}
if($this->getConfigBoolean("send-usage", true) !== false){
if($this->getProperty("settings.send-usage", true) !== false){
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "sendUsage")), 6000, 6000);
$this->sendUsage();
}
if($this->getConfigBoolean("upnp-forwarding", false) == true){
if($this->getProperty("settings.upnp-forwarding", false) == true){
$this->logger->info("[UPnP] Trying to port forward...");
UPnP::PortForward($this->getPort());
}
@ -1744,7 +1748,7 @@ class Server{
}
$dump .= "\r\n\r\n";
$version = new VersionString();
$dump .= "PocketMine-MP version: " . $version . " #" . $version->getNumber() . " [Protocol " . Info::CURRENT_PROTOCOL . "; API " . API_VERSION . "]\r\n";
$dump .= "PocketMine-MP version: " . $version->get(false). " #" . $version->getNumber() . " [Protocol " . Info::CURRENT_PROTOCOL . "; API " . API_VERSION . "]\r\n";
$dump .= "Git commit: " . GIT_COMMIT . "\r\n";
$dump .= "uname -a: " . php_uname("a") . "\r\n";
$dump .= "PHP Version: " . phpversion() . "\r\n";
@ -1853,6 +1857,12 @@ class Server{
}
}
public function doLevelGC(){
foreach($this->getLevels() as $level){
$level->doChunkGarbageCollection();
}
}
public function sendUsage(){
if($this->lastSendUsage instanceof SendUsageTask){
if(!$this->lastSendUsage->isFinished()){ //do not call multiple times
@ -1865,6 +1875,7 @@ class Server{
$plist .= str_replace(array(";", ":"), "", $d->getName()) . ":" . str_replace(array(";", ":"), "", $d->getVersion()) . ";";
}
$version = new VersionString();
$this->lastSendUsage = new SendUsageTask("http://stats.pocketmine.net/usage.php", array(
"serverid" => Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() . ":" . $this->getPort()), 0, 8)),
"port" => $this->getPort(),
@ -1872,7 +1883,8 @@ class Server{
"memory_total" => $this->getConfigString("memory-limit"),
"memory_usage" => memory_get_usage(),
"php_version" => \pocketmine\PHP_VERSION,
"version" => \pocketmine\VERSION,
"version" => $version->get(false),
"build" => $version->getBuild(),
"mc_version" => \pocketmine\MINECRAFT_VERSION,
"protocol" => network\protocol\Info::CURRENT_PROTOCOL,
"online" => count($this->players),

View File

@ -103,7 +103,7 @@ class SimpleCommandMap implements CommandMap{
$this->register("pocketmine", new TeleportCommand("tp"));
$this->register("pocketmine", new ReloadCommand("reload"));
if($this->server->getConfigBoolean("debug.commands", false) === true){
if($this->server->getProperty("debug.commands", false) === true){
$this->register("pocketmine", new StatusCommand("status"));
}
}

View File

@ -0,0 +1,50 @@
# Main configuration file for PocketMine-MP
# These settings are the ones that cannot be included in server.properties
# Some of these settings are safe, others can break your server if modified incorrectly
settings:
shutdown-message: "Server closed"
advanced-cache: false
upnp-forwarding: false
send-usage: true
debug:
#If > 1, it will show debug messages in the console
level: 1
#Enables /status
commands: false
chunk-sending:
per-second: 20
compression-level: 7
chunk-gc:
period-in-ticks: 600
ticks-per:
animal-spawns: 400
monster-spawns: 1
autosave: 6000
cache-cleanup: 900
spawn-limits:
monsters: 70
animals: 15
water-animals: 5
ambient: 15
auto-updater:
enabled: true
on-update:
warn-console: true
warn-ops: true
#Can be development, beta or stable.
preferred-channel: stable
#If using a development version, it will suggest changing the channel
suggest-channels: true
host: www.pocketmine.net
aliases:
#Examples
#showtheversion: version
#savestop: [save-all, stop]

View File

@ -0,0 +1,140 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* 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.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\updater;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\utils\TextFormat;
use pocketmine\utils\Utils;
use pocketmine\utils\VersionString;
class AutoUpdater{
/** @var Server */
protected $server;
protected $endpoint;
protected $hasUpdate = false;
protected $updateInfo = null;
public function __construct(Server $server, $endpoint){
$this->server = $server;
$this->endpoint = "http://$endpoint/api/";
if($server->getProperty("auto-updater.enabled", true)){
$this->check();
if($this->hasUpdate()){
if($this->server->getProperty("auto-updater.on-update.warn-console", true)){
$this->showConsoleUpdate();
}
}elseif($this->server->getProperty("auto-updater.preferred-channel", true)){
$version = new VersionString();
if(!$version->isDev() and $this->getChannel() !== "stable"){
$this->showChannelSuggestionStable();
}elseif($this->getChannel() === "stable"){
$this->showChannelSuggestionBeta();
}
}
}
}
protected function check(){
$response = Utils::getURL($this->endpoint . "?channel=". $this->getChannel(), 4);
$response = @json_decode($response, true);
if(!is_array($response)){
return;
}
$this->updateInfo = [
"version" => $response["version"],
"api_version" => $response["api_version"],
"build" => $response["build"],
"date" => $response["date"],
"details_url" => isset($response["details_url"]) ? $response["details_url"] : null,
"download_url" => $response["download_url"]
];
$this->checkUpdate();
}
/**
* @return bool
*/
public function hasUpdate(){
return $this->hasUpdate;
}
public function showConsoleUpdate(){
$logger = $this->server->getLogger();
$newVersion = new VersionString($this->updateInfo["version"]);
$logger->warning("----- PocketMine-MP Auto Updater -----");
$logger->warning("Your version of PocketMine-MP is out of date. Version ".$newVersion->get(false)." (build #".$newVersion->getBuild().") was released on ".date("D M j h:i:s Y", $this->updateInfo["date"]));
if($this->updateInfo["details_url"] !== null){
$logger->warning("Details: ".$this->updateInfo["details_url"]);
}
$logger->warning("Download: ".$this->updateInfo["download_url"]);
$logger->warning("----- -------------------------- -----");
}
public function showPlayerUpdate(Player $player){
$player->sendMessage(TextFormat::DARK_PURPLE . "The version of PocketMine-MP that this server is running is out of date. Please consider updating to the latest version.");
$player->sendMessage(TextFormat::DARK_PURPLE . "Check the console for more details.");
}
protected function showChannelSuggestionStable(){
$logger = $this->server->getLogger();
$logger->info("----- PocketMine-MP Auto Updater -----");
$logger->info("It appears you're running a Stable build, when you've specified that you prefer to run ".ucfirst($this->getChannel())." builds.");
$logger->info("If you would like to be kept informed about new Stable builds only, it is recommended that you change 'preferred-channel in your pocketmine.yml to 'stable'.");
$logger->info("----- -------------------------- -----");
}
protected function showChannelSuggestionBeta(){
$logger = $this->server->getLogger();
$logger->info("----- PocketMine-MP Auto Updater -----");
$logger->info("It appears you're running a Beta build, when you've specified that you prefer to run Stable builds.");
$logger->info("If you would like to be kept informed about new Beta or Development builds, it is recommended that you change 'preferred-channel in your pocketmine.yml to 'beta' or 'development'.");
$logger->info("----- -------------------------- -----");
}
protected function checkUpdate(){
if($this->updateInfo === null){
return;
}
$currentVersion = new VersionString($this->server->getPocketMineVersion());
$newVersion = new VersionString($this->updateInfo["version"]);
if($currentVersion->compare($newVersion) > 0){
$this->hasUpdate = true;
}
$this->hasUpdate = false;
}
public function getChannel(){
$channel = strtolower($this->server->getProperty("auto-updater.preferred-channel", "stable"));
if($channel !== "stable" and $channel !== "beta" and $channel !== "development"){
$channel = "stable";
}
return $channel;
}
}

View File

@ -36,7 +36,7 @@ class VersionString{
);
private $stage;
private $major;
private $release;
private $build;
private $minor;
private $development = false;
private $generation;
@ -48,12 +48,17 @@ class VersionString{
$this->generation = ($version >> 9) & 0x0F;
$this->stage = array_search(($version >> 13) & 0x0F, VersionString::$stageOrder, true);
}else{
$version = preg_split("/([A-Za-z]*)[ _\-]([0-9]*)\.([0-9]*)\.{0,1}([0-9]*)(dev|)/", $version, -1, PREG_SPLIT_DELIM_CAPTURE);
$version = preg_split("/([A-Za-z]*)[ _\\-]([0-9]*)\\.([0-9]*)\\.{0,1}([0-9]*)(dev|)(-[\\0-9]{1,}|)/", $version, -1, PREG_SPLIT_DELIM_CAPTURE);
$this->stage = strtolower($version[1]); //0-15
$this->generation = (int) $version[2]; //0-15
$this->major = (int) $version[3]; //0-15
$this->minor = (int) $version[4]; //0-31
$this->development = $version[5] === "dev" ? true : false;
if($version[6] !== ""){
$this->build = intval(substr($version[6], 1));
}else{
$this->build = 0;
}
}
}
@ -81,12 +86,16 @@ class VersionString{
return $this->generation . "." . $this->major . "." . $this->minor;
}
public function getBuild(){
return $this->build;
}
public function isDev(){
return $this->development === true;
}
public function get(){
return ucfirst($this->stage) . "_" . $this->getRelease() . ($this->development === true ? "dev" : "");
public function get($build = false){
return ucfirst($this->stage) . "_" . $this->getRelease() . ($this->development === true ? "dev" : "") . (($this->build > 0 and $build === true) ? "-" . $this->build : "");
}
public function __toString(){
@ -106,6 +115,10 @@ class VersionString{
return -1; //Target is older
}elseif($number < $tNumber){
return 1; //Target is newer
}elseif($target->getBuild() > $this->getBuild()){
return 1;
}elseif($target->getBuild() > $this->getBuild()){
return -1;
}else{
return 0; //Same version
}