|
<?php
|
|
|
|
/*
|
|
__PocketMine Plugin__
|
|
class=Hub
|
|
name=Hub
|
|
description=Hub plugin (gamma edition) for LegionPE
|
|
version=Gamma 1.1
|
|
apiversion=12,13
|
|
author=PEMapModder
|
|
*/
|
|
|
|
class Hub implements Plugin{
|
|
private static $instance = false;
|
|
public static function request(){
|
|
return self::$instance;
|
|
}
|
|
public $players=array();
|
|
public $ranks, $teams, $signs;
|
|
public function __construct(ServerAPI $a, $s=false){
|
|
$path=FILE_PATH."hub players/";
|
|
@mkdir($path);
|
|
$path=FILE_PATH."security/";
|
|
@mkdir($path);
|
|
$path.="logs/";
|
|
@mkdir($path);
|
|
self::$instance=$this;
|
|
$this->a=$a;
|
|
$this->p=$a->player;
|
|
$this->l=$a->level;
|
|
$this->t=$a->tile;
|
|
$this->c=$a->console;
|
|
$this->s=ServerAPI::request();
|
|
$this->ranks=new RankMgr($this);
|
|
$this->teams=new TeamMgr();
|
|
// $this->signs=new SignMgr();
|
|
}
|
|
public function __destruct(){
|
|
}
|
|
public function init(){
|
|
$this->s->addHandler("player.spawn", array($this, "onSpawn"), 51);
|
|
$this->s->addHandler("player.quit", array($this, "onQuit"));
|
|
}
|
|
public function onSpawn(Player $player){
|
|
if($player->username == "Steve"){
|
|
$player->sendChat("The default username, \"Steve\", is rejected in this server.\n----------------\nPlease change your username to another name.\n----------------\nYou are going to be kicked in ten seconds.");
|
|
$this->s->schedule(200, array($player, "close"), "Default username usage");
|
|
}
|
|
$this->players[strtolower(trim($player->username))]=new HubPlayer($player);
|
|
}
|
|
public function onQuit(Player $player){
|
|
$path="\$this->players[strtolower(trim(\$player->username))]";
|
|
eval("if(isset($path)){"."$path=false; unset($path);}");
|
|
}
|
|
public function getPlayer($player){
|
|
$path="\$this->players[strtolower(trim(\"\$player\"))]";
|
|
eval("return (isset($path)?$path:false);");
|
|
}
|
|
}
|
|
class HubPlayer{
|
|
const REGISTER_ONE=31;
|
|
const REGISTER_TWO=32;
|
|
const TO_LOGIN=21;
|
|
const OFFLINE=21;
|
|
const UNBLOCKED=11; // playing
|
|
public $blockTouchStatus="auth";
|
|
public $entityAttackStatus="auth";
|
|
public $chatStatus="auth";
|
|
public $p;
|
|
public $cfg;
|
|
public $session;
|
|
private $loginTrials=0;
|
|
public function __construct(Player $player){
|
|
$this->p=$player;
|
|
$this->addHandlers();
|
|
$r=HubConfig::fromPlayer($player);
|
|
$this->cfg=$r[0];
|
|
$line_seperator="-----------------------";
|
|
if($r[1] and $r[0]->get("passwordhash")!=="THIS PASSWORD IS NOT SET"){ // login
|
|
$player->sendChat("Welcome back to LegionPE - Ultimate PvP!");
|
|
$player->sendChat($line_seperator);
|
|
$player->sendChat("[Login wizard] Please login by typing your password directly into chat. You have 5 chances to type your password. You will be kicked if you fail in all five attempts to login.");
|
|
$this->loginTrials=5;
|
|
$this->session=self::TO_LOGIN;
|
|
}
|
|
else{ // register
|
|
$player->sendChat($line_seperator);
|
|
$player->sendChat("Welcome to LegionPE - Ultimate PvP!");
|
|
$player->sendChat($line_seperator);
|
|
$player->sendChat("Please follow the registering wizard to register your account, in order to protect your account.");
|
|
$player->sendChat($line_seperator);
|
|
$player->sendChat("[Register wizard] Please type in your password. It has to have a minimal length of 4 characters.");
|
|
$player->sendChat($line_seperator);
|
|
$this->session=self::REGISTER_ONE;
|
|
}
|
|
}
|
|
public function addHandlers(){
|
|
$s=ServerAPI::request();
|
|
$s->addHandler("player.chat", array($this, "onChat"), PHP_INT_MAX);
|
|
$s->addHandler("player.quit", array($this, "onQuit"), PHP_INT_MAX);
|
|
$s->addHandler("player.chat", array($this, "onChatLP"), 3);
|
|
$s->addHandler("console.command", array($this, "onCmd"), PHP_INT_MAX);
|
|
$s->addHandler("player.interact", array($this, "onHit"), 0x1000);
|
|
$s->addHandler("entity.health.change", array($this, "onHurt"), 0x1000);
|
|
$s->addHandler("player.teleport", array($this, "onTeleported"), 0x1000);
|
|
$s->addHandler("player.block.touch", array($this, "blockTouch"), 0x1000);
|
|
$s->addHandler("player.move", array($this, "onMove"), 0x1000);
|
|
}
|
|
//event handlers
|
|
public function onMove($data){
|
|
if($data->player->username!=$this->p->username){
|
|
return;
|
|
}
|
|
if($this->session!==self::UNBLOCKED){
|
|
$data->fallY=false;
|
|
$data->fallStart=false;
|
|
$pk=new MovePlayerPacket;
|
|
$pk->eid=0;
|
|
$pk->x=$data->x;
|
|
$pk->y=$data->y;
|
|
$pk->z=$data->z;
|
|
$pk->yaw=0;
|
|
$pk->pitch=0;
|
|
$pk->bodyYaw=0;
|
|
$this->p->dataPacket($pk);
|
|
return false;
|
|
}
|
|
}
|
|
public function onChat($msg){
|
|
if($msg["player"]->username!=$this->p->username)
|
|
return;
|
|
$msg=$msg["message"];
|
|
if($this->session===self::REGISTER_ONE){ // first time enter password
|
|
$this->tempPass=$msg;
|
|
$this->p->sendChat("[Register wizard] You have typed the password. Please type again to confirm.");
|
|
$this->session=self::REGISTER_TWO;
|
|
return false;
|
|
}
|
|
if($this->session===self::REGISTER_TWO){ // confirm password # unblock
|
|
if($msg===$this->tempPass){ // registry success!
|
|
$this->cfg->set("passwordhash", self::hashStr($msg));
|
|
$this->cfg->save();
|
|
$this->tempPass=0;
|
|
$this->session=self::UNBLOCKED;
|
|
$this->p->sendChat("[Register wizard] You have successfully registered your LegionPE account. Now you can move.");
|
|
ServerAPI::request()->handle("player.auth", $this->p);
|
|
$this->onRegister();
|
|
}
|
|
else{ // two times of typing password do not match
|
|
$this->session=self::REGISTER_ONE;
|
|
$this->p->sendChat("[Register wizard] The two passwords you typed in do not match. The register wizard has been reset.");
|
|
}
|
|
return false;
|
|
}
|
|
if($this->session===self::TO_LOGIN){ // typing password
|
|
if($this->cfg->get("passwordhash")!=$this->hashStr($msg)){ // if password incorrect
|
|
console("[WARNING] $this is using incorrect password. Hash mismatch: ".substr($this->hashStr($msg), 7)." is different from the registered password ".substr($this->cfg->get("passwordhash"), 7));
|
|
$this->loginTrials--;
|
|
echo $this->loginTrials;
|
|
if($this->loginTrials <= 0){ // auth failure kick
|
|
$this->p->sendChat("You failed to login into the account. Are you trying to hack the account? This failure is being logged. You will be kicked in 10 seconds.");
|
|
file_put_contents(FILE_PATH."security/logs/login failiures (>5).log", date(DATE_ATOM)." $this's account has been tried to be logged in from IP ".$this->p->ip." and failed for 5 times.", FILE_APPEND);
|
|
ServerAPI::request()->schedule(20*5, array($this->p, "close"), "kick $this Failing to login with the correct password for 5 times.");
|
|
}
|
|
$this->p->sendChat("[Login wizard] The password you entered is incorrect. Please try again. You have ".$this->loginTrials." more chance(s).");
|
|
}
|
|
else{ // login success!
|
|
$this->tell("[Login wizard] You have logged in. You can now move.");
|
|
$this->session=self::UNBLOCKED;
|
|
ServerAPI::request()->handle("player.auth", $this->p);
|
|
$this->onLogin();
|
|
}
|
|
return false;
|
|
}
|
|
if($this->p->entity->level->getName() == "world"){ // only talk to players at Hub
|
|
foreach(ServerAPI::request()->api->player->getAll(ServerAPI::request()->api->level->get("world")) as $p){
|
|
$p->sendChat("$this> ".strtolower($msg));
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
public function onChatLP($data){ // after most of the handlers are screened
|
|
if($data["player"]->username != $this->p->username)
|
|
return;
|
|
$msg=$data["message"];
|
|
foreach(ServerAPI::request()->api->player->getAll($this->p->entity->level) as $p)
|
|
$p->sendChat("$this: ".strtolower($msg));
|
|
}
|
|
public function onQuit($player){
|
|
if($player->username !== $this->p->username)
|
|
return;
|
|
$this->session=self::OFFLINE;
|
|
}
|
|
public function onCmd($data){
|
|
if(is_string($data["issuer"]))
|
|
return;
|
|
if($data["issuer"]->username !== $this->p->username)
|
|
return;
|
|
if($this->session!==self::UNBLOCKED){
|
|
$this->tell("Please login/register first.");
|
|
return true;
|
|
}
|
|
$params=$data["parameters"];
|
|
if($data["cmd"]==="tp" and (count($params)===4 or (isset($params[1]) and is_string($params[1]) and substr($params[1], 0, 2)=="w:"))){
|
|
if(Hub::request()->getPlayer($params[0])->getSession !== self::UNBLOCKED){
|
|
$this->tell("You cannot teleport a registering/logging-in player!");
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
public function onHit($data){
|
|
if($data["entity"]->player->username !== $this->p->username){
|
|
return;
|
|
}
|
|
if($this->session!==self::UNBLOCKED){
|
|
$this->tell("Please login/register first.");
|
|
return false;
|
|
}
|
|
$target=ServerAPI::request()->api->entity->get($data["target"]);
|
|
if($target->distance($this->p->entity) > 10){ // this is much enough
|
|
$this->tell("Don't use mods! You are being suspected using the mod \"Pick me\". This is going to be reported to the staffs. You are going to be kicked in 5 seconds.");
|
|
ServerAPI::request()->schedule(100, array($this->p, "close"), "being kicked for using mods");
|
|
foreach(ServerAPI::request()->api->player->getAll() as $p){
|
|
$p->sendChat("$this has been kicked for using the mod \"Pick me\"!");
|
|
}
|
|
}
|
|
}
|
|
public function onHurt($data){
|
|
if($data["eid"] !== $this->p->entity->eid)
|
|
return;
|
|
if($this->session !== self::UNBLOCKED){
|
|
if(($p=ServerAPI::request()->api->player->getByEID($data["cause"])) instanceof Player){
|
|
$p->sendChat("You cannot attack a logging-in or registering player!");
|
|
}
|
|
return false;
|
|
}
|
|
if($this->p->entity->level->getName() === "world" and $data["health"]!==20){
|
|
$this->p->entity->setHealth(20);
|
|
$this->tp(LegionPE::getHubSpawn());
|
|
return false;
|
|
}
|
|
}
|
|
public function onTeleported($data){
|
|
if($this->session!==self::UNBLOCKED){
|
|
return false;
|
|
}
|
|
}
|
|
public function blockTouch($data){
|
|
if($data["player"]->username !== $this->p->username)
|
|
return;
|
|
if($this->session !== self::UNBLOCKED){
|
|
$this->tell("Please login/register first.");
|
|
return false;
|
|
}
|
|
if($data["target"]->distance($this->p->entity) >= 12){ // Pick Me
|
|
$this->tell("Don't use mods! You are being suspected using the mod \"Pick me\". This is going to be reported to the staffs. You are going to be kicked in 5 seconds.");
|
|
console("[WARNING] $this is using the mod \"Picke Me\". Distance is ".$data["target"]->distance($this->p->entity));
|
|
ServerAPI::request()->schedule(100, array($this->p, "close"), "being kicked for using mods");
|
|
foreach(ServerAPI::request()->api->player->getAll() as $p)
|
|
$p->sendChat("$this has been kicked for using the mod \"Pick me\"!");
|
|
}
|
|
if($data["target"] instanceof SignPostBlock){ // TODO
|
|
$tile=Hub::request()->t->get($data["target"]);
|
|
$data=$tile->data;
|
|
if(Hub::request()->ranks->getRank($data["creator"]) !== "trust")
|
|
return;
|
|
$t=$data["target"];
|
|
// choose teams
|
|
for($i=0; $i<4; $i++){
|
|
if($t->equals(LegionPE::getChooseTeamSign($i))){
|
|
Hub::request()->team->joinTeam($i, $this->p);
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
//functions//
|
|
public function onRegister(){
|
|
$this->tp(LegionPE::getTeamChoosingStandPoint());
|
|
$this->tell("[Teams] Please choose a team among these four. Tap the sign to confirm.");
|
|
$this->tell("-------------------------");
|
|
$this->tell("[Teams] Some teams may be locked from being joined because they are too popular. Choose other team(s).");
|
|
$this->tell("-------------------------");
|
|
$this->tell("[Teams] [Hint] If you badly want to join a particular team (like if your brother is also in that team), wait a while or come back later.");
|
|
}
|
|
public function onLogin(){
|
|
$this->tp(LegionPE::getHubSpawn());
|
|
$this->tell("[Hub] Welcome back to the LegionPE Hub! Choose a minigame or read the score chart or just chat here.");
|
|
}
|
|
public function getRank(){
|
|
return Hub::request()->ranks->getRank($this);
|
|
}
|
|
public function getSession(){
|
|
return $this->session;
|
|
}
|
|
public function getTeam(){
|
|
return Hub::request()->team->get($this);
|
|
}
|
|
public function getPts(){
|
|
return $this->cfg->getPts();
|
|
}
|
|
public function addPts($pts){
|
|
return $this->cfg->addPts($pts);
|
|
}
|
|
//redirectors//
|
|
public function tell($msg){
|
|
return $this->p->sendChat($msg);
|
|
}
|
|
public function tp(Vector3 $pos){
|
|
return $this->p->teleport($pos);
|
|
}
|
|
public function __toString(){
|
|
return $this->p->username;
|
|
}
|
|
//static utils//
|
|
public static function hashStr($str){
|
|
return bin2hex(hash(hash_algos()[12], $str, TRUE));
|
|
}
|
|
}
|
|
class HubConfig extends Config{
|
|
public static function fromPlayer(Player $player){
|
|
$ign=self::pign($player);
|
|
$path=FILE_PATH."hub players/".substr($ign, 0, 1)."/";
|
|
@mkdir($path);
|
|
$path.="$ign.yml";
|
|
$e=file_exists($path);
|
|
$c=new HubConfig($path, $player);
|
|
return array($c, $e);
|
|
}
|
|
public static function pign($p){
|
|
return strtolower(trim("$p"));
|
|
}
|
|
public function __construct($path, Player $player){
|
|
if(defined("CONFIG_YAML"))
|
|
eval("\$type=CONFIG_YAML;");
|
|
else eval("\$type=Config::YAML;");
|
|
$preConfig=self::$preConfig;
|
|
// ...
|
|
parent::__construct($path, $type, $preConfig);
|
|
ServerAPI::request()->schedule(1200, array($this, "save"));
|
|
}
|
|
public static $preConfig = array(
|
|
"team" => -1,
|
|
"personalpoints" => 0,
|
|
"passwordhash" => "THIS PASSWORD IS NOT SET",
|
|
"preferences" => array(
|
|
"authbyip" => false,
|
|
"lang" => "en_US",
|
|
),
|
|
);
|
|
}
|
|
class RankMgr{
|
|
public $hub;
|
|
public $ranks=array();
|
|
public function __construct(Hub $hub){
|
|
$this->hub=$hub;
|
|
$this->reloadAll();
|
|
ServerAPI::request()->schedule(1200, array($this, "reloadAll"), array(), true);
|
|
console(FORMAT_LIGHT_PURPLE."[DEBUG] Evaluated ranks: ".self::arrToStr($this->ranks));
|
|
}
|
|
public static function arrToStr(array $arr){
|
|
$output="array(";
|
|
foreach($arr as $key=>$item){
|
|
if(is_string($key))
|
|
$output.="\"$key\"=>";
|
|
else $output.="$key=>";
|
|
|
|
if(is_string($item))
|
|
$output.="\"$item\", ";
|
|
elseif(is_numeric($item))
|
|
$output.="$item, ";
|
|
elseif(is_object($item)){
|
|
if(is_callable(array($item, "__toString")))
|
|
$output.=get_class($item)." instance $item, ";
|
|
else $output.=get_class($item)." instance, ";
|
|
}
|
|
elseif(is_null($item))
|
|
$output.="null, ";
|
|
elseif(is_bool($item))
|
|
$output.=(($item?"true":"false").", ");
|
|
elseif(is_array($item))
|
|
$output.=(self::arrToStr($item).", ");
|
|
}
|
|
$output.=")";
|
|
return $output;
|
|
}
|
|
public function reloadAll(){
|
|
@mkdir(FILE_PATH."ranks/");
|
|
foreach(array_keys(self::$rankValues) as $rank){
|
|
$this->ranks[$rank]=array();
|
|
if($rank==="guest")continue;
|
|
if(!file_exists(FILE_PATH."ranks/$rank.txt"))
|
|
file_put_contents(FILE_PATH."ranks/$rank.txt", <<<default
|
|
#list of player names of $rank
|
|
REM lines starting with "rem " or "#" are remarks/comments and would not be read.
|
|
#This list is case-insensitive. They are automatically read into and checked case-insensitive at the server runtime.
|
|
rEm This file is reloaded every minute.
|
|
#names containing spaces (" ") will be automatically trimmed.
|
|
rem e.g. " pe map modder " => "pemapmodder"
|
|
#names, after trimmed, shorter than or equal to 3 characters, will not be read.
|
|
ReM duplications are not to be counted
|
|
|
|
default
|
|
);
|
|
$list=explode(PHP_EOL, file_get_contents(FILE_PATH."ranks/$rank.txt"));
|
|
foreach($list as $name){
|
|
$real=str_replace(array(" ", "\n", "\r"), array("", "", ""), strtolower($name));
|
|
if(substr($name, 0, 1)!=="#" and strtoupper(substr($name, 0, 4))!=="REM " and strlen($real)> 3 and !in_array($real, $this->ranks[$rank]))
|
|
$this->ranks[$rank][]=$real;;
|
|
}
|
|
}
|
|
}
|
|
public function getRank($name){
|
|
$name=strtolower("$name");
|
|
foreach($this->ranks as $rank=>$names){
|
|
if(in_array($name, $names))
|
|
return $rank;
|
|
}
|
|
return "guest";
|
|
}
|
|
public function getRankIndex($name){
|
|
return self::$rankValues[$name];
|
|
}
|
|
public function getRankByIndex($idx){
|
|
return array_search(self::$rankValues);
|
|
}
|
|
public static $rankValues=array("dangerous"=>-5, "guest"=>0, "vip-lite"=>10, "vip"=>15, "vip-plus"=>20, "vip-star"=>25, "vip-hyper"=>30, "trust"=>100);
|
|
}
|
|
class TeamMgr{
|
|
public $teams;
|
|
public function __construct(){
|
|
@mkdir(FILE_PATH."teams/");
|
|
for($i=0; $i<4; $i++){
|
|
$path=FILE_PATH."teams/team-$i.yml";
|
|
$exist=file_exists($path);
|
|
if(defined("CONFIG_YAML"))
|
|
eval("\$yaml=CONFIG_YAML;");
|
|
else eval("\$yaml=Config::YAML"); // API update
|
|
$this->teams[$i]=new Team($path, $yaml, array(
|
|
"name" => $this->getNames($i)[0],
|
|
"points" => 1000, // prevent division by zero error
|
|
"total players count" => 1, // fix division by zero error
|
|
));
|
|
}
|
|
// ServerAPI::request()->schedule(20, array($this, "updateSigns"), array(), true);
|
|
}
|
|
public function getTeam($team){
|
|
return $this->teams[$team&0x03];
|
|
}
|
|
public function getNames($id){
|
|
if($id===-1)
|
|
return array("new player");
|
|
switch($id&0b11){
|
|
case 0b00:
|
|
return array("magma", "red", );
|
|
case 0b01:
|
|
return array("lapiz", "blue", );
|
|
case 0b10:
|
|
return array("lilac", "violet", "purple", );
|
|
case 0b11:
|
|
return array("lime", "green", );
|
|
}
|
|
}
|
|
public function updateBars(){
|
|
$scores=array();
|
|
foreach($this->teams as $team)
|
|
$scores[]=$team->get("points");
|
|
$max=max($scores);
|
|
$maxBlocks=LegionPE::getMaxScoreBarLength();
|
|
$direction=LegionPE::getScoreBarDirection();//return "x" or "z"
|
|
$ratio=$maxBlocks/$max;
|
|
for($team=0; $team<4; $team++){
|
|
$start=LegionPE::getScoreBarStartPos($team);
|
|
for($i=0; $i<$maxBlocks; $i++){ // reset
|
|
$temp=$start;
|
|
$temp->addDir($direction, $i);
|
|
$temp->setBlock(BlockAPI::get(0), false);
|
|
}
|
|
}
|
|
foreach($scores as $team=>$score){
|
|
$length=(int)($score*$ratio);
|
|
$start=LegionPE::getScoreBarStartPos($team); // return new MyPosition($x, $y, $z, $this->api->level->get("world"));
|
|
for($i=0; $i<=$length; $i++){
|
|
$temp=$start;
|
|
$temp->addDir($direction, $i);
|
|
$temp->setBlock(BlockAPI::get(WOOL, $this->getTeamColor($team)), false);
|
|
}
|
|
}
|
|
}
|
|
public function getTeamColor($team){
|
|
switch($team){
|
|
case 0:
|
|
return 1;
|
|
case 1:
|
|
return 3;
|
|
case 2:
|
|
return 2;
|
|
case 3:
|
|
return 5;
|
|
}
|
|
}
|
|
public function updateSigns(){
|
|
$ppl=array();
|
|
foreach($this->teams as $data){
|
|
$ppl[]=$data->get("total players count");
|
|
}
|
|
$min=min($ppl);
|
|
$max=max($ppl);
|
|
foreach($this->teams as $team=>$data){
|
|
$loc=LegionPE::getChooseTeamSign($team);
|
|
$sign=Hub::request()->t->get($loc);
|
|
$name=strtoupper($this->getNames($team)[0]);
|
|
$cnt=$ppl[$team];
|
|
$can=true;
|
|
if(100*($cnt-$min)/$min > 5 and $ppl[$team] == $max)
|
|
$can=false;
|
|
if($can)
|
|
$sign->setText("Tap me to", "enter the team", "[TEAM $name]");
|
|
else
|
|
$sign->setText("[TEAM $name]", "is full. Come", "back later to", "join this team.");
|
|
}
|
|
}
|
|
public function joinTeam($team, Player $player){
|
|
if(ServerAPI::request()->api->tile->get(LegionPE::getChooseTeamSign(team))->data["Text1"] !== "Tap me to"){
|
|
$player->sendChat("This team is full! Come back later if you insist to join it.");
|
|
return false;
|
|
}
|
|
$this->teams[$team&0b11]->addPlayer();
|
|
Hub::request()->getPlayer($player)->cfg->set("team", $team&0b11);
|
|
$player->sendChat("Welcome to team ".$this->getNames($team)."!");
|
|
$player->teleport(LegionPE::getHubSpawn());
|
|
return true;
|
|
}
|
|
}
|
|
class MyPosition extends Position{
|
|
public function __construct($x, $y, $z, Level $level){
|
|
parent::__construct($x, $y, $z, $level);
|
|
}
|
|
public function addX($delta){
|
|
$this->x+=$delta;
|
|
}
|
|
public function addY($delta){
|
|
$this->y+=$delta;
|
|
}
|
|
public function addZ($delta){
|
|
$this->z+=$delta;
|
|
}
|
|
public function addDir($direction, $delta){
|
|
switch($direction){
|
|
case "x":
|
|
return $this->addX($delta);
|
|
case "y":
|
|
return $this->addY($delta);
|
|
case "z":
|
|
return $this->addZ($delta);
|
|
}
|
|
}
|
|
public function setBlock(Block $block, $update=true){
|
|
return $this->level->setBlock($this, $block, $update, false, true);
|
|
}
|
|
public function getBlock(){
|
|
return $this->level->getBlock($this);
|
|
}
|
|
public function equals(Vector3 $other){
|
|
$ret=true;
|
|
$ret=$ret and ($other->x===$this->x);
|
|
$ret=$ret and ($other->y===$this->y);
|
|
$ret=$ret and ($other->z===$this->z);
|
|
if($other instanceof Position)
|
|
$ret=$ret and ($other->level->getName()===$this->level->getName());
|
|
return $ret;
|
|
}
|
|
}
|
|
class Team extends Config{
|
|
public function __construct($path, $yml, $data){
|
|
parent::__construct($path, $yml, $data);
|
|
}
|
|
public function addPoints($delta){
|
|
$this->config["points"]+=$delta;
|
|
}
|
|
public function &getPoints(){
|
|
return $this->config["points"];
|
|
}
|
|
public function addPlayer(){
|
|
Hub::request()->teams->updateSigns();
|
|
return ++$this->config["total players count"];
|
|
}
|
|
}
|
|
class LegionPE{
|
|
public static function getTeamChoosingStandPoint(){
|
|
return new MyPosition(180, 128, 180, ServerAPI::request()->api->level->get("world"));
|
|
}
|
|
public static function getHubSpawn(){
|
|
return new MyPosition(128, 70, 128, ServerAPI::request()->api->level->get("world"));
|
|
}
|
|
public static function getMaxScoreBarLength(){
|
|
return 10;
|
|
}
|
|
public static function getScoreBarDirection(){
|
|
return "x"; // or "z"
|
|
}
|
|
public static function getScoreBarStartPos($team){
|
|
$team=$team&0b11;
|
|
return new MyPosition(128+5*$team, 18, 100);
|
|
}
|
|
public static function getChooseTeamSign($team){
|
|
return new MyPosition(128+($team&0b11), 99, 100);
|
|
}
|
|
}
|
|
class HubWorldMgr{
|
|
public function __construct($prefix0, $prefix1, $interval, $cnt, $evac, $notice=false){
|
|
$this->basePrefix=$prefix0;
|
|
$this->copyPrefix=$prefix1;
|
|
$this->interval=$interval;
|
|
$this->cnt=$cnt;
|
|
$this->evac=$evac; // evacuate site
|
|
if(is_array($notice)){
|
|
ServerAPI::request()->schedule($this->interval, array($this, "broadcast"), $notice[1], true);
|
|
$this->delay=$notice[0];
|
|
}
|
|
}
|
|
public function init(){
|
|
$this->regen(false);
|
|
ServerAPI::request()->schedule($this->delay, array($this, "schedule"));
|
|
}
|
|
public function schedule(){
|
|
ServerAPI::request()->schedule($this->interval, array($this, "regen"), true, true);
|
|
}
|
|
public function broadcast($msg){
|
|
for($i=0; $i<$this->cnt; $i++){
|
|
$api=ServerAPI::request()->api;
|
|
if(($l=$api->level->get($this->copyPrefix.$i)) instanceof Player){
|
|
foreach($api->player->getAll($l) as $p)
|
|
$p->sendChat($msg);
|
|
}
|
|
}
|
|
}
|
|
public function regen(boolean $del){
|
|
$api=ServerAPI::request()->api;
|
|
if($del){
|
|
for($i=0; $i<$this->cnt; $i++){
|
|
$name=$this->copyPrefix.$i;
|
|
if(($l=$api->level->get($name)) instanceof Level){
|
|
foreach($api->player->getAll($l) as $p){
|
|
if($this->evac instanceof Position)
|
|
$p->teleport($this->evac);
|
|
elseif($this->evac instanceof Level)
|
|
$p->teleport($this->evac->getSafeSpawn());
|
|
elseif(is_callable($this->evac))
|
|
call_user_func($this->evac, $p, $name);
|
|
elseif(is_string($this->evac) and (($l=$api->level->get($this->evac)) instanceof Level))
|
|
$p->teleport($l->getSafeSpawn());
|
|
}
|
|
$api->level->unloadLevel($l, true);
|
|
}
|
|
$this->delDir(FILE_PATH."worlds/$name/");
|
|
}
|
|
}
|
|
for($i=0; $i<$this->cnt; $i++){
|
|
$name=$this->copyPrefix.$i;
|
|
$this->copyDir(FILE_PATH."worlds/".$this->basePrefix.$i, FILE_PATH."worlds/$name/");
|
|
$api->level->loadLevel($name);
|
|
}
|
|
}
|
|
public function delDir($dir){
|
|
if(substr($dir, -1)!="/" and substr($dir, -1)!="\\")
|
|
$dir.="/";
|
|
$directory=dir($dir);
|
|
while(($file=$directory->read())!==false){
|
|
if(is_file($dir.$file))
|
|
unlink($dir.$file);
|
|
elseif(is_dir($dir.$file) and str_replace(array(".", "/"), array("", ""), $file)===""){
|
|
$this->delDir($dir.$file);
|
|
}
|
|
}
|
|
rmdir($dir);
|
|
}
|
|
public function copyDir($dir, $to){
|
|
if(substr($dir, -1)!="/" and substr($dir, -1)!="\\")
|
|
$dir.="/";
|
|
$directory=dir($dir);
|
|
while(($file=$directory->read())!==false){
|
|
if(is_file($dir.$file))
|
|
copy($dir.$file, $to.$file);
|
|
elseif(is_dir($dir.$file) and str_replace(array(".", "/"), array("", ""), $file)===""){
|
|
$this->copyDir($dir.$file, $to.$file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
class MySpace{
|
|
public $start, $end;
|
|
public function __construct(Vector3 $start, Vector3 $end, Level $level){
|
|
$this->start=new Position(
|
|
min($start->x, $end->x),
|
|
min($start->y, $end->y),
|
|
min($start->z, $end->z),
|
|
$level
|
|
);
|
|
$this->start=new Position(
|
|
max($start->x, $end->x),
|
|
max($start->y, $end->y),
|
|
max($start->z, $end->z),
|
|
$level
|
|
);
|
|
}
|
|
public function isInSpace(Position $p){
|
|
return $this->isInside($p);
|
|
}
|
|
public function isInside(Position $pos){
|
|
return ($pos->x>$this->start->x and $pos->x<$this->end->x
|
|
and $pos->y>$this->start->y and $pos->y<$this->end->y
|
|
and $pos->z>$this->start->z and $pos->z>$thsi->end->z
|
|
and $pos->level->getName()===$this->end->level->getName());
|
|
}
|
|
}
|
I will not load the Disguise one, don't worry.