server = ServerAPI::request(); } public function getList(){ $list = array(); foreach($this->plugins as $p){ $list[] = $p[1]; } return $list; } public function getInfo($className){ $className = strtolower($className); if(!isset($this->plugins[$className])){ return false; } $plugin = $this->plugins[$className]; return array($plugin[1], get_class_methods($plugin[0])); } public function load($file){ if(strtolower(substr($file, -3)) === "pmf"){ $pmf = new PMFPlugin($file); $info = $pmf->getPluginInfo(); }else{ $content = file_get_contents($file); $info = strstr($content, "*/", true); $content = str_repeat(PHP_EOL, substr_count($info, "\n")).substr(strstr($content, "*/"),2); if(preg_match_all('#([a-zA-Z0-9\-_]*)=([^\r\n]*)#u', $info, $matches) == 0){ //false or 0 matches console("[ERROR] Failed parsing of ".basename($file)); return false; } $info = array(); foreach($matches[1] as $k => $i){ $v = $matches[2][$k]; switch(strtolower($v)){ case "on": case "true": case "yes": $v = true; break; case "off": case "false": case "no": $v = false; break; } $info[$i] = $v; } $info["code"] = $content; $info["class"] = trim(strtolower($info["class"])); } if(!isset($info["name"]) or !isset($info["version"]) or !isset($info["class"]) or !isset($info["author"])){ console("[ERROR] Failed parsing of ".basename($file)); return false; } console("[INFO] Loading plugin \"\x1b[32m".$info["name"]."\x1b[0m\" \x1b[35m".$info["version"]." \x1b[0mby \x1b[36m".$info["author"]."\x1b[0m"); if($info["class"] !== "none" and class_exists($info["class"])){ console("[ERROR] Failed loading plugin: class already exists"); return false; } if(eval($info["code"]) === false or ($info["class"] !== "none" and !class_exists($info["class"]))){ console("[ERROR] Failed loading plugin: evaluation error"); return false; } $className = $info["class"]; $apiversion = array_map("intval", explode(",", (string) $info["apiversion"])); if(!in_array((string) CURRENT_API_VERSION, $apiversion)){ console("[WARNING] Plugin \"".$info["name"]."\" may not be compatible with the API (".$info["apiversion"]." != ".CURRENT_API_VERSION.")! It can crash or corrupt the server!"); } if($info["class"] !== "none"){ $object = new $className($this->server->api, false); if(!($object instanceof Plugin)){ console("[ERROR] Plugin \"\x1b[36m".$info["name"]."\x1b[0m\" doesn't use the Plugin Interface"); if(method_exists($object, "__destruct")){ $object->__destruct(); } $object = null; unset($object); }else{ $this->plugins[$className] = array($object, $info); } }else{ $this->plugins[md5($info["name"])] = array(new DummyPlugin($this->server->api, false), $info); } } public function get(Plugin $plugin){ foreach($this->plugins as &$p){ if($p[0] === $plugin){ return $p; } } return false; } public function configPath(Plugin $plugin){ $p = $this->get($plugin); if($p === false){ return false; } $path = DATA_PATH."plugins/".$p[1]["name"]."/"; $this->plugins[$p[1]["class"]][1]["path"] = $path; @mkdir($path); return $path; } public function createConfig(Plugin $plugin, $default = array()){ $p = $this->get($plugin); if($p === false){ return false; } $path = $this->configPath($plugin); $cnf = new Config($path."config.yml", CONFIG_YAML, $default); $cnf->save(); return $path; } private function fillDefaults($default, &$yaml){ foreach($default as $k => $v){ if(is_array($v)){ if(!isset($yaml[$k]) or !is_array($yaml[$k])){ $yaml[$k] = array(); } $this->fillDefaults($v, $yaml[$k]); }elseif(!isset($yaml[$k])){ $yaml[$k] = $v; } } } public function readYAML($file){ return Spyc::YAMLLoad(file_get_contents($file)); } public function writeYAML($file, $data){ return file_put_contents($file, Spyc::YAMLDump($data)); } public function init(){ $this->server->event("server.start", array($this, "initAll")); $this->loadAll(); } public function loadAll(){ $dir = dir(DATA_PATH."plugins/"); while(false !== ($file = $dir->read())){ if($file{0} !== "."){ $ext = strtolower(substr($file, -3)); if($ext === "php" or $ext === "pmf"){ $this->load(DATA_PATH."plugins/" . $file); } } } } public function initAll(){ console("[INFO] Starting plugins..."); foreach($this->plugins as $p){ $p[0]->init(); //ARGHHH!!! Plugin loading randomly fails!! } } } interface Plugin{ public function __construct(ServerAPI $api, $server = false); public function init(); public function __destruct(); } class DummyPlugin implements Plugin{ public function __construct(ServerAPI $api, $server = false){ } public function init(){ } public function __destruct(){ } }