mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 11:16:57 +00:00
Compare commits
141 Commits
Alpha_1.0.
...
Alpha_1.0.
Author | SHA1 | Date | |
---|---|---|---|
de44ef742d | |||
386decf268 | |||
6cd51dbbf6 | |||
bf5df18170 | |||
b589b69beb | |||
1152c24bdf | |||
039011d9bb | |||
ef76138a1c | |||
c049b5fb72 | |||
aef32f2012 | |||
0fa3dded89 | |||
7723e3784f | |||
e4bf449198 | |||
23600349d1 | |||
8c92bc7c14 | |||
834d6719c7 | |||
bff4d92bcd | |||
937888a655 | |||
08499720f5 | |||
0d3cf74636 | |||
1d9e1fde79 | |||
a24da0e5ad | |||
a5229cc34e | |||
ed61111aca | |||
1409a1f7b5 | |||
78bfe7ce24 | |||
a6b9a9baff | |||
136fd205f0 | |||
aa92e83733 | |||
4067aff8e1 | |||
dfa8288ec9 | |||
3d1d3e89ea | |||
d6ab1a9a87 | |||
fe7595e313 | |||
4ddb8a298b | |||
3938db7c4f | |||
475419b693 | |||
d147caa913 | |||
ea26c32204 | |||
f79c6cf2e9 | |||
cac2a3a6e5 | |||
17161d7cd0 | |||
d988b27b16 | |||
fe70af47dc | |||
858cd5cb41 | |||
d306c8f713 | |||
310701f7e9 | |||
8bc40d2d9c | |||
cd05434853 | |||
3b10613f98 | |||
f47fa6d5dc | |||
29cd858622 | |||
aa22acee5f | |||
2d3580fd22 | |||
d3d2721f84 | |||
ce3dcf4cf4 | |||
3813ef73ea | |||
2ddb626edb | |||
6a97750e06 | |||
4b1f1cfd44 | |||
ac570213a5 | |||
44e53ccc1b | |||
bf1d78d1e4 | |||
d0cff39aa3 | |||
109b44a205 | |||
ce7c7efc79 | |||
dff26611e5 | |||
6d90249fbd | |||
74fa32dfa9 | |||
eacaf139c2 | |||
c23081e713 | |||
2ba2116498 | |||
07ac028558 | |||
7e4692aaf1 | |||
baec22208f | |||
62a7461bbd | |||
4df7aed15d | |||
d733eb6b4a | |||
e4d71949e3 | |||
4bda101ab8 | |||
b74c089ce7 | |||
02950474af | |||
b398b9daa2 | |||
b2731261e5 | |||
03c8c91b46 | |||
13f4f3285f | |||
8bc115a2ab | |||
2665dffdd8 | |||
ab2b519c2e | |||
6ab08020c3 | |||
107d71f291 | |||
09c2c1b2ee | |||
f3e9d4df31 | |||
d86bf37def | |||
5753db627c | |||
6102efc809 | |||
8d3ad0c5ec | |||
eebbc263b0 | |||
d5d319fb7c | |||
03db7c8738 | |||
2801f18753 | |||
b9b0039cd7 | |||
cd3aaa1b50 | |||
902cee1107 | |||
ab5481a392 | |||
f11bc82b86 | |||
0cd8479026 | |||
90d9099b3c | |||
47e80151e6 | |||
19aa4bd527 | |||
a6ddba8d97 | |||
3a110bf8b6 | |||
18bab3b045 | |||
89c0702a47 | |||
21594d699d | |||
b1b16bc366 | |||
aa1a39adfc | |||
b3b38605b5 | |||
7030f9118d | |||
b150d4e001 | |||
125f1c11b4 | |||
82f2a0f2f8 | |||
700314d75a | |||
54e6bd0ee9 | |||
fd1186061f | |||
f03f376535 | |||
586f49994a | |||
c1aec49ad1 | |||
683c05f206 | |||
9ebe68294b | |||
c2a45212dd | |||
344449fa12 | |||
732ee755e8 | |||
f0393f9b93 | |||
f23c2f894d | |||
85dfb651bd | |||
b5e6130214 | |||
957f24c1f3 | |||
518afeae48 | |||
57282225d2 | |||
369f268b90 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,6 +6,7 @@ logs/*
|
||||
server.properties
|
||||
white-list.txt
|
||||
banned-ips.txt
|
||||
banned.txt
|
||||
|
||||
#################
|
||||
## Eclipse
|
||||
|
@ -25,15 +25,11 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
*/
|
||||
|
||||
require_once("src/common/dependencies.php");
|
||||
require_once("classes/PocketMinecraftServer.class.php");
|
||||
require_once(dirname(__FILE__)."/src/common/dependencies.php");
|
||||
require_once("API/ServerAPI.php");
|
||||
|
||||
$server = new ServerAPI();
|
||||
if($server->start() !== true){
|
||||
//Stop
|
||||
}else{
|
||||
//Restart
|
||||
}
|
||||
$server->run();//$server->start();
|
||||
//$server->join();
|
||||
|
||||
kill(getmypid()); //Fix for segfault
|
62
README.md
62
README.md
@ -1,3 +1,7 @@
|
||||

|
||||
|
||||
# PocketMine-MP
|
||||
|
||||
```
|
||||
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
|
||||
@ -11,61 +15,33 @@ GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
```
|
||||
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ PocketMine \
|
||||
/ MP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
```
|
||||
|
||||
# PocketMine-MP
|
||||
|
||||
PocketMine-MP is a Server for Minecraft Pocket Edition done in PHP. It has a Plugin API that enables a developer to extend it and add new features, or change default ones.
|
||||
__PocketMine-MP is a Server for Minecraft Pocket Edition done in PHP__. It has a Plugin API that enables a developer to extend it and add new features, or change default ones.
|
||||
|
||||
The entire server is done in PHP, and has been tested, profiled and optimized to run smoothly.
|
||||
|
||||
[Go to Wiki for more information](https://github.com/shoghicp/PocketMine-MP/wiki)
|
||||
### [Homepage](http://shoghicp.github.com/PocketMine-MP/)
|
||||
|
||||
[FAQ: Frequently Asked Questions](https://github.com/shoghicp/PocketMine-MP/wiki/Frequently-Asked-Questions)
|
||||
### [Go to Wiki for more information](https://github.com/shoghicp/PocketMine-MP/wiki)
|
||||
|
||||
**Project Status: `ALPHA`**
|
||||
### [FAQ: Frequently Asked Questions](https://github.com/shoghicp/PocketMine-MP/wiki/Frequently-Asked-Questions)
|
||||
|
||||
**Tested in: `v4.0.0, v5.0.0`**
|
||||
### [@PocketMine](https://twitter.com/PocketMine)
|
||||
|
||||
|
||||
## Current features of the server:
|
||||
|
||||
* Full Creative mode!
|
||||
* Plugin API
|
||||
* Custom world generation
|
||||
* Update Channels!! (stable / dev)
|
||||
|
||||
|
||||
## How to contact me
|
||||
|
||||
* Email - <shoghicp@gmail.com>
|
||||
* Twitter - [@shoghicp](https://twitter.com/shoghicp)
|
||||
* Via IRC - #mcdevs or #mcpedevs on *irc.freenode.net* (or just /msg me there)
|
||||
* [MinecraftForums profile](http://www.minecraftforum.net/user/1476633-shoghicp/)
|
||||
### [Mailing List](https://groups.google.com/forum/#!forum/pocketmine-development) pocketmine-development@googlegroups.com
|
||||
|
||||
|
||||
## Third-party Libraries Used
|
||||
* __[PHP cURL](http://php.net/manual/en/book.curl.php)__
|
||||
* __[PHP Sockets](http://php.net/manual/en/book.sockets.php)__
|
||||
* __[PHP SQLite3](http://php.net/manual/en/book.sqlite3.php)__
|
||||
* __[PHP pthreads](https://github.com/krakjoe/pthreads)__ by _[krakjoe](https://github.com/krakjoe)_: Threading for PHP - Share Nothing, Do Everything
|
||||
* __[PHP NBT](https://github.com/TheFrozenFire/PHP-NBT-Decoder-Encoder/blob/master/nbt.class.php)__ by _[TheFrozenFire](https://github.com/TheFrozenFire)_: Class for reading in NBT-format files (modified to handle Little-Endian files)
|
||||
* __[PHP pthreads](https://github.com/krakjoe/pthreads)__ by _[krakjoe](https://github.com/krakjoe)_: Threading for PHP - Share Nothing, Do Everything.
|
||||
* __[PHP NBT](https://github.com/TheFrozenFire/PHP-NBT-Decoder-Encoder/blob/master/nbt.class.php)__ by _[TheFrozenFire](https://github.com/TheFrozenFire)_: Class for reading in NBT-format files (modified to handle Little-Endian files).
|
||||
* __[Math_BigInteger](http://phpseclib.sourceforge.net/math/intro.html)__ by _[phpseclib](http://phpseclib.sourceforge.net/)_: Pure-PHP arbitrary precission integer arithmetic library
|
||||
* __[Spyc](https://github.com/mustangostang/spyc/blob/master/Spyc.php)__ by _[Vlad Andersen](https://github.com/mustangostang)_: A simple YAML loader/dumper class for PHP
|
||||
* __[Spyc](https://github.com/mustangostang/spyc/blob/master/Spyc.php)__ by _[Vlad Andersen](https://github.com/mustangostang)_: A simple YAML loader/dumper class for PHP.
|
||||
* __[ANSICON](https://github.com/adoxa/ansicon)__ by _[Jason Hood](https://github.com/adoxa)_: Process ANSI escape sequences for Windows console programs.
|
||||
|
||||
|
||||
## IRC #mcpedevs @ irc.freenode.net
|
||||
* [WebIRC](http://webchat.freenode.net?channels=mcpedevs&uio=d4)
|
210
compile_php.sh
210
compile_php.sh
@ -1,74 +1,156 @@
|
||||
#!/bin/bash
|
||||
echo "[INFO] PocketMine-MP PHP compiler for Linux - by @shoghicp v0.1"
|
||||
if [ "$(whoami)" != 'root' ]; then
|
||||
echo "[ERROR] You must be root to run this script"
|
||||
exit 1;
|
||||
fi
|
||||
echo "[PocketMine] PHP installer and compiler for Linux - by @shoghicp v0.3"
|
||||
DIR=`pwd`
|
||||
mkdir -m 0777 install_data
|
||||
mkdir -m 0777 php5
|
||||
date > $DIR/install.log 2>&1
|
||||
uname -a >> $DIR/install.log 2>&1
|
||||
echo "[INFO] Checking dependecies"
|
||||
type make >> $DIR/install.log 2>&1 || { echo >&2 "[ERROR] Please install \"make\""; exit 1; }
|
||||
type autoconf >> $DIR/install.log 2>&1 || { echo >&2 "[ERROR] Please install \"autoconf\""; exit 1; }
|
||||
type automake >> $DIR/install.log 2>&1 || { echo >&2 "[ERROR] Please install \"automake\""; exit 1; }
|
||||
type gcc >> $DIR/install.log 2>&1 || { echo >&2 "[ERROR] Please install \"gcc\""; exit 1; }
|
||||
type m4 >> $DIR/install.log 2>&1 || { echo >&2 "[ERROR] Please install \"m4\""; exit 1; }
|
||||
rm -r -f install_data/ >> $DIR/install.log 2>&1
|
||||
rm -r -f php5/ >> $DIR/install.log 2>&1
|
||||
mkdir -m 0777 install_data >> $DIR/install.log 2>&1
|
||||
mkdir -m 0777 php5 >> $DIR/install.log 2>&1
|
||||
cd install_data
|
||||
apt-get -f -y install
|
||||
apt-get -y install \
|
||||
php5-cli \
|
||||
php5-common \
|
||||
php5-curl \
|
||||
php5-gd \
|
||||
php5-gmp \
|
||||
php5-mcrypt \
|
||||
build-essential \
|
||||
git-core \
|
||||
libxml2-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libjpeg-dev \
|
||||
libpng-dev \
|
||||
libmysqlclient-dev \
|
||||
libfreetype6-dev \
|
||||
libmcrypt-dev \
|
||||
libmhash-dev
|
||||
wget ftp://ftp.gmplib.org/pub/gmp-5.1.0/gmp-5.1.0.tar.bz2 -O gmp-5.1.0.tar.bz2
|
||||
tar -jxvf gmp-5.1.0.tar.bz2
|
||||
cd gmp-5.1.0
|
||||
./configure
|
||||
make
|
||||
make check
|
||||
make install
|
||||
wget http://php.net/get/php-5.4.10.tar.gz/from/this/mirror -O php-5.4.10.tar.gz
|
||||
tar -zxvf php-5.4.10.tar.gz
|
||||
cd php-5.4.10
|
||||
cd ext
|
||||
git clone https://github.com/krakjoe/pthreads.git
|
||||
cd ../
|
||||
./buildconf --force
|
||||
|
||||
#PHP 5
|
||||
echo -n "[PHP5] downloading..."
|
||||
wget http://php.net/get/php-5.4.11.tar.gz/from/this/mirror -O php-5.4.11.tar.gz >> $DIR/install.log 2>&1
|
||||
echo -n " extracting..."
|
||||
tar -zxvf php-5.4.11.tar.gz >> $DIR/install.log 2>&1
|
||||
rm -f php-5.4.11.tar.gz >> $DIR/install.log 2>&1
|
||||
mv php-5.4.11 php
|
||||
echo " done!"
|
||||
|
||||
#zlib
|
||||
echo -n "[zlib] downloading..."
|
||||
wget http://zlib.net/zlib-1.2.7.tar.gz -O zlib-1.2.7.tar.gz >> $DIR/install.log 2>&1
|
||||
echo -n " extracting..."
|
||||
tar -zxvf zlib-1.2.7.tar.gz >> $DIR/install.log 2>&1
|
||||
rm -f zlib-1.2.7.tar.gz >> $DIR/install.log 2>&1
|
||||
mv zlib-1.2.7 zlib
|
||||
echo -n " checking..."
|
||||
cd zlib
|
||||
./configure --prefix=$DIR/install_data/php/ext/zlib \
|
||||
--static >> $DIR/install.log 2>&1
|
||||
echo -n " compiling..."
|
||||
make >> $DIR/install.log 2>&1
|
||||
echo -n " installing..."
|
||||
make install >> $DIR/install.log 2>&1
|
||||
echo -n " cleaning..."
|
||||
cd ..
|
||||
rm -r -f ./zlib
|
||||
echo " done!"
|
||||
|
||||
#OpenSSL
|
||||
#echo -n "[OpenSSL] downloading..."
|
||||
#wget ftp://ftp.openssl.org/source/openssl-1.0.1c.tar.gz -O openssl-1.0.1c.tar.gz >> $DIR/install.log 2>&1
|
||||
#echo -n " extracting..."
|
||||
#tar -zxvf openssl-1.0.1c.tar.gz >> $DIR/install.log 2>&1
|
||||
#rm -f openssl-1.0.1c.tar.gz >> $DIR/install.log 2>&1
|
||||
#mv openssl-1.0.1c openssl
|
||||
#echo -n " checking..."
|
||||
#cd openssl
|
||||
#./config --prefix=$DIR/install_data/php/ext/openssl >> $DIR/install.log 2>&1
|
||||
#echo -n " compiling..."
|
||||
#make >> $DIR/install.log 2>&1
|
||||
#echo -n " installing..."
|
||||
#make install >> $DIR/install.log 2>&1
|
||||
#echo -n " cleaning..."
|
||||
#cd ..
|
||||
#rm -r -f ./openssl
|
||||
#echo " done!"
|
||||
|
||||
#GMP
|
||||
echo -n "[GMP] downloading..."
|
||||
wget ftp://ftp.gmplib.org/pub/gmp-5.1.0/gmp-5.1.0.tar.bz2 -O gmp-5.1.0.tar.bz2 >> $DIR/install.log 2>&1
|
||||
echo -n " extracting..."
|
||||
tar -jxvf gmp-5.1.0.tar.bz2 >> $DIR/install.log 2>&1
|
||||
rm -f gmp-5.1.0.tar.bz2 >> $DIR/install.log 2>&1
|
||||
mv gmp-5.1.0 gmp
|
||||
echo -n " checking..."
|
||||
cd gmp
|
||||
./configure --prefix=$DIR/install_data/php/ext/gmp \
|
||||
--disable-shared >> $DIR/install.log 2>&1
|
||||
echo -n " compiling..."
|
||||
make >> $DIR/install.log 2>&1
|
||||
echo -n " installing..."
|
||||
make install >> $DIR/install.log 2>&1
|
||||
echo -n " cleaning..."
|
||||
cd ..
|
||||
rm -r -f ./gmp
|
||||
echo " done!"
|
||||
|
||||
echo -n "[cURL] downloading..."
|
||||
wget https://github.com/bagder/curl/archive/master.tar.gz --no-check-certificate -O curl-master.tar.gz >> $DIR/install.log 2>&1
|
||||
echo -n " extracting..."
|
||||
tar -zxvf curl-master.tar.gz >> $DIR/install.log 2>&1
|
||||
rm -f curl-master.tar.gz >> $DIR/install.log 2>&1
|
||||
mv curl-master curl
|
||||
echo -n " checking..."
|
||||
cd curl
|
||||
./buildconf >> $DIR/install.log 2>&1
|
||||
./configure --prefix=$DIR/install_data/php/ext/curl \
|
||||
--disable-shared >> $DIR/install.log 2>&1
|
||||
echo -n " compiling..."
|
||||
make >> $DIR/install.log 2>&1
|
||||
echo -n " installing..."
|
||||
make install >> $DIR/install.log 2>&1
|
||||
echo -n " cleaning..."
|
||||
cd ..
|
||||
rm -r -f ./curl
|
||||
echo " done!"
|
||||
|
||||
#pthreads
|
||||
echo -n "[PHP pthreads] downloading..."
|
||||
wget https://github.com/krakjoe/pthreads/archive/master.tar.gz --no-check-certificate -O pthreads-master.tar.gz >> $DIR/install.log 2>&1
|
||||
echo -n " extracting..."
|
||||
tar -zxvf pthreads-master.tar.gz >> $DIR/install.log 2>&1
|
||||
rm -f pthreads-master.tar.gz >> $DIR/install.log 2>&1
|
||||
mv pthreads-master $DIR/install_data/php/ext/pthreads
|
||||
echo " done!"
|
||||
|
||||
#--with-openssl=$DIR/install_data/php/ext/openssl
|
||||
echo -n "[PHP5] checking..."
|
||||
cd php
|
||||
./buildconf --force >> $DIR/install.log 2>&1
|
||||
./configure --prefix=$DIR/php5 \
|
||||
--exec-prefix=$DIR/php5 \
|
||||
--enable-embedded-mysqli \
|
||||
--with-openssl \
|
||||
--with-mcrypt \
|
||||
--with-mhash \
|
||||
--enable-exif \
|
||||
--with-freetype-dir \
|
||||
--enable-calendar \
|
||||
--enable-soap \
|
||||
--enable-mbstring \
|
||||
--enable-bcmath \
|
||||
--enable-gd-native-ttf \
|
||||
--with-gmp \
|
||||
--with-curl \
|
||||
--enable-zip \
|
||||
--with-gd \
|
||||
--with-jpeg-dir \
|
||||
--with-png-dir \
|
||||
--with-mysql \
|
||||
--with-mcrypt \
|
||||
--with-zlib \
|
||||
--with-gmp=$DIR/install_data/php/ext/gmp \
|
||||
--with-curl=$DIR/install_data/php/ext/curl \
|
||||
--with-zlib=$DIR/install_data/php/ext/zlib \
|
||||
--disable-libxml \
|
||||
--disable-xml \
|
||||
--disable-dom \
|
||||
--disable-simplexml \
|
||||
--disable-xmlreader \
|
||||
--disable-xmlwriter \
|
||||
--without-pear \
|
||||
--disable-cgi \
|
||||
--disable-session \
|
||||
--enable-ctype \
|
||||
--without-iconv \
|
||||
--without-pdo-sqlite \
|
||||
--enable-sockets \
|
||||
--enable-shared=no \
|
||||
--enable-static=yes \
|
||||
--enable-pcntl \
|
||||
--enable-pthreads \
|
||||
--enable-maintainer-zts
|
||||
make
|
||||
echo "n" | make test
|
||||
make install
|
||||
--enable-maintainer-zts \
|
||||
--enable-cli >> $DIR/install.log 2>&1
|
||||
echo -n " compiling..."
|
||||
make >> $DIR/install.log 2>&1
|
||||
echo -n " installing..."
|
||||
make install >> $DIR/install.log 2>&1
|
||||
echo " done!"
|
||||
cd $DIR
|
||||
rm -r -f install_data/
|
||||
rmdir install_data/
|
||||
echo "[INFO] Compilation Completed!"
|
||||
echo -n "[INFO] Cleaning up..."
|
||||
rm -r -f install_data/ >> $DIR/install.log 2>&1
|
||||
date >> $DIR/install.log 2>&1
|
||||
echo " done!"
|
||||
echo "[PocketMine] You should start the server now using \"./start.sh\""
|
||||
echo "[PocketMine] If it doesn't works, please send the \"install.log\" file to the Bug Tracker"
|
216
src/API/BanAPI.php
Normal file
216
src/API/BanAPI.php
Normal file
@ -0,0 +1,216 @@
|
||||
<?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 BanAPI{
|
||||
private $server;
|
||||
private $whitelist;
|
||||
private $banned;
|
||||
private $bannedIPs;
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
public function init(){
|
||||
console("[INFO] Loading authentication lists...");
|
||||
$this->whitelist = new Config(FILE_PATH."white-list.txt", CONFIG_LIST);
|
||||
$this->bannedIPs = new Config(FILE_PATH."banned-ips.txt", CONFIG_LIST);
|
||||
$this->banned = new Config(FILE_PATH."banned.txt", CONFIG_LIST);
|
||||
$this->server->api->console->register("banip", "Manages IP Banning", array($this, "commandHandler"));
|
||||
$this->server->api->console->register("ban", "Manages Bannning", array($this, "commandHandler"));
|
||||
$this->server->api->console->register("kick", "Kicks a player", array($this, "commandHandler"));
|
||||
$this->server->api->console->register("whitelist", "Manages White-listing", array($this, "commandHandler"));
|
||||
}
|
||||
|
||||
public function commandHandler($cmd, $params){
|
||||
switch($cmd){
|
||||
case "kick":
|
||||
if(!isset($params[0])){
|
||||
console("[INFO] Usage: /kick <playername> [reason]");
|
||||
}else{
|
||||
$name = array_shift($params);
|
||||
$player = $this->server->api->player->get($name);
|
||||
if($player === false){
|
||||
console("[ERROR] Player \"".$name."\" does not exist");
|
||||
}else{
|
||||
$reason = implode(" ", $params);
|
||||
$reason = $reason == "" ? "No reason":$reason;
|
||||
$player->close("You have been kicked: ".$reason);
|
||||
console("[INFO] Player \"".$player->username."\" has been kicked: $reason");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "whitelist":
|
||||
$p = strtolower(array_shift($params));
|
||||
switch($p){
|
||||
case "remove":
|
||||
$user = trim(implode(" ", $params));
|
||||
$this->whitelist->remove($user);
|
||||
$this->whitelist->save();
|
||||
console("[INFO] Player \"$user\" removed from white-list");
|
||||
break;
|
||||
case "add":
|
||||
$user = trim(implode(" ", $params));
|
||||
$this->whitelist->set($user);
|
||||
$this->whitelist->save();
|
||||
console("[INFO] Player \"$user\" added to white-list");
|
||||
break;
|
||||
case "reload":
|
||||
$this->whitelist = $this->load(FILE_PATH."white-list.txt", CONFIG_LIST);
|
||||
break;
|
||||
case "list":
|
||||
console("[INFO] White-list: ".implode(", ", $this->whitelist->getAll(true)));
|
||||
break;
|
||||
case "on":
|
||||
case "true":
|
||||
case "1":
|
||||
console("[INFO] White-list turned on");
|
||||
$this->server->api->setProperty("white-list", true);
|
||||
break;
|
||||
case "off":
|
||||
case "false":
|
||||
case "0":
|
||||
console("[INFO] White-list turned off");
|
||||
$this->server->api->setProperty("white-list", false);
|
||||
break;
|
||||
default:
|
||||
console("[INFO] Usage: /whitelist <on | off | add | remove | reload | list> [username]");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "banip":
|
||||
$p = strtolower(array_shift($params));
|
||||
switch($p){
|
||||
case "pardon":
|
||||
case "remove":
|
||||
$ip = trim(implode($params));
|
||||
$this->bannedIPs->remove($ip);
|
||||
$this->bannedIPs->save();
|
||||
console("[INFO] IP \"$ip\" removed from ban list");
|
||||
break;
|
||||
case "add":
|
||||
case "ban":
|
||||
$ip = trim(implode($params));
|
||||
$this->bannedIPs->set($ip);
|
||||
$this->bannedIPs->save();
|
||||
console("[INFO] IP \"$ip\" added to ban list");
|
||||
break;
|
||||
case "reload":
|
||||
$this->bannedIPs = new Config(FILE_PATH."banned-ips.txt", CONFIG_LIST);
|
||||
break;
|
||||
case "list":
|
||||
console("[INFO] IP ban list: ".implode(", ", $this->bannedIPs->getAll(true)));
|
||||
break;
|
||||
default:
|
||||
console("[INFO] Usage: /banip <add | remove | list | reload> [IP]");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "ban":
|
||||
$p = strtolower(array_shift($params));
|
||||
switch($p){
|
||||
case "pardon":
|
||||
case "remove":
|
||||
$user = trim(implode($params));
|
||||
$this->banned->remove($user);
|
||||
$this->banned->save();
|
||||
console("[INFO] Player \"$user\" removed from ban list");
|
||||
break;
|
||||
case "add":
|
||||
case "ban":
|
||||
$user = trim(implode($params));
|
||||
$this->banned->set($user);
|
||||
$this->banned->save();
|
||||
$player = $this->server->api->player->get($user);
|
||||
if($player !== false){
|
||||
$player->close("You have been banned");
|
||||
}
|
||||
$this->server->api->chat->broadcast("$user has been banned");
|
||||
console("[INFO] Player \"$user\" added to ban list");
|
||||
break;
|
||||
case "reload":
|
||||
$this->banned = new Config(FILE_PATH."banned.txt", CONFIG_LIST);
|
||||
break;
|
||||
case "list":
|
||||
console("[INFO] Ban list: ".implode(", ", $this->banned->getAll(true)));
|
||||
break;
|
||||
default:
|
||||
console("[INFO] Usage: /ban <add | remove | list | reload> [player]");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function ban($username){
|
||||
$this->commandHandler("ban", array("add", $username));
|
||||
}
|
||||
|
||||
public function pardon($username){
|
||||
$this->commandHandler("ban", array("pardon", $username));
|
||||
}
|
||||
|
||||
public function banIP($ip){
|
||||
$this->commandHandler("banip", array("add", $ip));
|
||||
}
|
||||
|
||||
public function pardonIP($ip){
|
||||
$this->commandHandler("banip", array("pardon", $ip));
|
||||
}
|
||||
|
||||
public function reload(){
|
||||
$this->commandHandler("ban", array("reload"));
|
||||
$this->commandHandler("banip", array("reload"));
|
||||
$this->commandHandler("whitelist", array("reload"));
|
||||
}
|
||||
|
||||
public function isIPBanned($ip){
|
||||
if($this->server->api->dhandle("api.ban.ip.check", $ip) === false){
|
||||
return true;
|
||||
}elseif($this->bannedIPs->exists($ip)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isBanned($username){
|
||||
if($this->server->api->dhandle("api.ban.check", $username) === false){
|
||||
return true;
|
||||
}elseif($this->banned->exists($username)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function inWhitelist($username){
|
||||
if($this->server->api->dhandle("api.ban.whitelist.check", $ip) === false){
|
||||
return true;
|
||||
}elseif($this->whitelist->exists($username)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -37,15 +37,50 @@ class BlockAPI{
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
|
||||
public function init(){
|
||||
$this->server->addHandler("world.block.update", array($this, "updateBlockRemote"), 1);
|
||||
$this->server->addHandler("block.update", array($this, "updateBlockRemote"), 1);
|
||||
$this->server->addHandler("player.block.break", array($this, "blockBreak"), 1);
|
||||
$this->server->addHandler("player.block.action", array($this, "blockAction"), 1);
|
||||
$this->server->api->console->register("give", "Give items to a player", array($this, "commandHandler"));
|
||||
}
|
||||
|
||||
|
||||
public function commandHandler($cmd, $params){
|
||||
switch($cmd){
|
||||
case "give":
|
||||
if(!isset($params[0]) or !isset($params[1])){
|
||||
console("[INFO] Usage: /give <username> <item> [amount] [damage]");
|
||||
break;
|
||||
}
|
||||
$username = $params[0];
|
||||
$b = explode(":", $params[1]);
|
||||
if(!isset($b[1])){
|
||||
$meta = 0;
|
||||
}else{
|
||||
$meta = (int) $b[1];
|
||||
}
|
||||
$block = ((int) $b[0]) & 0xFFFF;
|
||||
if(!isset($params[2])){
|
||||
$amount = 64;
|
||||
}else{
|
||||
$amount = (int) $params[2];
|
||||
}
|
||||
if(isset($params[3])){
|
||||
$meta = (int) $params[3];
|
||||
}
|
||||
if(($player = $this->server->api->player->get($username)) !== false){
|
||||
$this->drop($player->entity->x - 0.5, $player->entity->y, $player->entity->z - 0.5, $block, $meta, $amount);
|
||||
console("[INFO] Giving ".$amount." of ".$block.":".$meta." to ".$username);
|
||||
}else{
|
||||
console("[INFO] Unknown player");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function cancelAction($block){
|
||||
$this->server->api->dhandle("world.block.change", array(
|
||||
$this->server->api->dhandle("block.change", array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2],
|
||||
@ -55,7 +90,7 @@ class BlockAPI{
|
||||
));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function blockBreak($data, $event){
|
||||
if($event !== "player.block.break"){
|
||||
return;
|
||||
@ -70,12 +105,29 @@ class BlockAPI{
|
||||
1, //Count
|
||||
);
|
||||
switch($target[0]){
|
||||
case 1:
|
||||
$drop[0] = 4;
|
||||
break;
|
||||
case 16:
|
||||
$drop = array(263, 0, 1);
|
||||
break;
|
||||
case 21:
|
||||
$drop = array(351, 4, mt_rand(4, 8));
|
||||
break;
|
||||
case 62:
|
||||
$drop[0] = 61;
|
||||
case 50: //Drop without metadata
|
||||
case 53:
|
||||
case 54:
|
||||
case 61:
|
||||
case 65:
|
||||
case 67:
|
||||
case 96:
|
||||
case 107:
|
||||
case 108:
|
||||
case 109:
|
||||
$drop[1] = 0;
|
||||
break;
|
||||
case 56:
|
||||
$drop = array(264, 0, 1);
|
||||
break;
|
||||
@ -125,22 +177,34 @@ class BlockAPI{
|
||||
2,
|
||||
);
|
||||
break;
|
||||
case 46: //TNT
|
||||
if(($player = $this->server->api->player->getByEID($data["eid"])) !== false){
|
||||
$player->dataPacket(MC_EXPLOSION, array(
|
||||
"x" => $data["x"],
|
||||
"y" => $data["y"],
|
||||
"z" => $data["z"],
|
||||
"radius" => 2,
|
||||
"records" => array(),
|
||||
));
|
||||
}
|
||||
break;
|
||||
case 60:
|
||||
case 2:
|
||||
$drop = array(3, 0, 1);
|
||||
break;
|
||||
case 64: //Door
|
||||
$drop = array(324, 0, 1);
|
||||
case 64: //Wood Door
|
||||
case 71: //Iron Door
|
||||
$drop = array(($target[0] === 64 ? 324:330), 0, 1);
|
||||
if(($target[1] & 0x08) === 0x08){
|
||||
$down = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
|
||||
if($down[0] === 64){
|
||||
if($down[0] === $target[0]){
|
||||
$data2 = $data;
|
||||
--$data2["y"];
|
||||
$this->server->trigger("player.block.break", $data2);
|
||||
}
|
||||
}else{
|
||||
$up = $this->server->api->level->getBlock($data["x"], $data["y"] + 1, $data["z"]);
|
||||
if($up[0] === 64){
|
||||
if($up[0] === $target[0]){
|
||||
$data2 = $data;
|
||||
++$data2["y"];
|
||||
$this->server->trigger("player.block.break", $data2);
|
||||
@ -154,7 +218,7 @@ class BlockAPI{
|
||||
$this->server->trigger("player.block.break", $data);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function drop($x, $y, $z, $block, $meta, $stack = 1){
|
||||
if($block === 0 or $stack <= 0 or $this->server->gamemode === 1){
|
||||
return;
|
||||
@ -167,12 +231,18 @@ class BlockAPI{
|
||||
"stack" => $stack,
|
||||
);
|
||||
$data["x"] += mt_rand(2, 8) / 10;
|
||||
$data["y"] += mt_rand(2, 8) / 10;
|
||||
$data["y"] += 0.19;
|
||||
$data["z"] += mt_rand(2, 8) / 10;
|
||||
$e = $this->server->api->entity->add(ENTITY_ITEM, $block, $data);
|
||||
$this->server->api->entity->spawnToAll($e->eid);
|
||||
if($this->server->api->handle("block.drop", $data) !== false){
|
||||
for($count = $stack; $count > 0; ){
|
||||
$data["stack"] = min(64, $count);
|
||||
$count -= $data["stack"];
|
||||
$e = $this->server->api->entity->add(ENTITY_ITEM, $block, $data);
|
||||
$this->server->api->entity->spawnToAll($e->eid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function blockAction($data, $event){
|
||||
if($event !== "player.block.action"){
|
||||
return;
|
||||
@ -180,16 +250,42 @@ class BlockAPI{
|
||||
if($data["face"] < 0 or $data["face"] > 5){
|
||||
return false;
|
||||
}
|
||||
$data["original"] = array($data["block"], $data["meta"]);
|
||||
$target = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"]);
|
||||
if($target[0] === 0){ //If no block exists
|
||||
$this->cancelAction($target);
|
||||
$block = $this->server->api->level->getBlockFace($target, $data["face"]);
|
||||
return $this->cancelAction($block);
|
||||
return $this->cancelAction($block);
|
||||
}
|
||||
|
||||
|
||||
$cancelPlace = false;
|
||||
if(isset(Material::$activable[$target[0]])){
|
||||
switch($target[0]){
|
||||
case 54:
|
||||
$cancelPlace = true;
|
||||
if($this->server->gamemode === 1){
|
||||
break;
|
||||
}
|
||||
$this->server->api->player->getByEID($data["eid"])->dataPacket(MC_CONTAINER_OPEN, array(
|
||||
"windowid" => 1,
|
||||
"type" => WINDOW_CHEST,
|
||||
"slots" => 27,
|
||||
"title" => "Chest",
|
||||
));
|
||||
break;
|
||||
case 61:
|
||||
case 62:
|
||||
$cancelPlace = true;
|
||||
if($this->server->gamemode === 1){
|
||||
break;
|
||||
}
|
||||
$this->server->api->player->getByEID($data["eid"])->dataPacket(MC_CONTAINER_OPEN, array(
|
||||
"windowid" => 1,
|
||||
"type" => WINDOW_FURNACE,
|
||||
"slots" => 3,
|
||||
"title" => "Furnace",
|
||||
));
|
||||
break;
|
||||
case 6:
|
||||
if($data["block"] === 351 and $data["meta"] === 0x0F){ //Bonemeal
|
||||
Sapling::growTree($this->server->api->level, $target, $target[1] & 0x03);
|
||||
@ -201,7 +297,7 @@ class BlockAPI{
|
||||
if($data["block"] === 292){ //Hoe
|
||||
$data["block"] = 60;
|
||||
$data["meta"] = 0;
|
||||
$this->server->handle("player.block.place", $data);
|
||||
$this->server->handle("player.block.update", $data);
|
||||
$cancelPlace = true;
|
||||
}
|
||||
case 59:
|
||||
@ -209,9 +305,9 @@ class BlockAPI{
|
||||
if($data["block"] === 351 and $data["meta"] === 0x0F){ //Bonemeal
|
||||
$data["block"] = $target[0];
|
||||
$data["meta"] = 0x07;
|
||||
$this->server->handle("player.block.place", $data);
|
||||
$this->server->handle("player.block.place", $data);
|
||||
$cancelPlace = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 64: //Door
|
||||
if(($target[1] & 0x08) === 0x08){
|
||||
@ -256,49 +352,68 @@ class BlockAPI{
|
||||
default:
|
||||
$cancelPlace = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($cancelPlace === true){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$replace = false;
|
||||
switch($target[0]){
|
||||
switch($data["block"]){
|
||||
case 44: //Slabs
|
||||
if($data["face"] !== 1){
|
||||
if($data["face"] === 0){
|
||||
break;
|
||||
}
|
||||
if(($target[1] & 0x07) === ($data["meta"] & 0x07)){
|
||||
$replace = true;
|
||||
$data["block"] = 43;
|
||||
$data["meta"] = $data["meta"] & 0x07;
|
||||
}elseif($data["face"] === 1){
|
||||
if(($target[1] & 0x07) === ($data["meta"] & 0x07) and $target[0] === 44){
|
||||
$replace = true;
|
||||
$data["block"] = 43;
|
||||
$data["meta"] = $data["meta"] & 0x07;
|
||||
}
|
||||
}else{
|
||||
$data2 = $data;
|
||||
BlockFace::setPosition($data2, $data["face"]);
|
||||
$b = $this->server->api->level->getBlock($data2["x"], $data2["y"], $data2["z"]);
|
||||
if($b[0] === 44 and ($b[1] & 0x07) === ($data["meta"] & 0x07) and $b[0] === 44){
|
||||
$data = $data2;
|
||||
$replace = true;
|
||||
$data["block"] = 43;
|
||||
$data["meta"] = $data["meta"] & 0x07;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if($replace === false){
|
||||
BlockFace::setPosition($data, $data["face"]);
|
||||
}
|
||||
|
||||
|
||||
if($data["y"] >= 127){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$block = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"]);
|
||||
|
||||
|
||||
if($replace === false and !isset(Material::$replaceable[$block[0]])){
|
||||
return $this->cancelAction($block);
|
||||
}
|
||||
|
||||
|
||||
if(isset(Material::$placeable[$data["block"]])){
|
||||
$data["block"] = Material::$placeable[$data["block"]] === true ? $data["block"]:Material::$placeable[$data["block"]];
|
||||
}else{
|
||||
return $this->cancelAction($block);
|
||||
}
|
||||
$entity = $this->server->api->entity->get($data["eid"]);
|
||||
if(($entity instanceof Entity) !== true){
|
||||
return $this->cancelAction($block); //No Entity WTF?
|
||||
}
|
||||
|
||||
$direction = $this->server->api->entity->get($data["eid"])->getDirection();
|
||||
|
||||
if(!isset(Material::$transparent[$data["block"]]) and $entity->inBlock($block[2][0], $block[2][1], $block[2][2])){
|
||||
return $this->cancelAction($block); //Entity in block
|
||||
}
|
||||
|
||||
$direction = $entity->getDirection();
|
||||
|
||||
switch($data["block"]){
|
||||
case 6:
|
||||
if($target[0] === 60){
|
||||
@ -306,7 +421,7 @@ class BlockAPI{
|
||||
}
|
||||
case 37:
|
||||
case 38:
|
||||
if($target[0] !== 2 and $target[0] !== 3){
|
||||
if(($target[0] !== 2 and $target[0] !== 3) or $data["face"] !== 1){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -327,7 +442,7 @@ class BlockAPI{
|
||||
$block2 = $this->server->api->level->getBlock($data["x"] + 1, $data["y"], $data["z"]);
|
||||
$block3 = $this->server->api->level->getBlock($data["x"] - 1, $data["y"], $data["z"]);
|
||||
if($block0[0] === 9 or $block0[0] === 8 or $block1[0] === 9 or $block1[0] === 8 or $block2[0] === 9 or $block2[0] === 8 or $block3[0] === 9 or $block3[0] === 8){
|
||||
|
||||
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
@ -385,6 +500,10 @@ class BlockAPI{
|
||||
$data["meta"] = $faces[$direction] & 0x03;
|
||||
break;
|
||||
case 64://Door placing
|
||||
case 71:
|
||||
if($data["face"] !== 1){
|
||||
return false;
|
||||
}
|
||||
$blockUp = $this->server->api->level->getBlock($data["x"], $data["y"] + 1, $data["z"]);
|
||||
$blockDown = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
|
||||
if(!isset(Material::$replaceable[$blockUp[0]]) or isset(Material::$transparent[$blockDown[0]])){
|
||||
@ -393,6 +512,16 @@ class BlockAPI{
|
||||
$data2 = $data;
|
||||
$data2["meta"] = 0x08;
|
||||
$data["meta"] = $direction & 0x03;
|
||||
$face = array(
|
||||
0 => 3,
|
||||
1 => 4,
|
||||
2 => 2,
|
||||
3 => 5,
|
||||
);
|
||||
$next = $this->server->api->level->getBlockFace($block, $face[(($direction + 2) % 4)]);
|
||||
if($next[0] === $data["block"]){ //Door hinge
|
||||
$data2["meta"] = $data2["meta"] | 0x01;
|
||||
}
|
||||
++$data2["y"];
|
||||
$this->server->handle("player.block.place", $data2);
|
||||
}
|
||||
@ -463,13 +592,13 @@ class BlockAPI{
|
||||
$this->server->handle("player.block.place", $data);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function blockScheduler($data){
|
||||
$this->updateBlock($data["x"], $data["y"], $data["z"], BLOCK_UPDATE_SCHEDULED);
|
||||
}
|
||||
|
||||
|
||||
public function updateBlockRemote($data, $event){
|
||||
if($event !== "world.block.update"){
|
||||
if($event !== "block.update"){
|
||||
return;
|
||||
}
|
||||
$this->updateBlock($data["x"], $data["y"], $data["z"], isset($data["type"]) ? $data["type"]:BLOCK_UPDATE_RANDOM);
|
||||
@ -506,14 +635,14 @@ class BlockAPI{
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], 10, $level | $down, false);
|
||||
return true;
|
||||
return true;
|
||||
}elseif(($source[1] & 0x08) === 0x08){
|
||||
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], $source[0], $source[1] & 0x07, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function flowWaterOn($source, $face){
|
||||
$down = 0;
|
||||
if($face === BlockFace::BOTTOM){
|
||||
@ -545,14 +674,14 @@ class BlockAPI{
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], 8, $level | $down, false);
|
||||
return true;
|
||||
return true;
|
||||
}elseif(($source[1] & 0x08) === 0x08){
|
||||
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], $source[0], $source[1] & 0x07, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function updateBlock($x, $y, $z, $type = BLOCK_UPDATE_NORMAL){
|
||||
$block = $this->server->api->level->getBlock($x, $y, $z);
|
||||
$changed = false;
|
||||
@ -626,7 +755,7 @@ class BlockAPI{
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], 0, 0, false);
|
||||
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], 0, 0, false);
|
||||
}else{
|
||||
$block[1] = ($block[1] & 0x08) | $level;
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
@ -668,7 +797,7 @@ class BlockAPI{
|
||||
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], $block[0], $block[1], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
case 11:
|
||||
@ -738,7 +867,7 @@ class BlockAPI{
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], 0, 0, false);
|
||||
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], 0, 0, false);
|
||||
}else{
|
||||
$block[1] = ($block[1] & 0x08) | $level;
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
@ -781,7 +910,7 @@ class BlockAPI{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case 74:
|
||||
if($type === BLOCK_UPDATE_SCHEDULED or $type === BLOCK_UPDATE_RANDOM){
|
||||
@ -810,7 +939,7 @@ class BlockAPI{
|
||||
$this->updateBlocksAround($x, $y, $z, $type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function updateBlocksAround($x, $y, $z, $type){
|
||||
$this->updateBlock($x + 1, $y, $z, $type);
|
||||
$this->updateBlock($x, $y + 1, $z, $type);
|
||||
|
@ -26,6 +26,26 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
class ChatAPI{
|
||||
|
||||
|
||||
private $server;
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
public function init(){
|
||||
|
||||
}
|
||||
|
||||
public function broadcast($message){
|
||||
$this->send(false, $message);
|
||||
}
|
||||
|
||||
public function send($owner, $text, $whitelist = false, $blacklist = false){
|
||||
$message = "";
|
||||
if($owner !== false){
|
||||
$message = "<".$owner."> ";
|
||||
}
|
||||
$message .= $text;
|
||||
console("[CHAT] ".$message);
|
||||
$this->server->handle("server.chat", new Container($message, $whitelist, $blacklist));
|
||||
}
|
||||
}
|
@ -33,22 +33,27 @@ class ConsoleAPI{
|
||||
$this->server = $server;
|
||||
$this->last = microtime(true);
|
||||
}
|
||||
|
||||
|
||||
public function init(){
|
||||
$this->event = $this->server->event("server.tick", array($this, "handle"));
|
||||
$this->loop = new ConsoleLoop;
|
||||
$this->loop->start();
|
||||
}
|
||||
|
||||
|
||||
function __destruct(){
|
||||
$this->server->deleteEvent($this->event);
|
||||
$this->loop->stop = true;
|
||||
$this->loop->notify();
|
||||
$this->loop->join();
|
||||
}
|
||||
|
||||
|
||||
public function defaultCommands($cmd, $params){
|
||||
switch($cmd){
|
||||
case "crash": //Crashes the server to generate an report
|
||||
$this->callNotDefinedMethodCrash();
|
||||
$this->server->api->server; //Access a private property
|
||||
callNotExistingFunction();
|
||||
break;
|
||||
case "invisible":
|
||||
$p = strtolower(array_shift($params));
|
||||
switch($p){
|
||||
@ -79,49 +84,9 @@ class ConsoleAPI{
|
||||
break;
|
||||
case "stop":
|
||||
$this->loop->stop = true;
|
||||
console("[INFO] Stopping the server...");
|
||||
console("[INFO] Stopping the server...");
|
||||
$this->server->close();
|
||||
break;
|
||||
/*case "restart":
|
||||
console("[INFO] Restarting the server...");
|
||||
$this->server->api->restart = true;
|
||||
$this->server->close();
|
||||
break;*/
|
||||
case "banip":
|
||||
$p = strtolower(array_shift($params));
|
||||
switch($p){
|
||||
case "pardon":
|
||||
case "remove":
|
||||
$ip = trim(implode($params));
|
||||
$new = array();
|
||||
foreach(explode("\n", str_replace(array("\r","\t"), "", file_get_contents(FILE_PATH."banned-ips.txt"))) as $i){
|
||||
if($i == $ip){
|
||||
console("[INFO] IP \"$ip\" removed from ban list");
|
||||
continue;
|
||||
}
|
||||
$new[$i] = $i;
|
||||
}
|
||||
file_put_contents(FILE_PATH."banned-ips.txt", implode("\r\n", $new));
|
||||
$this->server->reloadConfig();
|
||||
break;
|
||||
case "add":
|
||||
case "ban":
|
||||
$ip = trim(implode($params));
|
||||
file_put_contents(FILE_PATH."banned-ips.txt", "\r\n".$ip, FILE_APPEND);
|
||||
console("[INFO] IP \"$ip\" added to ban list");
|
||||
$this->server->reloadConfig();
|
||||
break;
|
||||
case "reload":
|
||||
$this->server->reloadConfig();
|
||||
break;
|
||||
case "list":
|
||||
console("[INFO] IP ban list: ".implode(", ", explode("\n", str_replace(array("\t","\r"), "", file_get_contents(FILE_PATH."banned-ips.txt")))));
|
||||
break;
|
||||
default:
|
||||
console("[INFO] Usage: /banip <add | remove | list | reload> [IP]");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "gamemode":
|
||||
$s = trim(array_shift($params));
|
||||
if($s == "" or (((int) $s) !== 0 and ((int) $s) !== 1)){
|
||||
@ -147,62 +112,11 @@ class ConsoleAPI{
|
||||
console("[INFO] Usage: /say <message>");
|
||||
break;
|
||||
}
|
||||
$this->server->chat(false, $s);
|
||||
break;
|
||||
case "whitelist":
|
||||
$p = strtolower(array_shift($params));
|
||||
switch($p){
|
||||
case "remove":
|
||||
$user = trim(implode(" ", $params));
|
||||
$new = array();
|
||||
foreach(explode("\n", str_replace(array("\r","\t"), "", file_get_contents(FILE_PATH."white-list.txt"))) as $u){
|
||||
if($u == $user){
|
||||
console("[INFO] Player \"$user\" removed from white-list");
|
||||
continue;
|
||||
}
|
||||
$new[$u] = $u;
|
||||
}
|
||||
file_put_contents(FILE_PATH."white-list.txt", implode("\r\n", $new));
|
||||
$this->server->reloadConfig();
|
||||
break;
|
||||
case "add":
|
||||
$user = trim(implode(" ", $params));
|
||||
file_put_contents(FILE_PATH."white-list.txt", "\r\n".$user, FILE_APPEND);
|
||||
console("[INFO] Player \"$user\" added to white-list");
|
||||
$this->server->reloadConfig();
|
||||
break;
|
||||
case "reload":
|
||||
$this->server->reloadConfig();
|
||||
break;
|
||||
case "list":
|
||||
console("[INFO] White-list: ".implode(", ", explode("\n", str_replace(array("\t","\r"), "", file_get_contents(FILE_PATH."white-list.txt")))));
|
||||
break;
|
||||
case "on":
|
||||
case "true":
|
||||
case "1":
|
||||
console("[INFO] White-list turned on");
|
||||
$this->server->api->setProperty("white-list", true);
|
||||
break;
|
||||
case "off":
|
||||
case "false":
|
||||
case "0":
|
||||
console("[INFO] White-list turned off");
|
||||
$this->server->api->setProperty("white-list", false);
|
||||
break;
|
||||
default:
|
||||
console("[INFO] Usage: /whitelist <on | off | add | remove | reload | list> [username]");
|
||||
break;
|
||||
}
|
||||
$this->server->api->chat->broadcast($s);
|
||||
break;
|
||||
case "save-all":
|
||||
$this->server->save();
|
||||
break;
|
||||
case "block":
|
||||
foreach($this->server->clients as $client){
|
||||
$b = $this->server->map->getBlock(round($client->entity->position["x"] - 0.5), round($client->entity->position["y"] - 1), round($client->entity->position["z"] - 0.5));
|
||||
console("[INFO] EID ".$client->eid." is over block ".$b[0].":".$b[1]);
|
||||
}
|
||||
break;
|
||||
case "help":
|
||||
case "?":
|
||||
console("[INFO] /help: Show available commands");
|
||||
@ -212,8 +126,6 @@ class ConsoleAPI{
|
||||
console("[INFO] /invisible: Manages server visibility");
|
||||
console("[INFO] /say: Broadcasts mesages");
|
||||
console("[INFO] /save-all: Saves pending changes");
|
||||
console("[INFO] /whitelist: Manages whitelisting");
|
||||
console("[INFO] /banip: Manages IP ban");
|
||||
console("[INFO] /stop: Stops the server");
|
||||
//console("[INFO] /restart: Restarts the server");
|
||||
foreach($this->help as $c => $h){
|
||||
@ -225,11 +137,15 @@ class ConsoleAPI{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function alias($alias, $cmd){
|
||||
if(!isset($this->cmds[$cmd])){
|
||||
return false;
|
||||
}
|
||||
$this->cmds[strtolower(trim($alias))] = &$this->cmds[$cmd];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function register($cmd, $help, $callback){
|
||||
if(!is_callable($callback)){
|
||||
return false;
|
||||
@ -239,20 +155,24 @@ class ConsoleAPI{
|
||||
$this->help[$cmd] = $help;
|
||||
}
|
||||
|
||||
public function run($line = ""){
|
||||
if($line != ""){
|
||||
$params = explode(" ", $line);
|
||||
$cmd = strtolower(array_shift($params));
|
||||
console("[INFO] Issued server command: /$cmd ".implode(" ", $params));
|
||||
if(isset($this->cmds[$cmd]) and is_callable($this->cmds[$cmd])){
|
||||
call_user_func($this->cmds[$cmd], $cmd, $params);
|
||||
}elseif($this->server->api->dhandle("api.console.command", array("cmd" => $cmd, "params" => $params)) !== false){
|
||||
$this->defaultCommands($cmd, $params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function handle($time){
|
||||
if($this->loop->line !== false){
|
||||
$line = trim($this->loop->line);
|
||||
$this->loop->line = false;
|
||||
if($line !== ""){
|
||||
$params = explode(" ", $line);
|
||||
$cmd = strtolower(array_shift($params));
|
||||
console("[INFO] Issued server command: /$cmd ".implode(" ", $params));
|
||||
if(isset($this->cmds[$cmd]) and is_callable($this->cmds[$cmd])){
|
||||
call_user_func($this->cmds[$cmd], $cmd, $params);
|
||||
}elseif($this->server->api->dhandle("api.console.command", array("cmd" => $cmd, "params" => $params)) !== false){
|
||||
$this->defaultCommands($cmd, $params);
|
||||
}
|
||||
}
|
||||
$this->run($line);
|
||||
}else{
|
||||
$this->loop->notify();
|
||||
}
|
||||
@ -261,7 +181,12 @@ class ConsoleAPI{
|
||||
}
|
||||
|
||||
class ConsoleLoop extends Thread{
|
||||
var $line = false, $stop = false;
|
||||
public $line, $stop;
|
||||
public function __construct(){
|
||||
$this->line = false;
|
||||
$this->stop = false;
|
||||
}
|
||||
|
||||
public function run(){
|
||||
$fp = fopen("php://stdin", "r");
|
||||
while($this->stop === false and ($line = fgets($fp)) !== false){
|
||||
|
@ -30,46 +30,6 @@ class EntityAPI{
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->server->addHandler("player.death", array($this, "handle"), 1);
|
||||
$this->server->api->console->register("give", "Give items to a player [DUMMY]", array($this, "commandHandler"));
|
||||
}
|
||||
|
||||
public function handle($data, $event){
|
||||
switch($event){
|
||||
case "player.death":
|
||||
$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){
|
||||
switch($cmd){
|
||||
case "give":
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function get($eid){
|
||||
if(isset($this->server->entities[$eid])){
|
||||
@ -78,28 +38,33 @@ class EntityAPI{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function init(){
|
||||
|
||||
}
|
||||
|
||||
public function getAll(){
|
||||
return $this->server->entities;
|
||||
}
|
||||
|
||||
|
||||
public function heal($eid, $heal = 1, $cause){
|
||||
$this->harm($eid, -$heal, $cause);
|
||||
}
|
||||
|
||||
|
||||
public function harm($eid, $attack = 1, $cause){
|
||||
$e = $this->get($eid);
|
||||
if($e === false or $e->dead === true){
|
||||
return false;
|
||||
}
|
||||
$e->setHealth($e->getHealth()-$attack, $cause);
|
||||
$e->setHealth($e->getHealth() - $attack, $cause);
|
||||
}
|
||||
|
||||
|
||||
public function add($class, $type = 0, $data = array()){
|
||||
$eid = $this->server->eidCnt++;
|
||||
$this->server->entities[$eid] = new Entity($this->server, $eid, $class, $type, $data);
|
||||
$this->server->handle("entity.add", $this->server->entities[$eid]);
|
||||
return $this->server->entities[$eid];
|
||||
}
|
||||
|
||||
|
||||
public function spawnTo($eid, $player){
|
||||
$e = $this->get($eid);
|
||||
if($e === false){
|
||||
@ -107,7 +72,7 @@ class EntityAPI{
|
||||
}
|
||||
$e->spawn($player);
|
||||
}
|
||||
|
||||
|
||||
public function spawnToAll($eid){
|
||||
$e = $this->get($eid);
|
||||
if($e === false){
|
||||
@ -119,17 +84,20 @@ class EntityAPI{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function spawnAll($player){
|
||||
foreach($this->getAll() as $e){
|
||||
$e->spawn($player);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function remove($eid){
|
||||
if(isset($this->server->entities[$eid])){
|
||||
$this->server->entities[$eid]->close();
|
||||
$entity = $this->server->entities[$eid];
|
||||
unset($this->server->entities[$eid]);
|
||||
$this->server->query("DELETE FROM entities WHERE EID = ".$entity->eid.";");
|
||||
$this->server->api->dhandle("entity.remove", $entity);
|
||||
unset($entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -32,13 +32,13 @@ class LevelAPI{
|
||||
$this->map = $this->server->map;
|
||||
$this->heightMap = array_fill(0, 256, array());
|
||||
}
|
||||
|
||||
|
||||
public function init(){
|
||||
$this->server->event("player.block.break", array($this, "handle"));
|
||||
$this->server->event("player.block.place", array($this, "handle"));
|
||||
$this->server->event("player.block.update", array($this, "handle"));
|
||||
}
|
||||
|
||||
|
||||
public function handle($data, $event){
|
||||
switch($event){
|
||||
case "player.block.place":
|
||||
@ -49,7 +49,6 @@ class LevelAPI{
|
||||
case "player.block.break":
|
||||
$block = $this->getBlock($data["x"], $data["y"], $data["z"]);
|
||||
console("[DEBUG] EID ".$data["eid"]." broke ".$block[0].":".$block[1]." at X ".$data["x"]." Y ".$data["y"]." Z ".$data["z"], true, true, 2);
|
||||
|
||||
if($block[0] === 0){
|
||||
break;
|
||||
}
|
||||
@ -57,38 +56,41 @@ class LevelAPI{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getSpawn(){
|
||||
return $this->server->spawn;
|
||||
}
|
||||
|
||||
public function getChunk($X, $Z){
|
||||
return $this->map->map[$X][$Z];
|
||||
return $this->map->map[$X][$Z];
|
||||
}
|
||||
|
||||
|
||||
public function getBlockFace($block, $face){
|
||||
$data = array("x" => $block[2][0], "y" => $block[2][1], "z" => $block[2][2]);
|
||||
BlockFace::setPosition($data, $face);
|
||||
return $this->getBlock($data["x"], $data["y"], $data["z"]);
|
||||
}
|
||||
|
||||
|
||||
public function getBlock($x, $y, $z){
|
||||
$b = $this->map->getBlock($x, $y, $z);
|
||||
$b[2] = array($x, $y, $z);
|
||||
return $b;
|
||||
}
|
||||
|
||||
|
||||
public function getFloor($x, $z){
|
||||
if(!isset($this->heightMap[$z][$x])){
|
||||
$this->heightMap[$z][$x] = $this->map->getFloor($x, $z);
|
||||
}
|
||||
return $this->heightMap[$z][$x];
|
||||
}
|
||||
|
||||
|
||||
public function setBlock($x, $y, $z, $block, $meta = 0, $update = true){
|
||||
if($x < 0 or $y < 0 or $z < 0){
|
||||
return false;
|
||||
}
|
||||
$this->map->setBlock($x, $y, $z, $block, $meta);
|
||||
$this->heightMap[$z][$x] = $this->map->getFloor($x, $z);
|
||||
if($this->server->api->dhandle("world.block.change", array(
|
||||
if($this->server->api->dhandle("block.change", array(
|
||||
"x" => $x,
|
||||
"y" => $y,
|
||||
"z" => $z,
|
||||
@ -100,8 +102,9 @@ class LevelAPI{
|
||||
$this->server->api->block->updateBlocksAround($x, $y, $z, BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function getOrderedChunk($X, $Z, $columnsPerPacket = 2){
|
||||
$columnsPerPacket = max(1, (int) $columnsPerPacket);
|
||||
$c = $this->getChunk($X, $Z);
|
||||
|
@ -30,28 +30,52 @@ class PlayerAPI{
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
|
||||
public function init(){
|
||||
$this->server->event("server.regeneration", array($this, "handle"));
|
||||
$this->server->addHandler("server.regeneration", array($this, "handle"));
|
||||
$this->server->addHandler("player.death", array($this, "handle"), 1);
|
||||
$this->server->api->console->register("list", "Shows connected player list", array($this, "commandHandler"));
|
||||
$this->server->api->console->register("kill", "Kills a player", array($this, "commandHandler"));
|
||||
$this->server->api->console->register("tppos", "Teleports a player to a position", array($this, "commandHandler"));
|
||||
$this->server->api->console->register("tp", "Teleports a player to another player", array($this, "commandHandler"));
|
||||
}
|
||||
|
||||
|
||||
public function handle($data, $event){
|
||||
switch($event){
|
||||
case "server.regeneration":
|
||||
$result = $this->server->query("SELECT ip,port FROM players WHERE EID = (SELECT EID FROM entities WHERE health < 20);", true);
|
||||
$result = $this->server->query("SELECT EID FROM players WHERE EID = (SELECT EID FROM entities WHERE health < 20);");
|
||||
if($result !== true and $result !== false){
|
||||
while(false !== ($player = $result->fetchArray())){
|
||||
$player->entity->setHealth(min(20, $player->entity->getHealth() + $data), "regeneration");
|
||||
if(($player = $this->server->api->player->getByEID($player["EID"])) !== false){
|
||||
$player->entity->setHealth(min(20, $player->entity->getHealth() + $data), "regeneration");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "player.death":
|
||||
$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){
|
||||
switch($cmd){
|
||||
case "tp":
|
||||
@ -98,7 +122,7 @@ class PlayerAPI{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function teleport($name, $target){
|
||||
$target = $this->get($target);
|
||||
if($target !== false){
|
||||
@ -106,7 +130,7 @@ class PlayerAPI{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function tppos($name, $x, $y, $z){
|
||||
$player = $this->get($name);
|
||||
if($player !== false){
|
||||
@ -122,7 +146,7 @@ class PlayerAPI{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function get($name){
|
||||
$CID = $this->server->query("SELECT ip,port FROM players WHERE name = '".str_replace("'", "", $name)."';", true);
|
||||
$CID = $this->server->clientID($CID["ip"], $CID["port"]);
|
||||
@ -131,11 +155,11 @@ class PlayerAPI{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function getAll(){
|
||||
return $this->server->clients;
|
||||
}
|
||||
|
||||
|
||||
public function getByEID($eid){
|
||||
$eid = (int) $eid;
|
||||
$CID = $this->server->query("SELECT ip,port FROM players WHERE EID = '".$eid."';", true);
|
||||
@ -145,7 +169,7 @@ class PlayerAPI{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function getByClientID($clientID){
|
||||
$clientID = (int) $clientID;
|
||||
$CID = $this->server->query("SELECT ip,port FROM players WHERE clientID = '".$clientID."';", true);
|
||||
@ -153,9 +177,9 @@ class PlayerAPI{
|
||||
if(isset($this->server->clients[$CID])){
|
||||
return $this->server->clients[$CID];
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function online(){
|
||||
$o = array();
|
||||
foreach($this->server->clients as $p){
|
||||
@ -165,29 +189,28 @@ class PlayerAPI{
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
public function add($CID){
|
||||
if(isset($this->server->clients[$CID])){
|
||||
$player = $this->server->clients[$CID];
|
||||
console("[INFO] Player \"".$player->username."\" connected from ".$player->ip.":".$player->port);
|
||||
console("[INFO] Player \"\x1b[33m".$player->username."\x1b[0m\" connected from \x1b[36m".$player->ip.":".$player->port."\x1b[0m");
|
||||
$player->data = $this->getOffline($player->username);
|
||||
$this->server->query("INSERT OR REPLACE INTO players (clientID, ip, port, name) VALUES (".$player->clientID.", '".$player->ip."', ".$player->port.", '".$player->username."');");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function remove($CID){
|
||||
if(isset($this->server->clients[$CID])){
|
||||
$player = $this->server->clients[$CID];
|
||||
if(is_object($player->entity)){
|
||||
$player->entity->close();
|
||||
}
|
||||
unset($this->server->clients[$CID]);
|
||||
$player->close();
|
||||
$this->saveOffline($player->username, $player->data);
|
||||
$this->server->query("DELETE FROM players WHERE name = '".$player->username."';");
|
||||
unset($this->server->entities[$player->eid]);
|
||||
unset($this->server->clients[$player->CID]);
|
||||
$this->server->api->entity->remove($player->eid);
|
||||
unset($player);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getOffline($name){
|
||||
if(!file_exists(FILE_PATH."players/".$name.".dat")){
|
||||
console("[NOTICE] Player data not found for \"".$name."\", creating new profile");
|
||||
@ -197,6 +220,7 @@ class PlayerAPI{
|
||||
"y" => $this->server->spawn["y"],
|
||||
"z" => $this->server->spawn["z"],
|
||||
),
|
||||
"inventory" => array_fill(0, 36, array(0, 0, 0)),
|
||||
"health" => 20,
|
||||
"lastIP" => "",
|
||||
"lastID" => 0,
|
||||
@ -208,9 +232,9 @@ class PlayerAPI{
|
||||
$this->server->handle("api.player.offline.get", $data);
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
public function saveOffline($name, $data){
|
||||
$this->server->handle("api.player.offline.save", $data);
|
||||
file_put_contents(FILE_PATH."players/".str_replace("/", "", $name).".dat", serialize($data));
|
||||
}
|
||||
}
|
||||
}
|
@ -26,13 +26,12 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
class PluginAPI extends stdClass{
|
||||
private $server, $plugins;
|
||||
private $server;
|
||||
private $plugins = array();
|
||||
public function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
$this->plugins = array();
|
||||
require_once("classes/Spyc.class.php"); //YAML parser
|
||||
}
|
||||
|
||||
|
||||
public function getList(){
|
||||
$list = array();
|
||||
foreach($this->plugins as $p){
|
||||
@ -40,7 +39,7 @@ class PluginAPI extends stdClass{
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
public function getInfo($className){
|
||||
if(!isset($this->plugins[$className])){
|
||||
return false;
|
||||
@ -48,7 +47,7 @@ class PluginAPI extends stdClass{
|
||||
$plugin = $this->plugins[$className];
|
||||
return array($plugin[1], get_class_methods($plugin[0]));
|
||||
}
|
||||
|
||||
|
||||
public function load($file){
|
||||
$content = file_get_contents($file);
|
||||
$info = strstr($content, "*/", true);
|
||||
@ -77,7 +76,7 @@ class PluginAPI extends stdClass{
|
||||
if(!isset($info["name"]) or !isset($info["version"]) or !isset($info["class"]) or !isset($info["author"])){
|
||||
console("[ERROR] [PluginAPI] Failed parsing of ".basename($file));
|
||||
}
|
||||
console("[INFO] [PluginAPI] Loading plugin \"".$info["name"]."\" ".$info["version"]." by ".$info["author"]);
|
||||
console("[INFO] [PluginAPI] Loading plugin \"\x1b[32m".$info["name"]."\x1b[0m\" \x1b[35m".$info["version"]."\x1b[0m by \x1b[36m".$info["author"]."\x1b[0m");
|
||||
if(class_exists($info["class"])){
|
||||
console("[ERROR] [PluginAPI] Failed loading plugin: class exists");
|
||||
}
|
||||
@ -86,21 +85,21 @@ class PluginAPI extends stdClass{
|
||||
}
|
||||
$className = trim($info["class"]);
|
||||
if(isset($info["api"]) and $info["api"] !== true){
|
||||
console("[NOTICE] [PluginAPI] Plugin \"".$info["name"]."\" got raw access to Server methods");
|
||||
console("[NOTICE] [PluginAPI] Plugin \"\x1b[36m".$info["name"]."\x1b[0m\" got raw access to Server methods");
|
||||
}
|
||||
$object = new $className($this->server->api, ((isset($info["api"]) and $info["api"] !== true) ? $this->server:false));
|
||||
if(!($object instanceof Plugin)){
|
||||
console("[ERROR] [PluginAPI] Plugin \"".$info["name"]."\" doesn't use the Plugin Interface");
|
||||
console("[ERROR] [PluginAPI] Plugin \"\x1b[36m".$info["name"]."\x1b[0m\" doesn't use the Plugin Interface");
|
||||
if(method_exists($object, "__destruct")){
|
||||
$object->__destruct();
|
||||
}
|
||||
$object = null;
|
||||
unset($object);
|
||||
unset($object);
|
||||
}else{
|
||||
$this->plugins[$className] = array($object, $info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function get(Plugin $plugin){
|
||||
foreach($this->plugins as &$p){
|
||||
if($p[0] === $plugin){
|
||||
@ -110,6 +109,16 @@ class PluginAPI extends stdClass{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function configPath(Plugin $plugin){
|
||||
$p = $this->get($plugin);
|
||||
if($p === false){
|
||||
return false;
|
||||
}
|
||||
$path = FILE_PATH."plugins/".$p[1]["name"]."/";
|
||||
$this->plugins[$p[1]["class"]][1]["path"] = $path;
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function createConfig(Plugin $plugin, $default = array()){
|
||||
$p = $this->get($plugin);
|
||||
if($p === false){
|
||||
@ -117,17 +126,11 @@ class PluginAPI extends stdClass{
|
||||
}
|
||||
$path = FILE_PATH."plugins/".$p[1]["name"]."/";
|
||||
$this->plugins[$p[1]["class"]][1]["path"] = $path;
|
||||
if(!file_exists($path."config.yml")){
|
||||
@mkdir($path, 0777);
|
||||
$this->writeYAML($path."config.yml", $default);
|
||||
}else{
|
||||
$data = $this->readYAML($path."config.yml");
|
||||
$this->fillDefaults($default, $data);
|
||||
$this->writeYAML($path."config.yml", $data);
|
||||
}
|
||||
$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)){
|
||||
@ -140,19 +143,20 @@ class PluginAPI extends stdClass{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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, "loadAll"));
|
||||
$this->server->event("server.start", array($this, "initAll"));
|
||||
$this->loadAll();
|
||||
}
|
||||
|
||||
|
||||
public function loadAll(){
|
||||
console("[INFO] Loading Plugins...");
|
||||
$dir = dir(FILE_PATH."plugins/");
|
||||
@ -163,10 +167,11 @@ class PluginAPI extends stdClass{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function initAll(){
|
||||
foreach($this->plugins as $p){
|
||||
if(method_exists($p[0], "init")){
|
||||
$p[0]->init();
|
||||
}
|
||||
$p[0]->init(); //ARGHHH!!! Plugin loading randomly fails!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,18 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
*/
|
||||
|
||||
class ServerAPI extends stdClass{ //Yay! I can add anything to this class in runtime!
|
||||
class ServerAPI{
|
||||
var $restart = false;
|
||||
private $server, $config, $apiList = array();
|
||||
function __construct(){
|
||||
private $server;
|
||||
private $config;
|
||||
private $apiList = array();
|
||||
|
||||
public function run(){
|
||||
$this->load();
|
||||
return $this->init();
|
||||
}
|
||||
|
||||
public function load(){
|
||||
@mkdir(FILE_PATH."logs/", 0777, true);
|
||||
@mkdir(FILE_PATH."players/", 0777);
|
||||
@mkdir(FILE_PATH."worlds/", 0777);
|
||||
@ -36,7 +44,7 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
console("[INFO] Starting ServerAPI server handler...");
|
||||
file_put_contents(FILE_PATH."logs/packets.log", "");
|
||||
if(!file_exists(FILE_PATH."logs/test.bin.log") or md5_file(FILE_PATH."logs/test.bin.log") !== TEST_MD5){
|
||||
console("[NOTICE] Executing integrity tests...");
|
||||
console("[NOTICE] Executing tests...");
|
||||
console("[INFO] OS: ".PHP_OS.", ".Utils::getOS());
|
||||
console("[INFO] uname -a: ".php_uname("a"));
|
||||
console("[INFO] PHP Version: ".phpversion());
|
||||
@ -59,46 +67,63 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
$test .= Utils::writeLong("-1152921504606846976");
|
||||
$test .= Utils::writeTriad(16777215);
|
||||
$test .= Utils::writeTriad(16777216);
|
||||
$str = new Java_String("THIS_IS_ a TEsT_SEED1_123456789^.,.,\xff\x00\x15");
|
||||
$str = new Java_String("TESTING\x00\n\r\t\xff");
|
||||
$test .= Utils::writeLong($str->hashCode());
|
||||
$test .= Utils::writeDataArray(array("a", "b", "c", "\xff\xff\xff\xff"));
|
||||
$test .= Utils::hexToStr("012334567890");
|
||||
file_put_contents(FILE_PATH."logs/test.bin.log", $test);
|
||||
if(md5($test) !== TEST_MD5){
|
||||
$md5 = md5($test);
|
||||
console("[INFO] MD5 of test: ".$md5);
|
||||
if($md5 !== TEST_MD5){
|
||||
console("[ERROR] Test error, please send your console.log + test.bin.log to the Github repo");
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
if(!file_exists(FILE_PATH."white-list.txt")){
|
||||
console("[NOTICE] No white-list.txt found, creating blank file");
|
||||
file_put_contents(FILE_PATH."white-list.txt", "");
|
||||
}
|
||||
|
||||
if(!file_exists(FILE_PATH."banned-ips.txt")){
|
||||
console("[NOTICE] No banned-ips.txt found, creating blank file");
|
||||
file_put_contents(FILE_PATH."banned-ips.txt", "");
|
||||
}
|
||||
|
||||
if(!file_exists(FILE_PATH."server.properties")){
|
||||
console("[NOTICE] No server.properties found, using default settings");
|
||||
copy(FILE_PATH."src/common/default.properties", FILE_PATH."server.properties");
|
||||
}
|
||||
|
||||
console("[DEBUG] Loading server.properties...", true, true, 2);
|
||||
$this->config = new Config(FILE_PATH . "server.properties", CONFIG_PROPERTIES, array(
|
||||
"server-name" => "Minecraft Server",
|
||||
"description" => "Server made using PocketMine-MP",
|
||||
"motd" => "Welcome @username to this server!",
|
||||
"invisible" => false,
|
||||
"port" => 19132,
|
||||
"memory-limit" => "256M",
|
||||
"last-update" => false,
|
||||
"update-channel" => "stable",
|
||||
"white-list" => false,
|
||||
"debug" => 2,
|
||||
"max-players" => 20,
|
||||
"server-type" => "normal",
|
||||
"time-per-second" => 20,
|
||||
"gamemode" => 1,
|
||||
"difficulty" => 1,
|
||||
"generator" => "",
|
||||
"generator-settings" => "",
|
||||
"level-name" => false,
|
||||
"server-id" => false,
|
||||
"upnp-forwarding" => false,
|
||||
));
|
||||
$this->parseProperties();
|
||||
define("DEBUG", $this->config["debug"]);
|
||||
define("DEBUG", $this->getProperty("debug"));
|
||||
$this->server = new PocketMinecraftServer($this->getProperty("server-name"), $this->getProperty("gamemode"), false, $this->getProperty("port"), $this->getProperty("server-id"));
|
||||
$this->setProperty("server-id", $this->server->serverID);
|
||||
$this->server->api = $this;
|
||||
if($this->getProperty("upnp-forwarding") === true){
|
||||
console("[INFO] [UPnP] Trying to port forward...");
|
||||
UPnP_PortForward($this->getProperty("port"));
|
||||
}
|
||||
if(($ip = Utils::getIP()) !== false){
|
||||
console("[INFO] External IP: ".$ip);
|
||||
}
|
||||
if($this->getProperty("last-update") === false or ($this->getProperty("last-update") + 3600) < time()){
|
||||
console("[INFO] Checking for new server version");
|
||||
console("[INFO] Last check: ".date("Y-m-d H:i:s", $this->getProperty("last-update")));
|
||||
console("[INFO] Last check: \x1b[36m".date("Y-m-d H:i:s", $this->getProperty("last-update"))."\x1b[0m");
|
||||
$channel = "stable";
|
||||
if($this->getProperty("update-channel") == "dev" or $this->getProperty("update-channel") == "development"){
|
||||
$channel = "dev";
|
||||
}
|
||||
$this->setProperty("update-channel", $channel);
|
||||
|
||||
|
||||
if($channel === "dev"){
|
||||
$info = json_decode(Utils::curl_get("https://api.github.com/repos/shoghicp/PocketMine-MP"), true);
|
||||
if($info === false or !isset($info["updated_at"])){
|
||||
@ -107,13 +132,13 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
$last = new DateTime($info["updated_at"]);
|
||||
$last = $last->getTimestamp();
|
||||
if($last >= $this->getProperty("last-update") and $this->getProperty("last-update") !== false){
|
||||
console("[NOTICE] A new DEVELOPMENT version of PocketMine-MP has been released");
|
||||
console("[NOTICE] If you want to update, get the latest version at https://github.com/shoghicp/PocketMine-MP/archive/master.zip");
|
||||
console("[NOTICE] \x1b[33mA new DEVELOPMENT version of PocketMine-MP has been released");
|
||||
console("[NOTICE] \x1b[36mIf you want to update, get the latest version at https://github.com/shoghicp/PocketMine-MP/archive/master.zip");
|
||||
console("[NOTICE] This message will dissapear when you issue the command \"/update-done\"");
|
||||
sleep(3);
|
||||
}else{
|
||||
$this->setProperty("last-update", time());
|
||||
console("[INFO] This is the latest DEVELOPMENT version");
|
||||
console("[INFO] \x1b[36mThis is the latest DEVELOPMENT version");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
@ -121,19 +146,30 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
if($info === false or !isset($info[0])){
|
||||
console("[ERROR] GitHub API Error");
|
||||
}else{
|
||||
$info = $info[0];
|
||||
if($info["name"] != MAJOR_VERSION){
|
||||
console("[NOTICE] A new STABLE version of PocketMine-MP has been released");
|
||||
console("[NOTICE] Version \"".$info["name"]."\" [".substr($info["commit"]["sha"], 0, 10)."]");
|
||||
console("[NOTICE] Download it at ".$info["zipball_url"]);
|
||||
|
||||
$newest = new VersionString(MAJOR_VERSION);
|
||||
$newest = array(-1, $newest->getNumber());
|
||||
foreach($info as $i => $tag){
|
||||
$update = new VersionString($tag["name"]);
|
||||
$update = $update->getNumber();
|
||||
if($update > $newest[1]){
|
||||
$newest = array($i, $update);
|
||||
}
|
||||
}
|
||||
|
||||
if($newest[0] !== -1){
|
||||
$target = $info[$newest[0]];
|
||||
console("[NOTICE] \x1b[33mA new STABLE version of PocketMine-MP has been released");
|
||||
console("[NOTICE] \x1b[36mVersion \"".(new VersionString($newest[1]))."\" #".$newest[1]." [".substr($target["commit"]["sha"], 0, 10)."]");
|
||||
console("[NOTICE] Download it at ".$target["zipball_url"]);
|
||||
console("[NOTICE] This message will dissapear as soon as you update");
|
||||
sleep(5);
|
||||
}else{
|
||||
$this->setProperty("last-update", time());
|
||||
console("[INFO] This is the latest STABLE version");
|
||||
console("[INFO] \x1b[36mThis is the latest STABLE version");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
if(file_exists(FILE_PATH."worlds/level.dat")){
|
||||
@ -163,14 +199,14 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
}
|
||||
$this->loadProperties();
|
||||
$this->server->loadMap();
|
||||
|
||||
|
||||
//Autoload all default APIs
|
||||
console("[INFO] Loading default APIs");
|
||||
$dir = dir(FILE_PATH."src/API/");
|
||||
while(false !== ($file = $dir->read())){
|
||||
if($file{0} !== "."){ //Hidden and upwards folders
|
||||
$API = basename($file, ".php");
|
||||
if(strtolower($API) !== "serverapi"){
|
||||
if(strtolower($API) !== "serverapi" and strtolower($API) !== "pluginapi"){
|
||||
$name = strtolower(substr($API, 0, -3));
|
||||
$this->loadAPI($name, $API);
|
||||
}
|
||||
@ -178,13 +214,16 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
}
|
||||
foreach($this->apiList as $ob){
|
||||
if(is_callable(array($ob, "init"))){
|
||||
$ob->init();
|
||||
$ob->init(); //Fails sometimes!!!
|
||||
}
|
||||
}
|
||||
$this->loadAPI("plugin", "PluginAPI"); //fix :(
|
||||
$this->plugin->init();
|
||||
|
||||
|
||||
$this->server->loadEntities();
|
||||
}
|
||||
|
||||
|
||||
public function __destruct(){
|
||||
foreach($this->apiList as $ob){
|
||||
if(is_callable($ob, "__destruct")){
|
||||
@ -193,68 +232,42 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private function loadProperties(){
|
||||
if(isset($this->config["memory-limit"])){
|
||||
@ini_set("memory_limit", $this->config["memory-limit"]);
|
||||
if(($memory = $this->getProperty("memory-limit")) !== false){
|
||||
$value = array("M" => 1, "G" => 1024);
|
||||
$real = ((int) substr($memory, 0, -1)) * $value[substr($memory, -1)];
|
||||
if($real < 128){
|
||||
console("[ERROR] PocketMine doesn't work right with less than 128MB of RAM", true, true, 0);
|
||||
}
|
||||
@ini_set("memory_limit", $memory);
|
||||
}else{
|
||||
$this->config["memory-limit"] = "256M";
|
||||
$this->setProperty("memory-limit", "256M");
|
||||
}
|
||||
if(!isset($this->config["invisible"])){
|
||||
$this->config["invisible"] = false;
|
||||
if(!$this->config->exists("invisible")){
|
||||
$this->config->set("invisible", false);
|
||||
}
|
||||
if(is_object($this->server)){
|
||||
$this->server->setType($this->config["server-type"]);
|
||||
$this->server->timePerSecond = $this->config["time-per-second"];
|
||||
$this->server->invisible = $this->config["invisible"];
|
||||
$this->server->maxClients = $this->config["max-players"];
|
||||
$this->server->description = $this->config["description"];
|
||||
$this->server->motd = $this->config["motd"];
|
||||
$this->server->gamemode = $this->config["gamemode"];
|
||||
$this->server->difficulty = $this->config["difficulty"];
|
||||
$this->server->whitelist = $this->config["white-list"];
|
||||
$this->server->setType($this->getProperty("server-type"));
|
||||
$this->server->timePerSecond = $this->getProperty("time-per-second");
|
||||
$this->server->invisible = $this->getProperty("invisible");
|
||||
$this->server->maxClients = $this->getProperty("max-players");
|
||||
$this->server->description = $this->getProperty("description");
|
||||
$this->server->motd = $this->getProperty("motd");
|
||||
$this->server->gamemode = $this->getProperty("gamemode");
|
||||
$this->server->difficulty = $this->getProperty("difficulty");
|
||||
$this->server->whitelist = $this->getProperty("white-list");
|
||||
$this->server->reloadConfig();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function writeProperties(){
|
||||
if(is_object($this->server)){
|
||||
$this->config["server-id"] = $this->server->serverID;
|
||||
}
|
||||
$config = $this->config;
|
||||
$config["white-list"] = $config["white-list"] === true ? "true":"false";
|
||||
$config["invisible"] = $config["invisible"] === true ? "true":"false";
|
||||
$prop = "#Pocket Minecraft PHP server properties\r\n#".date("D M j H:i:s T Y")."\r\n";
|
||||
foreach($config as $n => $v){
|
||||
$prop .= $n."=".$v."\r\n";
|
||||
}
|
||||
file_put_contents(FILE_PATH."server.properties", $prop);
|
||||
$this->config->save();
|
||||
}
|
||||
|
||||
|
||||
private function parseProperties(){
|
||||
$prop = file_get_contents(FILE_PATH."server.properties");
|
||||
$prop = explode("\n", str_replace("\r", "", $prop));
|
||||
$this->config = array();
|
||||
foreach($prop as $line){
|
||||
if(trim($line) == "" or $line{0} == "#"){
|
||||
continue;
|
||||
}
|
||||
$d = explode("=", $line);
|
||||
$n = strtolower(array_shift($d));
|
||||
$v = implode("=", $d);
|
||||
switch(strtolower(trim($v))){
|
||||
case "on":
|
||||
case "true":
|
||||
case "yes":
|
||||
$v = true;
|
||||
break;
|
||||
case "off":
|
||||
case "false":
|
||||
case "no":
|
||||
$v = false;
|
||||
break;
|
||||
}
|
||||
foreach($this->config->getAll() as $n => $v){
|
||||
switch($n){
|
||||
case "last-update":
|
||||
if($v === false){
|
||||
@ -277,18 +290,22 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
}
|
||||
break;
|
||||
}
|
||||
$this->config[$n] = $v;
|
||||
$this->config->set($n, $v);
|
||||
}
|
||||
}
|
||||
|
||||
public function start(){
|
||||
|
||||
public function init(){
|
||||
$this->server->init();
|
||||
unregister_tick_function(array($this->server, "tick"));
|
||||
$this->__destruct();
|
||||
unset($this->server);
|
||||
if($this->getProperty("upnp-forwarding") === true ){
|
||||
console("[INFO] [UPnP] Removing port forward...");
|
||||
UPnP_RemovePortForward($this->getProperty("port"));
|
||||
}
|
||||
return $this->restart;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
public function addHandler($e, $c, $p = 5){
|
||||
@ -298,31 +315,31 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
public function dhandle($e, $d){
|
||||
return $this->server->handle($e, $d);
|
||||
}
|
||||
|
||||
|
||||
public function handle($e, &$d){
|
||||
return $this->server->handle($e, $d);
|
||||
}
|
||||
|
||||
|
||||
public function action($t, $c, $r = true){
|
||||
return $this->server->action($t, $c, $r);
|
||||
}
|
||||
|
||||
|
||||
public function schedule($t, $c, $d, $r = false, $e = "server.schedule"){
|
||||
return $this->server->schedule($t, $c, $d, $r, $e);
|
||||
}
|
||||
|
||||
|
||||
public function event($e, $d){
|
||||
return $this->server->event($e, $d);
|
||||
}
|
||||
|
||||
|
||||
public function trigger($e, $d){
|
||||
return $this->server->trigger($e, $d);
|
||||
}
|
||||
|
||||
|
||||
public function deleteEvent($id){
|
||||
return $this->server->deleteEvent($id);
|
||||
}
|
||||
|
||||
|
||||
public function importMap($dir, $remove = false){
|
||||
if(file_exists($dir."level.dat")){
|
||||
$nbt = new NBT();
|
||||
@ -330,7 +347,7 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
console("[DEBUG] Importing map \"".$level["LevelName"]."\" gamemode ".$level["GameType"]." with seed ".$level["RandomSeed"], true, true, 2);
|
||||
unset($level["Player"]);
|
||||
$lvName = $level["LevelName"]."/";
|
||||
@mkdir(FILE_PATH."worlds/".$lvName, 0777);
|
||||
@mkdir(FILE_PATH."worlds/".$lvName, 0777);
|
||||
file_put_contents(FILE_PATH."worlds/".$lvName."level.dat", serialize($level));
|
||||
$entities = parseNBTData($nbt->loadFile($dir."entities.dat"));
|
||||
file_put_contents(FILE_PATH."worlds/".$lvName."entities.dat", serialize($entities["Entities"]));
|
||||
@ -339,7 +356,7 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
}
|
||||
file_put_contents(FILE_PATH."worlds/".$lvName."tileEntities.dat", serialize($entities["TileEntities"]));
|
||||
console("[DEBUG] Imported ".count($entities["Entities"])." Entities and ".count($entities["TileEntities"])." TileEntities", true, true, 2);
|
||||
|
||||
|
||||
if($remove === true){
|
||||
rename($dir."chunks.dat", FILE_PATH."worlds/".$lvName."chunks.dat");
|
||||
unlink($dir."level.dat");
|
||||
@ -358,29 +375,67 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
$this->writeProperties();
|
||||
}
|
||||
console("[INFO] Map \"".$level["LevelName"]."\" importing done!");
|
||||
unset($level, $entities, $nbt);
|
||||
unset($level, $entities, $nbt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getProperty($name){
|
||||
if(isset($this->config[$name])){
|
||||
return $this->config[$name];
|
||||
}
|
||||
return false;
|
||||
public function getProperties(){
|
||||
return $this->config->getAll();
|
||||
}
|
||||
|
||||
|
||||
public function getProperty($name){
|
||||
if(($v = arg($name)) !== false){ //Allow for command-line arguments
|
||||
switch(strtolower(trim($v))){
|
||||
case "on":
|
||||
case "true":
|
||||
case "yes":
|
||||
$v = true;
|
||||
break;
|
||||
case "off":
|
||||
case "false":
|
||||
case "no":
|
||||
$v = false;
|
||||
break;
|
||||
}
|
||||
switch($name){
|
||||
case "last-update":
|
||||
if($v === false){
|
||||
$v = time();
|
||||
}else{
|
||||
$v = (int) $v;
|
||||
}
|
||||
break;
|
||||
case "gamemode":
|
||||
case "max-players":
|
||||
case "port":
|
||||
case "debug":
|
||||
case "difficulty":
|
||||
case "time-per-second":
|
||||
$v = (int) $v;
|
||||
break;
|
||||
case "server-id":
|
||||
if($v !== false){
|
||||
$v = preg_match("/[^0-9\-]/", $v) > 0 ? Utils::readInt(substr(md5($v, true), 0, 4)):$v;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return $v;
|
||||
}
|
||||
return $this->config->get($name);
|
||||
}
|
||||
|
||||
public function setProperty($name, $value){
|
||||
$this->config[$name] = $value;
|
||||
$this->config->set($name, $value);
|
||||
$this->writeProperties();
|
||||
$this->loadProperties();
|
||||
}
|
||||
|
||||
|
||||
public function getList(){
|
||||
return $this->apiList;
|
||||
}
|
||||
|
||||
|
||||
public function loadAPI($name, $class, $dir = false){
|
||||
if($dir === false){
|
||||
$dir = FILE_PATH."src/API/";
|
||||
@ -393,7 +448,7 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
require_once($file);
|
||||
$this->$name = new $class($this->server);
|
||||
$this->apiList[] = $this->$name;
|
||||
console("[INFO] API ".$name." [".$class."] loaded");
|
||||
console("[INFO] API \x1b[36m".$name."\x1b[0m [\x1b[30;1m".$class."\x1b[0m] loaded");
|
||||
}
|
||||
|
||||
}
|
@ -36,11 +36,11 @@ class TimeAPI{
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
|
||||
public function init(){
|
||||
$this->server->api->console->register("time", "Manages server time", array($this, "commandHandler"));
|
||||
}
|
||||
|
||||
|
||||
public function commandHandler($cmd, $params){
|
||||
switch($cmd){
|
||||
case "time":
|
||||
@ -74,7 +74,7 @@ class TimeAPI{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function night(){
|
||||
$this->set("night");
|
||||
}
|
||||
@ -87,20 +87,20 @@ class TimeAPI{
|
||||
public function sunset(){
|
||||
$this->set("sunset");
|
||||
}
|
||||
|
||||
|
||||
public function get($raw = false){
|
||||
return $raw === true ? $this->server->time:abs($this->server->time) % 19200;
|
||||
}
|
||||
|
||||
|
||||
public function add($time){
|
||||
$this->server->time += (int) $time;
|
||||
}
|
||||
|
||||
|
||||
public function getDate($time = false){
|
||||
$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);
|
||||
}
|
||||
|
||||
|
||||
public function getPhase($time = false){
|
||||
$time = $time === false ? $this->get():$time;
|
||||
if($time < $this->phase["sunset"]){
|
||||
@ -114,7 +114,7 @@ class TimeAPI{
|
||||
}
|
||||
return $time;
|
||||
}
|
||||
|
||||
|
||||
public function set($time){
|
||||
if(is_string($time) and isset($this->phases[$time])){
|
||||
$this->server->time = $this->phases[$time];
|
||||
@ -122,6 +122,6 @@ class TimeAPI{
|
||||
$this->server->time = (int) $time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -60,7 +60,7 @@ class Async extends Thread {
|
||||
/**
|
||||
* Do whatever, result stored in $this->result, don't try to join twice
|
||||
**/
|
||||
public function __toString(){
|
||||
public function __toString(){
|
||||
if(!$this->joined) {
|
||||
$this->joined = true;
|
||||
$this->join();
|
@ -104,6 +104,7 @@ class Material{
|
||||
38 => true,
|
||||
39 => true,
|
||||
40 => true,
|
||||
44 => true,
|
||||
46 => true,
|
||||
50 => true,
|
||||
51 => true,
|
||||
@ -113,14 +114,13 @@ class Material{
|
||||
67 => true,
|
||||
78 => true,
|
||||
79 => true,
|
||||
81 => true,
|
||||
83 => true,
|
||||
89 => true,
|
||||
96 => true,
|
||||
102 => true,
|
||||
105 => true,
|
||||
107 => true,
|
||||
108 => true,
|
||||
108 => true,
|
||||
);
|
||||
static $replaceable = array(
|
||||
0 => true,
|
||||
@ -130,7 +130,7 @@ class Material{
|
||||
11 => true,
|
||||
31 => true,
|
||||
51 => true,
|
||||
78 => true,
|
||||
78 => true,
|
||||
);
|
||||
static $activable = array(
|
||||
2 => true,
|
||||
@ -138,7 +138,7 @@ class Material{
|
||||
6 => true,
|
||||
26 => true,
|
||||
31 => true,
|
||||
46 => true,
|
||||
//46 => true,
|
||||
51 => true,
|
||||
54 => true,
|
||||
58 => true,
|
||||
@ -146,6 +146,7 @@ class Material{
|
||||
61 => true,
|
||||
62 => true,
|
||||
64 => true,
|
||||
71 => true,
|
||||
78 => true,
|
||||
96 => true,
|
||||
105 => true,
|
||||
@ -204,6 +205,7 @@ class Material{
|
||||
324 => 64,
|
||||
65 => true,
|
||||
67 => true,
|
||||
330 => 71,
|
||||
73 => true,
|
||||
79 => true,
|
||||
80 => true,
|
||||
@ -234,7 +236,7 @@ class Material{
|
||||
4 => "Cobblestone",
|
||||
5 => "Wooden Planks",
|
||||
6 => "Sapling",
|
||||
7 => "Bedrock",
|
||||
7 => "Bedrock",
|
||||
);
|
||||
|
||||
|
35
src/classes/Deprecation.php
Normal file
35
src/classes/Deprecation.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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 Deprecation{
|
||||
public static $events = array(
|
||||
"world.block.change" => "block.change",
|
||||
);
|
||||
|
||||
|
||||
}
|
@ -1,405 +0,0 @@
|
||||
<?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 Player{
|
||||
private $server, $timeout, $connected, $evid, $queue, $buffer;
|
||||
var $clientID, $ip, $port, $counter, $username, $eid, $data, $entity, $auth, $CID, $MTU, $spawned, $equipment;
|
||||
function __construct($server, $clientID, $ip, $port, $MTU){
|
||||
$this->queue = array();
|
||||
$this->buffer = array();
|
||||
$this->MTU = $MTU;
|
||||
$this->server = $server;
|
||||
$this->clientID = $clientID;
|
||||
$this->CID = $this->server->clientID($ip, $port);
|
||||
$this->eid = false;
|
||||
$this->data = array();
|
||||
$this->ip = $ip;
|
||||
$this->entity = false;
|
||||
$this->port = $port;
|
||||
$this->timeout = microtime(true) + 25;
|
||||
$this->evid = array();
|
||||
$this->equipment = array(1, 0);
|
||||
$this->spawned = false;
|
||||
$this->evid[] = $this->server->event("server.tick", array($this, "onTick"));
|
||||
$this->evid[] = $this->server->event("server.close", array($this, "close"));
|
||||
console("[DEBUG] New Session started with ".$ip.":".$port.". MTU ".$this->MTU.", Client ID ".$this->clientID, true, true, 2);
|
||||
$this->connected = true;
|
||||
$this->auth = false;
|
||||
$this->counter = array(0, 0, 0);
|
||||
}
|
||||
|
||||
public function onTick($time, $event){
|
||||
if($event !== "server.tick"){
|
||||
return;
|
||||
}
|
||||
if($time > $this->timeout){
|
||||
$this->close("timeout");
|
||||
}else{
|
||||
if(!empty($this->queue)){
|
||||
$cnt = 0;
|
||||
while($cnt < 4){
|
||||
$p = array_shift($this->queue);
|
||||
if($p === null){
|
||||
break;
|
||||
}
|
||||
switch($p[0]){
|
||||
case 0:
|
||||
$this->dataPacket($p[1], $p[2], false, $p[3]);
|
||||
break;
|
||||
case 1:
|
||||
eval($p[1]);
|
||||
break;
|
||||
}
|
||||
++$cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function save(){
|
||||
if(is_object($this->entity)){
|
||||
$this->data["spawn"] = array(
|
||||
"x" => $this->entity->x,
|
||||
"y" => $this->entity->y,
|
||||
"z" => $this->entity->z,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function close($reason = "", $msg = true){
|
||||
$reason = $reason == "" ? "server stop":$reason;
|
||||
$this->save();
|
||||
foreach($this->evid as $ev){
|
||||
$this->server->deleteEvent($ev);
|
||||
}
|
||||
$this->eventHandler("You have been kicked. Reason: ".$reason, "server.chat");
|
||||
$this->dataPacket(MC_LOGIN_STATUS, array(
|
||||
"status" => 1,
|
||||
));
|
||||
$this->dataPacket(MC_DISCONNECT);
|
||||
|
||||
$this->connected = false;
|
||||
if($msg === true){
|
||||
$this->server->api->dhandle("server.chat", $this->username." left the game");
|
||||
}
|
||||
console("[INFO] Session with ".$this->ip.":".$this->port." Client ID ".$this->clientID." closed due to ".$reason);
|
||||
$this->server->api->player->remove($this->CID);
|
||||
}
|
||||
|
||||
public function eventHandler($data, $event){
|
||||
switch($event){
|
||||
case "player.item.pick":
|
||||
$this->dataPacket(MC_TAKE_ITEM_ENTITY, $data);
|
||||
break;
|
||||
case "player.equipment.change":
|
||||
if($data["eid"] === $this->eid){
|
||||
break;
|
||||
}
|
||||
$this->dataPacket(MC_PLAYER_EQUIPMENT, $data);
|
||||
break;
|
||||
case "world.block.change":
|
||||
$this->dataPacket(MC_UPDATE_BLOCK, $data);
|
||||
break;
|
||||
case "entity.move":
|
||||
if($data === $this->eid){
|
||||
break;
|
||||
}
|
||||
$entity = $this->server->entities[$data];
|
||||
$this->dataPacket(MC_MOVE_ENTITY_POSROT, array(
|
||||
"eid" => $data,
|
||||
"x" => $entity->x,
|
||||
"y" => $entity->y,
|
||||
"z" => $entity->z,
|
||||
"yaw" => $entity->yaw,
|
||||
"pitch" => $entity->pitch,
|
||||
));
|
||||
break;
|
||||
case "entity.remove":
|
||||
if($data === $this->eid){
|
||||
break;
|
||||
}
|
||||
$this->dataPacket(MC_REMOVE_ENTITY, array(
|
||||
"eid" => $data,
|
||||
));
|
||||
break;
|
||||
case "server.time.change":
|
||||
$this->dataPacket(MC_SET_TIME, array(
|
||||
"time" => $data,
|
||||
));
|
||||
break;
|
||||
case "entity.animate":
|
||||
if($data["eid"] === $this->eid){
|
||||
break;
|
||||
}
|
||||
$this->dataPacket(MC_ANIMATE, array(
|
||||
"eid" => $data["eid"],
|
||||
"action" => $data["action"],
|
||||
));
|
||||
break;
|
||||
case "server.chat":
|
||||
$this->dataPacket(MC_CHAT, array(
|
||||
"message" => str_replace("@username", $this->username, $data),
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function handle($pid, $data){
|
||||
if($this->connected === true){
|
||||
$this->timeout = microtime(true) + 25;
|
||||
switch($pid){
|
||||
case 0xa0: //NACK
|
||||
if(isset($this->buffer[$data[2]])){
|
||||
array_unshift($this->queue, array(0, $this->buffer[$data[2]][0], $this->buffer[$data[2]][1], $data[2]));
|
||||
}
|
||||
if(isset($data[3])){
|
||||
if(isset($this->buffer[$data[3]])){
|
||||
array_unshift($this->queue, array(0, $this->buffer[$data[3]][0], $this->buffer[$data[3]][1], $data[3]));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xc0: //ACK
|
||||
$diff = $data[2] - $this->counter[2];
|
||||
if($diff > 8){ //Packet recovery
|
||||
array_unshift($this->queue, array(0, $this->buffer[$data[2]][0], $this->buffer[$data[2]][1], $data[2]));
|
||||
}
|
||||
$this->counter[2] = $data[2];
|
||||
unset($this->buffer[$data[2]]);
|
||||
|
||||
if(isset($data[3])){
|
||||
$diff = $data[3] - $this->counter[2];
|
||||
if($diff > 8){ //Packet recovery
|
||||
array_unshift($this->queue, array(0, $this->buffer[$data[3]][0], $this->buffer[$data[3]][1], $data[3]));
|
||||
}
|
||||
$this->counter[2] = $data[3];
|
||||
unset($this->buffer[$data[3]]);
|
||||
}
|
||||
break;
|
||||
case 0x07:
|
||||
$this->send(0x08, array(
|
||||
MAGIC,
|
||||
$this->server->serverID,
|
||||
$this->port,
|
||||
$data[3],
|
||||
0,
|
||||
));
|
||||
break;
|
||||
case 0x80:
|
||||
case 0x84:
|
||||
case 0x88:
|
||||
case 0x8c:
|
||||
if(isset($data[0])){
|
||||
$diff = $data[0] - $this->counter[1];
|
||||
if($diff > 1){ //Packet recovery
|
||||
for($i = $this->counter[1]; $i < $data[0]; ++$i){
|
||||
$this->send(0xa0, array(1, true, $i));
|
||||
}
|
||||
$this->counter[1] = $data[0];
|
||||
}elseif($diff === 1){
|
||||
$this->counter[1] = $data[0];
|
||||
}
|
||||
$this->send(0xc0, array(1, true, $data[0]));
|
||||
}
|
||||
switch($data["id"]){
|
||||
case MC_DISCONNECT:
|
||||
$this->connected = false;
|
||||
$this->close("client disconnect");
|
||||
break;
|
||||
case MC_CLIENT_CONNECT:
|
||||
$this->dataPacket(MC_SERVER_HANDSHAKE, array(
|
||||
"port" => $this->port,
|
||||
"session" => $data["session"],
|
||||
"session2" => Utils::readLong("\x00\x00\x00\x00\x04\x44\x0b\xa9"),
|
||||
));
|
||||
break;
|
||||
case MC_CLIENT_HANDSHAKE:
|
||||
|
||||
break;
|
||||
case MC_LOGIN:
|
||||
$this->username = str_replace("/", "", $data["username"]);
|
||||
if($this->username == ""){
|
||||
$this->close("bad username", false);
|
||||
break;
|
||||
}
|
||||
$o = $this->server->api->player->getOffline($this->username);
|
||||
if($this->server->whitelist !== false and (!in_array($this->username, $this->server->whitelist)/* or ($o["lastID"] != 0 and $o["lastID"] != $this->clientID)*/)){
|
||||
$this->close("\"".$this->username."\" not being on white-list", false);
|
||||
break;
|
||||
}
|
||||
$u = $this->server->api->player->get($this->username);
|
||||
$c = $this->server->api->player->getByClientID($this->clientID);
|
||||
if($u !== false){
|
||||
$u->close("logged in from another location");
|
||||
}
|
||||
if($c !== false){
|
||||
$c->close("logged in from another location");
|
||||
}
|
||||
$this->server->api->player->add($this->CID);
|
||||
$this->auth = true;
|
||||
$this->data["lastIP"] = $this->ip;
|
||||
$this->data["lastID"] = $this->clientID;
|
||||
$this->server->api->player->saveOffline($this->username, $this->data);
|
||||
$this->dataPacket(MC_LOGIN_STATUS, array(
|
||||
"status" => 0,
|
||||
));
|
||||
$this->dataPacket(MC_START_GAME, array(
|
||||
"seed" => $this->server->seed,
|
||||
"x" => $this->data["spawn"]["x"],
|
||||
"y" => $this->data["spawn"]["y"],
|
||||
"z" => $this->data["spawn"]["z"],
|
||||
"unknown1" => 0,
|
||||
"gamemode" => $this->server->gamemode,
|
||||
"eid" => 0,
|
||||
));
|
||||
break;
|
||||
case MC_READY:
|
||||
if($this->spawned !== false){
|
||||
break;
|
||||
}
|
||||
$this->spawned = true;
|
||||
$this->entity = $this->server->api->entity->add(ENTITY_PLAYER, 0, array("player" => $this));
|
||||
$this->eid = $this->entity->eid;
|
||||
$this->server->query("UPDATE players SET EID = ".$this->eid." WHERE clientID = ".$this->clientID.";");
|
||||
$this->entity->setName($this->username);
|
||||
$this->entity->data["clientID"] = $this->clientID;
|
||||
$this->server->api->entity->spawnAll($this);
|
||||
$this->server->api->entity->spawnToAll($this->eid);
|
||||
$this->evid[] = $this->server->event("server.time.change", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("server.chat", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("entity.remove", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("entity.move", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("entity.animate", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("player.equipment.change", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("player.item.pick", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("world.block.change", array($this, "eventHandler"));
|
||||
console("[DEBUG] Player with EID ".$this->eid." \"".$this->username."\" spawned!", true, true, 2);
|
||||
|
||||
$this->eventHandler($this->server->motd, "server.chat");
|
||||
if($this->MTU <= 548){
|
||||
$this->eventHandler("Your connection is bad, you may experience lag and slow map loading.", "server.chat");
|
||||
}
|
||||
break;
|
||||
case MC_MOVE_PLAYER:
|
||||
if(is_object($this->entity)){
|
||||
$this->entity->setPosition($data["x"], $data["y"], $data["z"], $data["yaw"], $data["pitch"]);
|
||||
$this->server->api->dhandle("entity.move", $this->eid);
|
||||
}
|
||||
break;
|
||||
case MC_PLAYER_EQUIPMENT:
|
||||
$data["eid"] = $this->eid;
|
||||
if($this->server->handle("player.equipment.change", $data) !== false){
|
||||
$this->equipment[0] = $data["block"];
|
||||
$this->equipment[1] = $data["meta"];
|
||||
console("[DEBUG] EID ".$this->eid." has now ".$data["block"].":".$data["meta"]." in their hands!", true, true, 2);
|
||||
}
|
||||
break;
|
||||
case MC_REQUEST_CHUNK:
|
||||
$this->actionQueue('
|
||||
$max = max(1, floor(($this->MTU - 16 - 255) / 192));
|
||||
$chunk = $this->server->api->level->getOrderedChunk('.$data["x"].', '.$data["z"].', $max);
|
||||
foreach($chunk as $d){
|
||||
$this->dataPacket(MC_CHUNK_DATA, array(
|
||||
"x" => '.$data["x"].',
|
||||
"z" => '.$data["z"].',
|
||||
"data" => $d,
|
||||
), true);
|
||||
}
|
||||
');
|
||||
console("[INTERNAL] Chunk X ".$data["x"]." Z ".$data["z"]." requested", true, true, 3);
|
||||
break;
|
||||
case MC_USE_ITEM:
|
||||
$data["eid"] = $this->eid;
|
||||
if(Utils::distance($this->entity->position, $data) > 8){
|
||||
break;
|
||||
}
|
||||
$this->server->handle("player.block.action", $data);
|
||||
break;
|
||||
case MC_PLACE_BLOCK:
|
||||
|
||||
break;
|
||||
case MC_REMOVE_BLOCK:
|
||||
$data["eid"] = $this->eid;
|
||||
if(Utils::distance($this->entity->position, $data) > 8){
|
||||
break;
|
||||
}
|
||||
$this->server->handle("player.block.break", $data);
|
||||
break;
|
||||
case MC_INTERACT:
|
||||
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);
|
||||
if($this->server->gamemode !== 1 and $this->server->difficulty > 0){
|
||||
$this->server->api->entity->harm($data["target"], $this->server->difficulty, $this->eid);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_ANIMATE:
|
||||
$this->server->api->dhandle("entity.animate", array("eid" => $this->eid, "action" => $data["action"]));
|
||||
break;
|
||||
case MC_RESPAWN:
|
||||
$this->entity->setHealth(20, "respawn");
|
||||
$this->entity->setPosition($data["x"], $data["y"], $data["z"], 0, 0);
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function send($pid, $data = array(), $raw = false){
|
||||
if($this->connected === true){
|
||||
$this->server->send($pid, $data, $raw, $this->ip, $this->port);
|
||||
}
|
||||
}
|
||||
|
||||
public function actionQueue($code){
|
||||
$this->queue[] = array(1, $code);
|
||||
}
|
||||
|
||||
public function dataPacket($id, $data = array(), $queue = false, $count = false){
|
||||
if($queue === true){
|
||||
$this->queue[] = array(0, $id, $data, $count);
|
||||
}else{
|
||||
if($count === false){
|
||||
$count = $this->counter[0];
|
||||
++$this->counter[0];
|
||||
if(count($this->buffer) >= 512){
|
||||
array_shift($this->buffer);
|
||||
}
|
||||
$this->buffer[$count] = array($id, $data);
|
||||
}
|
||||
$data["id"] = $id;
|
||||
$this->send(0x80, array(
|
||||
$count,
|
||||
0x00,
|
||||
$data,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
565
src/classes/Player.php
Normal file
565
src/classes/Player.php
Normal file
@ -0,0 +1,565 @@
|
||||
<?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 Player{
|
||||
private $server;
|
||||
private $queue = array();
|
||||
private $buffer = array();
|
||||
private $evid = array();
|
||||
var $timeout;
|
||||
var $connected = true;
|
||||
var $clientID;
|
||||
var $ip;
|
||||
var $port;
|
||||
var $counter = array(0, 0, 0);
|
||||
var $username;
|
||||
var $eid = false;
|
||||
var $data = array();
|
||||
var $entity = false;
|
||||
var $auth = false;
|
||||
var $CID;
|
||||
var $MTU;
|
||||
var $spawned = false;
|
||||
var $inventory;
|
||||
var $equipment = array(1, 0);
|
||||
var $loggedIn = false;
|
||||
function __construct(PocketMinecraftServer $server, $clientID, $ip, $port, $MTU){
|
||||
$this->MTU = $MTU;
|
||||
$this->server = $server;
|
||||
$this->clientID = $clientID;
|
||||
$this->CID = $this->server->clientID($ip, $port);
|
||||
$this->ip = $ip;
|
||||
$this->port = $port;
|
||||
$this->timeout = microtime(true) + 25;
|
||||
$this->inventory = array_fill(0, 36, array(0, 0, 0));
|
||||
$this->evid[] = $this->server->event("server.tick", array($this, "onTick"));
|
||||
$this->evid[] = $this->server->event("server.close", array($this, "close"));
|
||||
console("[DEBUG] New Session started with ".$ip.":".$port.". MTU ".$this->MTU.", Client ID ".$this->clientID, true, true, 2);
|
||||
}
|
||||
|
||||
public function onTick($time, $event){
|
||||
if($event !== "server.tick"){ //WTF??
|
||||
return;
|
||||
}
|
||||
if($time > $this->timeout){
|
||||
$this->close("timeout");
|
||||
}else{
|
||||
if(!empty($this->queue)){
|
||||
$cnt = 0;
|
||||
while($cnt < 4){
|
||||
$p = array_shift($this->queue);
|
||||
if($p === null){
|
||||
break;
|
||||
}
|
||||
switch($p[0]){
|
||||
case 0:
|
||||
$this->dataPacket($p[1], $p[2], false, $p[3]);
|
||||
break;
|
||||
case 1:
|
||||
eval($p[1]);
|
||||
break;
|
||||
}
|
||||
++$cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function save(){
|
||||
if(is_object($this->entity)){
|
||||
$this->data["spawn"] = array(
|
||||
"x" => $this->entity->x,
|
||||
"y" => $this->entity->y,
|
||||
"z" => $this->entity->z,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function close($reason = "", $msg = true){
|
||||
if($this->connected === true){
|
||||
foreach($this->evid as $ev){
|
||||
$this->server->deleteEvent($ev);
|
||||
}
|
||||
$this->server->api->dhandle("player.quit", $this);
|
||||
$reason = $reason == "" ? "server stop":$reason;
|
||||
$this->save();
|
||||
$this->eventHandler(new Container("You have been kicked. Reason: ".$reason), "server.chat");
|
||||
$this->dataPacket(MC_LOGIN_STATUS, array(
|
||||
"status" => 1,
|
||||
));
|
||||
$this->dataPacket(MC_DISCONNECT);
|
||||
|
||||
$this->connected = false;
|
||||
if($msg === true){
|
||||
$this->server->api->chat->broadcast($this->username." left the game");
|
||||
}
|
||||
console("[INFO] Session with \x1b[36m".$this->ip.":".$this->port."\x1b[0m Client ID ".$this->clientID." closed due to ".$reason);
|
||||
$this->server->api->player->remove($this->CID);
|
||||
}
|
||||
}
|
||||
|
||||
public function addItem($type, $damage, $count){
|
||||
while($count > 0){
|
||||
$add = 0;
|
||||
foreach($this->inventory as $s => $data){
|
||||
if($data[0] === 0){
|
||||
$add = min(64, $count);
|
||||
$this->inventory[$s] = array($type, $damage, $add);
|
||||
break;
|
||||
}elseif($data[0] === $type and $data[1] === $damage){
|
||||
$add = min(64 - $data[2], $count);
|
||||
if($add <= 0){
|
||||
continue;
|
||||
}
|
||||
$this->inventory[$s] = array($type, $damage, $data[2] + $add);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($add === 0){
|
||||
return false;
|
||||
}
|
||||
$count -= $add;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function removeItem($type, $damage, $count){
|
||||
while($count > 0){
|
||||
$remove = 0;
|
||||
foreach($this->inventory as $s => $data){
|
||||
if($data[0] === $type and $data[1] === $damage){
|
||||
$remove = min($count, $data[2]);
|
||||
if($remove < $data[2]){
|
||||
$this->inventory[$s][2] -= $remove;
|
||||
}else{
|
||||
$this->inventory[$s] = array(0, 0, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($remove === 0){
|
||||
return false;
|
||||
}
|
||||
$count -= $remove;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function hasItem($type, $damage = false){
|
||||
foreach($this->inventory as $s => $data){
|
||||
if($data[0] === $type and ($data[1] === $damage or $damage === false) and $data[2] > 0){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function eventHandler($data, $event){
|
||||
switch($event){
|
||||
case "player.block.place":
|
||||
if($data["eid"] === $this->eid and $this->server->gamemode === 0){
|
||||
$this->removeItem($data["original"][0], $data["original"][1], 1);
|
||||
}
|
||||
break;
|
||||
case "player.pickup":
|
||||
if($data["eid"] === $this->eid){
|
||||
$data["eid"] = 0;
|
||||
if($this->server->gamemode === 0){
|
||||
$this->addItem($data["entity"]->type, $data["entity"]->meta, $data["entity"]->stack);
|
||||
}
|
||||
}
|
||||
$this->dataPacket(MC_TAKE_ITEM_ENTITY, $data);
|
||||
break;
|
||||
case "player.equipment.change":
|
||||
if($data["eid"] === $this->eid){
|
||||
break;
|
||||
}
|
||||
$this->dataPacket(MC_PLAYER_EQUIPMENT, $data);
|
||||
break;
|
||||
case "block.change":
|
||||
$this->dataPacket(MC_UPDATE_BLOCK, $data);
|
||||
break;
|
||||
case "entity.move":
|
||||
if($data->eid === $this->eid){
|
||||
break;
|
||||
}
|
||||
$this->dataPacket(MC_MOVE_ENTITY_POSROT, array(
|
||||
"eid" => $data->eid,
|
||||
"x" => $data->x,
|
||||
"y" => $data->y,
|
||||
"z" => $data->z,
|
||||
"yaw" => $data->yaw,
|
||||
"pitch" => $data->pitch,
|
||||
));
|
||||
break;
|
||||
case "entity.remove":
|
||||
if($data->eid === $this->eid){
|
||||
break;
|
||||
}
|
||||
$this->dataPacket(MC_REMOVE_ENTITY, array(
|
||||
"eid" => $data->eid,
|
||||
));
|
||||
break;
|
||||
case "server.time":
|
||||
$this->dataPacket(MC_SET_TIME, array(
|
||||
"time" => $data,
|
||||
));
|
||||
break;
|
||||
case "entity.animate":
|
||||
if($data["eid"] === $this->eid){
|
||||
break;
|
||||
}
|
||||
$this->dataPacket(MC_ANIMATE, array(
|
||||
"eid" => $data["eid"],
|
||||
"action" => $data["action"],
|
||||
));
|
||||
break;
|
||||
case "server.chat":
|
||||
if(($data instanceof Container) === true){
|
||||
if(!$data->check($this->username)){
|
||||
return;
|
||||
}else{
|
||||
$message = $data->get();
|
||||
}
|
||||
}else{
|
||||
$message = (string) $data;
|
||||
}
|
||||
$this->dataPacket(MC_CHAT, array(
|
||||
"message" => str_replace("@username", $this->username, $message),
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function handle($pid, $data){
|
||||
if($this->connected === true){
|
||||
$this->timeout = microtime(true) + 25;
|
||||
switch($pid){
|
||||
case 0xa0: //NACK
|
||||
if(isset($this->buffer[$data[2]])){
|
||||
array_unshift($this->queue, array(0, $this->buffer[$data[2]][0], $this->buffer[$data[2]][1], $data[2]));
|
||||
}
|
||||
if(isset($data[3])){
|
||||
if(isset($this->buffer[$data[3]])){
|
||||
array_unshift($this->queue, array(0, $this->buffer[$data[3]][0], $this->buffer[$data[3]][1], $data[3]));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xc0: //ACK
|
||||
$diff = $data[2] - $this->counter[2];
|
||||
if($diff > 8){ //Packet recovery
|
||||
array_unshift($this->queue, array(0, $this->buffer[$data[2]][0], $this->buffer[$data[2]][1], $data[2]));
|
||||
}
|
||||
$this->counter[2] = $data[2];
|
||||
unset($this->buffer[$data[2]]);
|
||||
|
||||
if(isset($data[3])){
|
||||
$diff = $data[3] - $this->counter[2];
|
||||
if($diff > 8){ //Packet recovery
|
||||
array_unshift($this->queue, array(0, $this->buffer[$data[3]][0], $this->buffer[$data[3]][1], $data[3]));
|
||||
}
|
||||
$this->counter[2] = $data[3];
|
||||
unset($this->buffer[$data[3]]);
|
||||
}
|
||||
break;
|
||||
case 0x07:
|
||||
$this->send(0x08, array(
|
||||
MAGIC,
|
||||
$this->server->serverID,
|
||||
$this->port,
|
||||
$data[3],
|
||||
0,
|
||||
));
|
||||
break;
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
case 0x82:
|
||||
case 0x83:
|
||||
case 0x84:
|
||||
case 0x85:
|
||||
case 0x86:
|
||||
case 0x87:
|
||||
case 0x88:
|
||||
case 0x89:
|
||||
case 0x8a:
|
||||
case 0x8b:
|
||||
case 0x8c:
|
||||
case 0x8d:
|
||||
case 0x8e:
|
||||
case 0x8f:
|
||||
if(isset($data[0])){
|
||||
$diff = $data[0] - $this->counter[1];
|
||||
if($diff > 1){ //Packet recovery
|
||||
for($i = $this->counter[1]; $i < $data[0]; ++$i){
|
||||
$this->send(0xa0, array(1, true, $i));
|
||||
}
|
||||
$this->counter[1] = $data[0];
|
||||
}elseif($diff === 1){
|
||||
$this->counter[1] = $data[0];
|
||||
}
|
||||
$this->send(0xc0, array(1, true, $data[0]));
|
||||
}
|
||||
switch($data["id"]){
|
||||
|
||||
case MC_KEEP_ALIVE:
|
||||
|
||||
break;
|
||||
case 0x03:
|
||||
|
||||
break;
|
||||
case MC_DISCONNECT:
|
||||
$this->close("client disconnect");
|
||||
break;
|
||||
case MC_CLIENT_CONNECT:
|
||||
$this->dataPacket(MC_SERVER_HANDSHAKE, array(
|
||||
"port" => $this->port,
|
||||
"session" => $data["session"],
|
||||
"session2" => Utils::readLong("\x00\x00\x00\x00\x04\x44\x0b\xa9"),
|
||||
));
|
||||
break;
|
||||
case MC_CLIENT_HANDSHAKE:
|
||||
|
||||
break;
|
||||
case MC_LOGIN:
|
||||
if($this->loggedIn === true){
|
||||
break;
|
||||
}
|
||||
$this->loggedIn = true;
|
||||
$this->username = str_replace(array("\x00", "/", " ", "\r", "\n"), array("", "-", "_", "", ""), $data["username"]);
|
||||
if($this->username == ""){
|
||||
$this->close("bad username", false);
|
||||
break;
|
||||
}
|
||||
$o = $this->server->api->player->getOffline($this->username);
|
||||
if($this->server->whitelist === true and !$this->server->api->ban->inWhitelist($this->username)){
|
||||
$this->close("\"\x1b[33m".$this->username."\x1b[0m\" not being on white-list", false);
|
||||
break;
|
||||
}elseif($this->server->api->ban->isBanned($this->username) or $this->server->api->ban->isIPBanned($this->ip)){
|
||||
$this->close("\"\x1b[33m".$this->username."\x1b[0m\" is banned!", false);
|
||||
}
|
||||
$u = $this->server->api->player->get($this->username);
|
||||
$c = $this->server->api->player->getByClientID($this->clientID);
|
||||
if($u !== false){
|
||||
$u->close("logged in from another location");
|
||||
}
|
||||
if($c !== false){
|
||||
$c->close("logged in from another location");
|
||||
}
|
||||
if($this->server->api->dhandle("player.join", $this) === false){
|
||||
$this->close();
|
||||
return;
|
||||
}
|
||||
$this->server->api->player->add($this->CID);
|
||||
$this->auth = true;
|
||||
if(!isset($this->data["inventory"]) or $this->server->gamemode === 1){
|
||||
$this->data["inventory"] = $this->inventory;
|
||||
}
|
||||
$this->inventory = &$this->data["inventory"];
|
||||
|
||||
$this->data["lastIP"] = $this->ip;
|
||||
$this->data["lastID"] = $this->clientID;
|
||||
$this->server->api->player->saveOffline($this->username, $this->data);
|
||||
$this->dataPacket(MC_LOGIN_STATUS, array(
|
||||
"status" => 0,
|
||||
));
|
||||
$this->dataPacket(MC_START_GAME, array(
|
||||
"seed" => $this->server->seed,
|
||||
"x" => $this->data["spawn"]["x"],
|
||||
"y" => $this->data["spawn"]["y"],
|
||||
"z" => $this->data["spawn"]["z"],
|
||||
"unknown1" => 0,
|
||||
"gamemode" => $this->server->gamemode,
|
||||
"eid" => 0,
|
||||
));
|
||||
break;
|
||||
case MC_READY:
|
||||
switch($data["status"]){
|
||||
case 1:
|
||||
if($this->spawned !== false){
|
||||
break;
|
||||
}
|
||||
$this->spawned = true;
|
||||
$this->entity = $this->server->api->entity->add(ENTITY_PLAYER, 0, array("player" => $this));
|
||||
$this->eid = $this->entity->eid;
|
||||
$this->server->query("UPDATE players SET EID = ".$this->eid." WHERE clientID = ".$this->clientID.";");
|
||||
$this->entity->x = $this->data["spawn"]["x"];
|
||||
$this->entity->y = $this->data["spawn"]["y"];
|
||||
$this->entity->z = $this->data["spawn"]["z"];
|
||||
$this->entity->setName($this->username);
|
||||
$this->entity->data["clientID"] = $this->clientID;
|
||||
$this->server->api->entity->spawnAll($this);
|
||||
$this->server->api->entity->spawnToAll($this->eid);
|
||||
$this->evid[] = $this->server->event("server.time", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("server.chat", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("entity.remove", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("entity.move", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("entity.animate", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("player.equipment.change", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("player.pickup", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("block.change", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("player.block.place", array($this, "eventHandler"));
|
||||
console("[DEBUG] Player \"".$this->username."\" EID ".$this->eid." spawned at X ".$this->entity->x." Y ".$this->entity->y." Z ".$this->entity->z, true, true, 2);
|
||||
$this->eventHandler(new Container($this->server->motd), "server.chat");
|
||||
if($this->MTU <= 548){
|
||||
$this->eventHandler("Your connection is bad, you may experience lag and slow map loading.", "server.chat");
|
||||
}
|
||||
foreach($this->inventory as $s => $data){
|
||||
if($data[0] <= 0 or $data[2] <= 0){
|
||||
$this->inventory[$s] = array(0, 0, 0);
|
||||
continue;
|
||||
}
|
||||
$e = $this->server->api->entity->add(ENTITY_ITEM, $data[0], array(
|
||||
"x" => $this->entity->x + 0.5,
|
||||
"y" => $this->entity->y + 0.19,
|
||||
"z" => $this->entity->z + 0.5,
|
||||
"meta" => $data[1],
|
||||
"stack" => $data[2],
|
||||
));
|
||||
$this->server->api->entity->spawnTo($e->eid, $this);
|
||||
}
|
||||
break;
|
||||
case 2://Chunk loaded?
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MC_MOVE_PLAYER:
|
||||
if(is_object($this->entity)){
|
||||
$this->entity->setPosition($data["x"], $data["y"], $data["z"], $data["yaw"], $data["pitch"]);
|
||||
$this->server->api->dhandle("player.move", $this->entity);
|
||||
}
|
||||
break;
|
||||
case MC_PLAYER_EQUIPMENT:
|
||||
$data["eid"] = $this->eid;
|
||||
if($this->server->handle("player.equipment.change", $data) !== false){
|
||||
$this->equipment[0] = $data["block"];
|
||||
$this->equipment[1] = $data["meta"];
|
||||
console("[DEBUG] EID ".$this->eid." has now ".$data["block"].":".$data["meta"]." in their hands!", true, true, 2);
|
||||
}
|
||||
break;
|
||||
case MC_REQUEST_CHUNK:
|
||||
$this->actionQueue('
|
||||
$max = max(1, floor(($this->MTU - 16 - 255) / 192));
|
||||
$chunk = $this->server->api->level->getOrderedChunk('.$data["x"].', '.$data["z"].', $max);
|
||||
foreach($chunk as $d){
|
||||
$this->dataPacket(MC_CHUNK_DATA, array(
|
||||
"x" => '.$data["x"].',
|
||||
"z" => '.$data["z"].',
|
||||
"data" => $d,
|
||||
), true);
|
||||
}
|
||||
');
|
||||
console("[INTERNAL] Chunk X ".$data["x"]." Z ".$data["z"]." requested", true, true, 3);
|
||||
break;
|
||||
case MC_USE_ITEM:
|
||||
$data["eid"] = $this->eid;
|
||||
if(Utils::distance($this->entity->position, $data) > 10){
|
||||
break;
|
||||
}elseif($this->server->gamemode === 0 and !$this->hasItem($data["block"], $data["meta"])){
|
||||
console("[DEBUG] Player \"".$this->username."\" tried to place not got block (or crafted block)", true, true, 2);
|
||||
//break;
|
||||
}
|
||||
$this->server->handle("player.block.action", $data);
|
||||
break;
|
||||
case MC_REMOVE_BLOCK:
|
||||
$data["eid"] = $this->eid;
|
||||
if(Utils::distance($this->entity->position, $data) > 8){
|
||||
break;
|
||||
}
|
||||
$this->server->handle("player.block.break", $data);
|
||||
break;
|
||||
case MC_INTERACT:
|
||||
if(isset($this->server->entities[$data["target"]]) and Utils::distance($this->entity->position, $this->server->entities[$data["target"]]->position) <= 8){
|
||||
if($this->handle("player.interact", $data) !== false){
|
||||
console("[DEBUG] EID ".$this->eid." attacked EID ".$data["target"], true, true, 2);
|
||||
if($this->server->gamemode !== 1 and $this->server->difficulty > 0){
|
||||
$this->server->api->entity->harm($data["target"], $this->server->difficulty, $this->eid);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_ANIMATE:
|
||||
$this->server->api->dhandle("entity.animate", array("eid" => $this->eid, "action" => $data["action"]));
|
||||
break;
|
||||
case MC_RESPAWN:
|
||||
$this->entity->invincible = true;
|
||||
$this->entity->setHealth(20, "respawn");
|
||||
$this->entity->setPosition($data["x"], $data["y"], $data["z"], 0, 0);
|
||||
$this->entity->invincible = false;
|
||||
break;
|
||||
case MC_SET_HEALTH:
|
||||
if($this->server->gamemode === 1){
|
||||
break;
|
||||
}
|
||||
//$this->entity->setHealth($data["health"], "client");
|
||||
break;
|
||||
case MC_DROP_ITEM:
|
||||
if($this->server->handle("player.drop", $data) !== false){
|
||||
$this->server->api->block->drop($this->entity->x, $this->entity->y, $this->entity->z, $data["block"], $data["meta"], $data["stack"]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console("[DEBUG] Unhandled 0x".dechex($data["id"])." Data Packet for Client ID ".$this->clientID.": ".print_r($data, true), true, true, 2);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function send($pid, $data = array(), $raw = false){
|
||||
if($this->connected === true){
|
||||
$this->server->send($pid, $data, $raw, $this->ip, $this->port);
|
||||
}
|
||||
}
|
||||
|
||||
public function actionQueue($code){
|
||||
$this->queue[] = array(1, $code);
|
||||
}
|
||||
|
||||
public function dataPacket($id, $data = array(), $queue = false, $count = false){
|
||||
if($queue === true){
|
||||
$this->queue[] = array(0, $id, $data, $count);
|
||||
}else{
|
||||
if($count === false){
|
||||
$count = $this->counter[0];
|
||||
++$this->counter[0];
|
||||
if(count($this->buffer) >= 512){
|
||||
array_shift($this->buffer);
|
||||
}
|
||||
$this->buffer[$count] = array($id, $data);
|
||||
}
|
||||
$data["id"] = $id;
|
||||
$this->send(0x80, array(
|
||||
$count,
|
||||
0x00,
|
||||
$data,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -25,28 +25,34 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
*/
|
||||
|
||||
class PocketMinecraftServer extends stdClass{
|
||||
var $invisible, $tickMeasure, $preparedSQL, $seed, $gamemode, $name, $maxClients, $clients, $eidCnt, $custom, $description, $motd, $timePerSecond, $responses, $spawn, $entities, $mapDir, $mapName, $map, $level, $tileEntities;
|
||||
private $database, $interface, $evCnt, $handCnt, $events, $handlers, $version, $serverType, $lastTick;
|
||||
function __construct($name, $gamemode = 1, $seed = false, $port = 19132, $serverID = false, $version = CURRENT_VERSION){
|
||||
$this->port = (int) $port; //19132 - 19135
|
||||
console("[INFO] PocketMine-MP ".MAJOR_VERSION." by @shoghicp, LGPL License", true, true, 0);
|
||||
class PocketMinecraftServer{
|
||||
var $version, $invisible, $api, $tickMeasure, $preparedSQL, $seed, $gamemode, $name, $maxClients, $clients, $eidCnt, $custom, $description, $motd, $timePerSecond, $spawn, $entities, $mapDir, $mapName, $map, $levelData, $tileEntities;
|
||||
private $database, $interface, $evCnt, $handCnt, $events, $handlers, $serverType, $lastTick, $ticker;
|
||||
|
||||
private function load(){
|
||||
$this->version = new VersionString();
|
||||
console("[INFO] \x1b[33;1mPocketMine-MP ".MAJOR_VERSION." #".$this->version->getNumber()." by @shoghicp, LGPL License", true, true, 0);
|
||||
console("[INFO] Target Minecraft PE: \x1b[36;1m".CURRENT_MINECRAFT_VERSION."\x1b[0m, protocol #".CURRENT_PROTOCOL, true, true, 0);
|
||||
if($this->version->isDev()){
|
||||
console("[INFO] \x1b[31;1mThis is a Development version");
|
||||
}
|
||||
console("[INFO] Starting Minecraft PE Server at *:".$this->port);
|
||||
if($this->port < 19132 or $this->port > 19135){
|
||||
console("[WARNING] You've selected a not-standard port. Normal port range is from 19132 to 19135 included");
|
||||
}
|
||||
$this->serverID = $this->serverID === false ? Utils::readLong(Utils::getRandomBytes(8)):$this->serverID;
|
||||
$this->seed = $this->seed === false ? Utils::readInt(Utils::getRandomBytes(4)):$this->seed;
|
||||
console("[INFO] Loading database...");
|
||||
$this->startDatabase();
|
||||
$this->gamemode = (int) $gamemode;
|
||||
$this->version = (int) $version;
|
||||
$this->name = $name;
|
||||
$this->doTick = false;
|
||||
$this->api = false;
|
||||
$this->mapDir = false;
|
||||
$this->mapName = false;
|
||||
$this->events = array();
|
||||
$this->handlers = array();
|
||||
$this->map = false;
|
||||
$this->invisible = false;
|
||||
$this->level = false;
|
||||
$this->levelData = false;
|
||||
$this->difficulty = 1;
|
||||
$this->tileEntities = array();
|
||||
$this->entities = array();
|
||||
@ -59,41 +65,42 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->scheduleCnt = 0;
|
||||
$this->description = "";
|
||||
$this->whitelist = false;
|
||||
$this->bannedIPs = array();
|
||||
$this->motd = "Welcome to ".$name;
|
||||
$this->serverID = $serverID === false ? Utils::readLong(Utils::getRandomBytes(8)):$serverID;
|
||||
$this->seed = $seed === false ? Utils::readInt(Utils::getRandomBytes(4)):$seed;
|
||||
$this->clients = array();
|
||||
$this->spawn = array("x" => 128.5,"y" => 100,"z" => 128.5);
|
||||
$this->time = 0;
|
||||
$this->timePerSecond = 10;
|
||||
$this->tickMeasure = array_fill(0, 40, 0);
|
||||
$this->setType("normal");
|
||||
$this->interface = new MinecraftInterface("255.255.255.255", $this->port, true, false);
|
||||
$this->interface = new MinecraftInterface("255.255.255.255", $this->port, true, false);
|
||||
$this->reloadConfig();
|
||||
console("[INFO] Server Name: ".$this->name);
|
||||
console("[INFO] Server GUID: ".$this->serverID);
|
||||
console("[INFO] Protocol Version: ".CURRENT_PROTOCOL);
|
||||
console("[INFO] Max Clients: ".$this->maxClients);
|
||||
$this->stop = false;
|
||||
console("[INFO] Server Name: \x1b[36m".$this->name."\x1b[0m");
|
||||
console("[DEBUG] Server ID: ".$this->serverID, true, true, 2);
|
||||
$this->stop = false;
|
||||
}
|
||||
|
||||
function __construct($name, $gamemode = 1, $seed = false, $port = 19132, $serverID = false){
|
||||
$this->port = (int) $port; //19132 - 19135
|
||||
$this->gamemode = (int) $gamemode;
|
||||
$this->name = $name;
|
||||
$this->motd = "Welcome to ".$name;
|
||||
$this->serverID = $serverID;
|
||||
$this->seed = $seed;
|
||||
$this->load();
|
||||
}
|
||||
|
||||
public function getTPS(){
|
||||
$v = array_values($this->tickMeasure);
|
||||
$tps = 40 / ($v[39] - $v[0]);
|
||||
return round($tps, 4);
|
||||
}
|
||||
|
||||
public function loadEvents(){
|
||||
$this->event("server.chat", array($this, "eventHandler"));
|
||||
$this->event("player.new", array($this, "eventHandler"));
|
||||
|
||||
$this->action(500000, '$this->time += (int) ($this->timePerSecond / 2);$this->api->dhandle("server.time.change", $this->time);');
|
||||
|
||||
public function loadEvents(){
|
||||
$this->action(500000, '$this->time += (int) ($this->timePerSecond / 2);$this->api->dhandle("server.time", $this->time);');
|
||||
$this->action(5000000, 'if($this->difficulty < 2){$this->api->dhandle("server.regeneration", 1);}');
|
||||
$this->action(1000000 * 60, '$this->reloadConfig();');
|
||||
$this->action(1000000 * 60 * 10, '$this->custom = array();');
|
||||
if($this->api !== false){
|
||||
$this->action(1000000 * 80, '$this->chat(false, "Online (".count($this->clients)."): ".implode(", ",$this->api->player->online()));');
|
||||
$this->action(1000000 * 80, '$cnt = count($this->clients); if($cnt > 1){$this->api->chat->broadcast("Online (".$cnt."): ".implode(", ",$this->api->player->online()));}');
|
||||
}
|
||||
$this->action(1000000 * 120, '$this->debugInfo(true);');
|
||||
}
|
||||
@ -101,7 +108,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
public function startDatabase(){
|
||||
$this->preparedSQL = new stdClass();
|
||||
$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 secure_delete = OFF;");
|
||||
$this->query("CREATE TABLE players (clientID INTEGER PRIMARY KEY, EID NUMERIC, ip TEXT, port NUMERIC, name TEXT UNIQUE);");
|
||||
@ -111,12 +118,12 @@ class PocketMinecraftServer extends stdClass{
|
||||
$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("PRAGMA synchronous = OFF;");
|
||||
$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 = :name;");
|
||||
$this->preparedSQL->selectHandlers = $this->database->prepare("SELECT DISTINCT ID FROM handlers WHERE name = :name ORDER BY priority DESC;");
|
||||
$this->preparedSQL->selectEvents = $this->database->prepare("SELECT DISTINCT ID FROM events WHERE name = :name;");
|
||||
$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);");
|
||||
}
|
||||
|
||||
|
||||
public function query($sql, $fetch = false){
|
||||
console("[INTERNAL] [SQL] ".$sql, true, true, 3);
|
||||
$result = $this->database->query($sql) or console("[ERROR] [SQL Error] ".$this->database->lastErrorMsg().". Query: ".$sql, true, true, 0);
|
||||
@ -125,14 +132,11 @@ class PocketMinecraftServer extends stdClass{
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function reloadConfig(){
|
||||
if($this->whitelist === true or is_array($this->whitelist)){
|
||||
$this->whitelist = explode("\n", str_replace(array("\t","\r"), "", file_get_contents(FILE_PATH."white-list.txt")));
|
||||
}
|
||||
$this->bannedIPs = explode("\n", str_replace(array(" ","\t","\r"), "", file_get_contents(FILE_PATH."banned-ips.txt")));
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function debugInfo($console = false){
|
||||
$info = array();
|
||||
$info["tps"] = $this->getTPS();
|
||||
@ -142,34 +146,40 @@ class PocketMinecraftServer extends stdClass{
|
||||
$info["entities"] = $info["entities"]["count"];
|
||||
$info["events"] = $this->query("SELECT count(ID) as count FROM events;", true);
|
||||
$info["events"] = $info["events"]["count"];
|
||||
$info["handlers"] = $this->query("SELECT count(ID) as count FROM handlers;", true);
|
||||
$info["handlers"] = $info["handlers"]["count"];
|
||||
$info["actions"] = $this->query("SELECT count(ID) as count FROM actions;", true);
|
||||
$info["actions"] = $info["actions"]["count"];
|
||||
$info["garbage"] = gc_collect_cycles();
|
||||
$this->handle("server.debug", $info);
|
||||
if($console === true){
|
||||
console("[DEBUG] TPS: ".$info["tps"].", Memory usage: ".$info["memory_usage"]." (Peak ".$info["memory_peak_usage"]."), Entities: ".$info["entities"].", Events: ".$info["events"].", Actions: ".$info["actions"].", Garbage: ".$info["garbage"], true, true, 2);
|
||||
console("[DEBUG] TPS: ".$info["tps"].", Memory usage: ".$info["memory_usage"]." (Peak ".$info["memory_peak_usage"]."), Entities: ".$info["entities"].", Events: ".$info["events"].", Handlers: ".$info["handlers"].", Actions: ".$info["actions"].", Garbage: ".$info["garbage"], true, true, 2);
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
||||
public function close($reason = "stop"){
|
||||
if($this->stop !== true){
|
||||
$this->chat(false, "Stopping server...");
|
||||
if(is_int($reason)){
|
||||
$reason = "signal stop";
|
||||
}
|
||||
if(($this->api instanceof ServerAPI) === true){
|
||||
if(($this->api->chat instanceof ChatAPI) === true){
|
||||
$this->api->chat->send(false, "Stopping server...");
|
||||
}
|
||||
}
|
||||
//$this->ticker->stop = true;
|
||||
$this->save(true);
|
||||
$this->stop = true;
|
||||
$this->trigger("server.close");
|
||||
$this->trigger("server.close", $reason);
|
||||
$this->interface->close();
|
||||
}
|
||||
}
|
||||
|
||||
public function chat($owner, $text, $target = true){
|
||||
$message = "";
|
||||
if($owner !== false){
|
||||
$message = "<".$owner."> ";
|
||||
}
|
||||
$message .= $text;
|
||||
$this->handle("server.chat", $message);
|
||||
|
||||
public function chat($owner, $text, $target = false){
|
||||
$this->api->chat->send($owner, $text, $target);
|
||||
}
|
||||
|
||||
|
||||
public function setType($type = "normal"){
|
||||
switch($type){
|
||||
case "normal":
|
||||
@ -179,94 +189,121 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->serverType = "MCCPP;MINECON;";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function addHandler($event, $callable, $priority = 5){
|
||||
if(!is_callable($callable)){
|
||||
return false;
|
||||
}elseif(isset(Deprecation::$events[$event])){
|
||||
$sub = "";
|
||||
if(Deprecation::$events[$event] !== false){
|
||||
$sub = " Substitute \"".Deprecation::$events[$event]."\" found.";
|
||||
}
|
||||
console("[ERROR] Event \"$event\" has been deprecated.$sub [Adding handle to ".(is_array($callable) ? get_class($callable[0])."::".$callable[1]:$callable)."]");
|
||||
}
|
||||
$priority = (int) $priority;
|
||||
$this->handlers[$this->handCnt] = $callable;
|
||||
$this->query("INSERT INTO handlers (ID, name, priority) VALUES (".$this->handCnt.", '".str_replace("'", "\\'", $event)."', ".$priority.");");
|
||||
console("[INTERNAL] New handler ".(is_array($callable) ? get_class($callable[0])."::".$callable[1]:$callable)." to special event ".$event." (ID ".$this->handCnt.")", true, true, 3);
|
||||
return $this->handCnt++;
|
||||
$hnid = $this->handCnt++;
|
||||
$this->handlers[$hnid] = $callable;
|
||||
$this->query("INSERT INTO handlers (ID, name, priority) VALUES (".$hnid.", '".str_replace("'", "\\'", $event)."', ".$priority.");");
|
||||
console("[INTERNAL] New handler ".(is_array($callable) ? get_class($callable[0])."::".$callable[1]:$callable)." to special event ".$event." (ID ".$hnid.")", true, true, 3);
|
||||
return $hnid;
|
||||
}
|
||||
|
||||
|
||||
public function handle($event, &$data){
|
||||
$this->preparedSQL->selectHandlers->reset();
|
||||
$this->preparedSQL->selectHandlers->clear();
|
||||
$this->preparedSQL->selectHandlers->bindValue(":name", $event, SQLITE3_TEXT);
|
||||
$handlers = $this->preparedSQL->selectHandlers->execute();
|
||||
$result = true;
|
||||
if($handlers !== false and $handlers !== true){
|
||||
while(false !== ($hn = $handlers->fetchArray(SQLITE3_ASSOC)) and $result !== false){
|
||||
$handler = $this->handlers[(int) $hn["ID"]];
|
||||
if(is_array($handler)){
|
||||
$method = $handler[1];
|
||||
$result = $handler[0]->$method($data, $event);
|
||||
if($handlers !== false and $handlers !== true){
|
||||
console("[INTERNAL] Handling ".$event, true, true, 3);
|
||||
$call = array();
|
||||
while(($hn = $handlers->fetchArray(SQLITE3_ASSOC)) !== false){
|
||||
$call[(int) $hn["ID"]] = true;
|
||||
}
|
||||
$handlers->finalize();
|
||||
foreach($call as $hnid => $boolean){
|
||||
if($result !== false){
|
||||
$called[$hnid] = true;
|
||||
$handler = $this->handlers[$hnid];
|
||||
if(is_array($handler)){
|
||||
$method = $handler[1];
|
||||
$result = $handler[0]->$method($data, $event);
|
||||
}else{
|
||||
$result = $handler($data, $event);
|
||||
}
|
||||
}else{
|
||||
$result = $handler($data, $event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}elseif(isset(Deprecation::$events[$event])){
|
||||
$sub = "";
|
||||
if(Deprecation::$events[$event] !== false){
|
||||
$sub = " Substitute \"".Deprecation::$events[$event]."\" found.";
|
||||
}
|
||||
console("[ERROR] Event \"$event\" has been deprecated.$sub [Handler]");
|
||||
}
|
||||
$handlers->finalize();
|
||||
|
||||
if($result !== false){
|
||||
$this->trigger($event, $data);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function eventHandler($data, $event){
|
||||
switch($event){
|
||||
case "player.new":
|
||||
console("[DEBUG] Player \"".$data["username"]."\" EID ".$data["eid"]." spawned at X ".$data["x"]." Y ".$data["y"]." Z ".$data["z"], true, true, 2);
|
||||
break;
|
||||
case "server.chat":
|
||||
console("[CHAT] $data");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function loadMap(){
|
||||
if($this->mapName !== false and trim($this->mapName) !== ""){
|
||||
$this->level = unserialize(file_get_contents($this->mapDir."level.dat"));
|
||||
console("[INFO] Map: ".$this->level["LevelName"]);
|
||||
$this->time = (int) $this->level["Time"];
|
||||
$this->seed = (int) $this->level["RandomSeed"];
|
||||
if(isset($this->level["SpawnX"])){
|
||||
$this->spawn = array("x" => $this->level["SpawnX"], "y" => $this->level["SpawnY"], "z" => $this->level["SpawnZ"]);
|
||||
}else{
|
||||
$this->level["SpawnX"] = $this->spawn["x"];
|
||||
$this->level["SpawnY"] = $this->spawn["y"];
|
||||
$this->level["SpawnZ"] = $this->spawn["z"];
|
||||
if($this->mapName !== false and trim($this->mapName) !== ""){
|
||||
$this->levelData = unserialize(file_get_contents($this->mapDir."level.dat"));
|
||||
if($this->levelData === false){
|
||||
console("[ERROR] Invalid world data for \"".$this->mapDir."\. Please import the world correctly");
|
||||
$this->close("invalid world data");
|
||||
}
|
||||
$this->level["Time"] = &$this->time;
|
||||
console("[INFO] Spawn: X ".$this->level["SpawnX"]." Y ".$this->level["SpawnY"]." Z ".$this->level["SpawnZ"]);
|
||||
console("[INFO] Time: ".$this->time);
|
||||
console("[INFO] Seed: ".$this->seed);
|
||||
console("[INFO] Gamemode: ".($this->gamemode === 0 ? "survival":"creative"));
|
||||
console("[INFO] Map: ".$this->levelData["LevelName"]);
|
||||
$this->time = (int) $this->levelData["Time"];
|
||||
$this->seed = (int) $this->levelData["RandomSeed"];
|
||||
if(isset($this->levelData["SpawnX"])){
|
||||
$this->spawn = array("x" => $this->levelData["SpawnX"], "y" => $this->levelData["SpawnY"], "z" => $this->levelData["SpawnZ"]);
|
||||
}else{
|
||||
$this->levelData["SpawnX"] = $this->spawn["x"];
|
||||
$this->levelData["SpawnY"] = $this->spawn["y"];
|
||||
$this->levelData["SpawnZ"] = $this->spawn["z"];
|
||||
}
|
||||
$this->levelData["Time"] = $this->time;
|
||||
console("[INFO] Spawn: X \x1b[36m".$this->levelData["SpawnX"]."\x1b[0m Y \x1b[36m".$this->levelData["SpawnY"]."\x1b[0m Z \x1b[36m".$this->levelData["SpawnZ"]."\x1b[0m");
|
||||
console("[INFO] Time: \x1b[36m".$this->time."\x1b[0m");
|
||||
console("[INFO] Seed: \x1b[36m".$this->seed."\x1b[0m");
|
||||
console("[INFO] Gamemode: \x1b[36m".($this->gamemode === 0 ? "survival":"creative")."\x1b[0m");
|
||||
$d = array(0 => "peaceful", 1 => "easy", 2 => "normal", 3 => "hard");
|
||||
console("[INFO] Difficulty: ".$d[$this->difficulty]);
|
||||
console("[INFO] Difficulty: \x1b[36m".$d[$this->difficulty]."\x1b[0m");
|
||||
console("[INFO] Loading map...");
|
||||
$this->map = new ChunkParser();
|
||||
if(!$this->map->loadFile($this->mapDir."chunks.dat")){
|
||||
console("[ERROR] Couldn't load the map \"".$this->level["LevelName"]."\"!", true, true, 0);
|
||||
console("[ERROR] Couldn't load the map \"\x1b[32m".$this->levelData["LevelName"]."\x1b[0m\"!", true, true, 0);
|
||||
$this->map = false;
|
||||
}else{
|
||||
$this->map->loadMap();
|
||||
}
|
||||
}else{
|
||||
console("[INFO] Time: ".$this->time);
|
||||
console("[INFO] Seed: ".$this->seed);
|
||||
console("[INFO] Gamemode: ".($this->gamemode === 0 ? "survival":"creative"));
|
||||
console("[INFO] Time: \x1b[36m".$this->time."\x1b[0m");
|
||||
console("[INFO] Seed: \x1b[36m".$this->seed."\x1b[0m");
|
||||
console("[INFO] Gamemode: \x1b[36m".($this->gamemode === 0 ? "survival":"creative")."\x1b[0m");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function loadEntities(){
|
||||
if($this->map !== false){
|
||||
console("[INFO] Loading entities...");
|
||||
$entities = unserialize(file_get_contents($this->mapDir."entities.dat"));
|
||||
if($entities === false or !is_array($entities)){
|
||||
console("[ERROR] Invalid world data for \"".$this->mapDir."\. Please import the world correctly");
|
||||
$this->close("invalid world data");
|
||||
}
|
||||
foreach($entities as $entity){
|
||||
if(!isset($entity["id"])){
|
||||
break;
|
||||
@ -286,26 +323,28 @@ class PocketMinecraftServer extends stdClass{
|
||||
$e = $this->api->entity->add(ENTITY_MOB, $entity["id"]);
|
||||
$e->setPosition($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2], $entity["Rotation"][0], $entity["Rotation"][1]);
|
||||
$e->setHealth($entity["Health"]);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
console("[DEBUG] Loaded ".count($this->entities)." Entities", true, true, 2);
|
||||
$this->action(1000000 * 60 * 15, '$this->chat(false, "Forcing save...");$this->save();$this->chat(false, "Done");');
|
||||
}
|
||||
$this->action(1000000 * 60 * 15, '$this->api->chat->broadcast("Forcing save...");$this->save();');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function save($final = false){
|
||||
if($this->mapName !== false){
|
||||
file_put_contents($this->mapDir."level.dat", serialize($this->level));
|
||||
if($this->mapName !== false){
|
||||
$this->levelData["Time"] = $this->time;
|
||||
file_put_contents($this->mapDir."level.dat", serialize($this->levelData));
|
||||
$this->map->saveMap($final);
|
||||
console("[INFO] Saving entities...");
|
||||
foreach($this->entities as $entity){
|
||||
|
||||
|
||||
}
|
||||
$this->trigger("server.save", $final);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function init(){
|
||||
if($this->mapName !== false and $this->map === false){
|
||||
$this->loadMap();
|
||||
@ -313,34 +352,76 @@ class PocketMinecraftServer extends stdClass{
|
||||
}
|
||||
console("[INFO] Loading events...");
|
||||
$this->loadEvents();
|
||||
//$this->ticker = new TickLoop($this);
|
||||
//$this->ticker->start();
|
||||
declare(ticks=15);
|
||||
register_tick_function(array($this, "tick"));
|
||||
register_shutdown_function(array($this, "dumpError"));
|
||||
register_shutdown_function(array($this, "close"));
|
||||
if(function_exists("pcntl_signal")){
|
||||
pcntl_signal(SIGTERM, array($this, "close"));
|
||||
pcntl_signal(SIGINT, array($this, "close"));
|
||||
pcntl_signal(SIGHUP, array($this, "close"));
|
||||
}
|
||||
$this->trigger("server.start", microtime(true));
|
||||
console("[INFO] Server started!");
|
||||
$this->process();
|
||||
}
|
||||
|
||||
public function dumpError(){
|
||||
console("[ERROR] An Unrecovereable has ocurred and the server has Crashed. Creating an Error Dump");
|
||||
$dump = "# PocketMine-MP Error Dump ".date("D M j H:i:s T Y")."\r\n";
|
||||
$dump .= "Error: ".var_export(error_get_last(), true)."\r\n\r\n";
|
||||
$version = new VersionString();
|
||||
$dump .= "PM Version: ".$version." #".$version->getNumber()." [Protocol ".CURRENT_PROTOCOL."]\r\n";
|
||||
$dump .= "uname -a: ".php_uname("a")."\r\n";
|
||||
$dump .= "PHP Version: " .phpversion()."\r\n";
|
||||
$dump .= "Zend version: ".zend_version()."\r\n";
|
||||
$dump .= "OS : " .PHP_OS.", ".Utils::getOS()."\r\n";
|
||||
$dump .= "Debug Info: ".var_export($this->debugInfo(false), true)."\r\n\r\n\r\n";
|
||||
global $arguments;
|
||||
$dump .= "Parameters: ".var_export($arguments, true)."\r\n\r\n\r\n";
|
||||
$dump .= "server.properties: ".var_export($this->api->getProperties(), true)."\r\n\r\n\r\n";
|
||||
global $lasttrace;
|
||||
$dump .= "Last Backtrace: ".$lasttrace."\r\n\r\n\r\n";
|
||||
$dump .= "Loaded Modules: ".var_export(get_loaded_extensions(), true)."\r\n\r\n";
|
||||
$name = "error_dump_".time();
|
||||
logg($dump, $name, true, 0, true);
|
||||
console("[ERROR] Please submit the \"logs/{$name}.log\" file to the Bug Reporting page. Give as much info as you can.", true, true, 0);
|
||||
}
|
||||
|
||||
public function tick(){
|
||||
/*if($this->ticker->tick === true and $this->ticker->isWaiting() === true){
|
||||
$this->ticker->tick = false;
|
||||
$time = microtime(true);
|
||||
array_shift($this->tickMeasure);
|
||||
$this->tickMeasure[] = $this->lastTick = $time;
|
||||
$this->tickerFunction($time);
|
||||
$this->trigger("server.tick", $time);
|
||||
$this->ticker->notify();
|
||||
}*/
|
||||
$time = microtime(true);
|
||||
if($this->lastTick <= ($time - 0.05)){
|
||||
array_shift($this->tickMeasure);
|
||||
$this->tickMeasure[] = $this->lastTick = $time;
|
||||
$this->tickMeasure[] = $this->lastTick = $time;
|
||||
$this->tickerFunction($time);
|
||||
$this->trigger("server.tick", $time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function clientID($ip, $port){
|
||||
return md5($pi . $port, true);
|
||||
return md5($ip . $port, true);
|
||||
}
|
||||
|
||||
|
||||
public function packetHandler($packet){
|
||||
$data =& $packet["data"];
|
||||
$CID = $this->clientID($packet["ip"], $packet["port"]);
|
||||
if(isset($this->clients[$CID])){
|
||||
$this->clients[$CID]->handle($packet["pid"], $data);
|
||||
}else{
|
||||
if($this->handle("server.noauthpacket", $packet) === false){
|
||||
return;
|
||||
}
|
||||
switch($packet["pid"]){
|
||||
case 0x02:
|
||||
if($this->invisible === true){
|
||||
@ -349,10 +430,10 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->serverID,
|
||||
MAGIC,
|
||||
$this->serverType,
|
||||
), false, $packet["ip"], $packet["port"]);
|
||||
), false, $packet["ip"], $packet["port"]);
|
||||
break;
|
||||
}
|
||||
if(in_array($packet["ip"], $this->bannedIPs)){
|
||||
if($this->api->ban->isIPBanned($packet["ip"])){
|
||||
$this->send(0x1c, array(
|
||||
$data[0],
|
||||
$this->serverID,
|
||||
@ -365,6 +446,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->custom["times_".$CID] = 0;
|
||||
}
|
||||
$ln = 15;
|
||||
$this->description .= " ";
|
||||
$txt = substr($this->description, $this->custom["times_".$CID], $ln);
|
||||
$txt .= substr($this->description, 0, $ln - strlen($txt));
|
||||
$this->send(0x1c, array(
|
||||
@ -376,7 +458,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->custom["times_".$CID] = ($this->custom["times_".$CID] + 1) % strlen($this->description);
|
||||
break;
|
||||
case 0x05:
|
||||
if(in_array($packet["ip"], $this->bannedIPs) or count($this->clients) >= $this->maxClients){
|
||||
if($this->api->ban->isIPBanned($packet["ip"]) or count($this->clients) >= $this->maxClients){
|
||||
$this->send(0x80, array(
|
||||
0,
|
||||
0x00,
|
||||
@ -412,7 +494,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
}
|
||||
break;
|
||||
case 0x07:
|
||||
if(in_array($packet["ip"], $this->bannedIPs) or count($this->clients) >= $this->maxClients){
|
||||
if($this->api->ban->isIPBanned($packet["ip"]) or count($this->clients) >= $this->maxClients){
|
||||
$this->send(0x80, array(
|
||||
0,
|
||||
0x00,
|
||||
@ -433,28 +515,28 @@ class PocketMinecraftServer extends stdClass{
|
||||
$port = $data[2];
|
||||
$MTU = $data[3];
|
||||
$clientID = $data[4];
|
||||
$this->clients[$CID] = new Player($this, $clientID, $packet["ip"], $packet["port"], $MTU);
|
||||
$this->clients[$CID] = new Player($this, $clientID, $packet["ip"], $packet["port"], $MTU); //New Session!
|
||||
$this->clients[$CID]->handle(0x07, $data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function send($pid, $data = array(), $raw = false, $dest = false, $port = false){
|
||||
$this->interface->writePacket($pid, $data, $raw, $dest, $port);
|
||||
}
|
||||
|
||||
|
||||
public function process(){
|
||||
while($this->stop === false){
|
||||
$packet = @$this->interface->readPacket();
|
||||
$packet = $this->interface->readPacket();
|
||||
if($packet !== false){
|
||||
$this->packetHandler($packet);
|
||||
}else{
|
||||
usleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function trigger($event, $data = ""){
|
||||
$this->preparedSQL->selectEvents->reset();
|
||||
$this->preparedSQL->selectEvents->clear();
|
||||
@ -463,42 +545,51 @@ class PocketMinecraftServer extends stdClass{
|
||||
if($events === false or $events === true){
|
||||
return;
|
||||
}
|
||||
while(false !== ($evn = $events->fetchArray(SQLITE3_ASSOC))){
|
||||
$ev = $this->events[(int) $evn["ID"]];
|
||||
if(is_array($ev)){
|
||||
$method = $ev[1];
|
||||
$this->responses[(int) $evn["ID"]] = $ev[0]->$method($data, $event);
|
||||
}else{
|
||||
$this->responses[(int) $evn["ID"]] = $ev($data, $event);
|
||||
}
|
||||
$call = array();
|
||||
while(($evn = $events->fetchArray(SQLITE3_ASSOC)) !== false){
|
||||
$call[(int) $evn["ID"]] = true;
|
||||
}
|
||||
$events->finalize();
|
||||
if(count($call) > 0){
|
||||
foreach($call as $evid => $boolean){
|
||||
$ev = $this->events[$evid];
|
||||
if(!is_callable($ev)){
|
||||
$this->deleteEvent($evid);
|
||||
continue;
|
||||
}
|
||||
if(is_array($ev)){
|
||||
$method = $ev[1];
|
||||
$ev[0]->$method($data, $event);
|
||||
}else{
|
||||
$ev($data, $event);
|
||||
}
|
||||
}
|
||||
}elseif(isset(Deprecation::$events[$event])){
|
||||
$sub = "";
|
||||
if(Deprecation::$events[$event] !== false){
|
||||
$sub = " Substitute \"".Deprecation::$events[$event]."\" found.";
|
||||
}
|
||||
console("[ERROR] Event \"$event\" has been deprecated.$sub [Trigger]");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function response($eid){
|
||||
if(isset($this->responses[$eid])){
|
||||
$res = $this->responses[$eid];
|
||||
unset($this->responses[$eid]);
|
||||
return $res;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function schedule($ticks, $callback, $data = array(), $repeat = false, $eventName = "server.schedule"){
|
||||
if(!is_callable($callback)){
|
||||
return false;
|
||||
}
|
||||
$add = "";
|
||||
$chcnt = $this->scheduleCnt++;
|
||||
if($repeat === false){
|
||||
$add = ' unset($this->schedule['.$this->scheduleCnt.']);';
|
||||
$add = ' unset($this->schedule['.$chcnt.']);';
|
||||
}
|
||||
$this->schedule[$this->scheduleCnt] = array($callback, $data, $eventName);
|
||||
$this->action(50000 * $ticks, '$schedule = $this->schedule['.$this->scheduleCnt.'];'.$add.'if(!is_callable($schedule[0])){unset($this->schedule['.$this->scheduleCnt.']);return;} call_user_func($schedule[0], $schedule[1], $schedule[2]);', (bool) $repeat);
|
||||
return $this->scheduleCnt++;
|
||||
$this->schedule[$chcnt] = array($callback, $data, $eventName);
|
||||
$this->action(50000 * $ticks, '$schedule = $this->schedule['.$chcnt.'];'.$add.'if(!is_callable($schedule[0])){unset($this->schedule['.$chcnt.']);return false;} call_user_func($schedule[0], $schedule[1], $schedule[2]);', (bool) $repeat);
|
||||
return $chcnt;
|
||||
}
|
||||
|
||||
public function action($microseconds, $code, $repeat = true){
|
||||
|
||||
public function action($microseconds, $code, $repeat = true){
|
||||
$this->query("INSERT INTO actions (interval, last, code, repeat) VALUES(".($microseconds / 1000000).", ".microtime(true).", '".base64_encode($code)."', ".($repeat === true ? 1:0).");");
|
||||
console("[INTERNAL] Attached to action ".$microseconds, true, true, 3);
|
||||
}
|
||||
@ -509,13 +600,13 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->preparedSQL->selectActions->clear();
|
||||
$this->preparedSQL->selectActions->bindValue(":time", $time, SQLITE3_FLOAT);
|
||||
$actions = $this->preparedSQL->selectActions->execute();
|
||||
|
||||
|
||||
if($actions === false or $actions === true){
|
||||
return;
|
||||
}
|
||||
while(false !== ($action = $actions->fetchArray(SQLITE3_ASSOC))){
|
||||
eval(base64_decode($action["code"]));
|
||||
if($action["repeat"] === 0){
|
||||
while(($action = $actions->fetchArray(SQLITE3_ASSOC)) !== false){
|
||||
$return = eval(base64_decode($action["code"]));
|
||||
if($action["repeat"] === 0 or $return === false){
|
||||
$this->query("DELETE FROM actions WHERE ID = ".$action["ID"].";");
|
||||
}
|
||||
}
|
||||
@ -524,22 +615,29 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->preparedSQL->updateActions->clear();
|
||||
$this->preparedSQL->updateActions->bindValue(":time", $time, SQLITE3_FLOAT);
|
||||
$this->preparedSQL->updateActions->execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function event($event, $func){
|
||||
if(!is_callable($func)){
|
||||
return false;
|
||||
}elseif(isset(Deprecation::$events[$event])){
|
||||
$sub = "";
|
||||
if(Deprecation::$events[$event] !== false){
|
||||
$sub = " Substitute \"".Deprecation::$events[$event]."\" found.";
|
||||
}
|
||||
console("[ERROR] Event \"$event\" has been deprecated.$sub [Attach to ".(is_array($func) ? get_class($func[0])."::".$func[1]:$func)."]");
|
||||
}
|
||||
$this->events[$this->evCnt] = $func;
|
||||
$this->query("INSERT INTO events (ID, name) VALUES (".$this->evCnt.", '".str_replace("'", "\\'", $event)."');");
|
||||
console("[INTERNAL] Attached ".(is_array($func) ? get_class($func[0])."::".$func[1]:$func)." to event ".$event." (ID ".$this->evCnt.")", true, true, 3);
|
||||
return $this->evCnt++;
|
||||
$evid = $this->evCnt++;
|
||||
$this->events[$evid] = $func;
|
||||
$this->query("INSERT INTO events (ID, name) VALUES (".$evid.", '".str_replace("'", "\\'", $event)."');");
|
||||
console("[INTERNAL] Attached ".(is_array($func) ? get_class($func[0])."::".$func[1]:$func)." to event ".$event." (ID ".$evid.")", true, true, 3);
|
||||
return $evid;
|
||||
}
|
||||
|
||||
|
||||
public function deleteEvent($id){
|
||||
$id = (int) $id;
|
||||
unset($this->events[$id]);
|
||||
$this->query("DELETE FROM events WHERE ID = ".$id.";");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -30,7 +30,7 @@ class Sapling{
|
||||
const SPRUCE = 1;
|
||||
const BIRCH = 2;
|
||||
const BURN_TIME = 5;
|
||||
|
||||
|
||||
public static function growTree(LevelAPI $level, $block, $type){
|
||||
$type = $type & 0x03;
|
||||
TreeObject::growTree($level, $block, $type);
|
49
src/classes/inventory/Item.php
Normal file
49
src/classes/inventory/Item.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?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 Item{
|
||||
public $id;
|
||||
protected $maxStackSize = 64;
|
||||
private $durability = 0;
|
||||
private $name = "Unknown";
|
||||
public function __construct($id){
|
||||
$this->id = (int) $id;
|
||||
}
|
||||
|
||||
public function setMaxStackSize($size = 64){
|
||||
$this->maxStackSize = (int) $size;
|
||||
}
|
||||
|
||||
public function getDestroySpeed(Item $item, Entity $entity){
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getMaxStackSize(){
|
||||
return $this->maxStackSize;
|
||||
}
|
||||
|
||||
}
|
39
src/classes/inventory/Window.php
Normal file
39
src/classes/inventory/Window.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
define("WINDOW_CHEST", 0);
|
||||
define("WINDOW_WORKBENCH", 1);
|
||||
define("WINDOW_FURNACE", 2);
|
||||
|
||||
class Window{
|
||||
private $server;
|
||||
public function __construct(PocketMinecraftServer $server){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -27,7 +27,7 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
class Vector2{
|
||||
public $x, $y;
|
||||
|
||||
|
||||
public function __construct($x = 0, $y = 0){
|
||||
if(($x instanceof Vector2) === true){
|
||||
$this->__construct($x->x, $x->y);
|
||||
@ -36,23 +36,23 @@ class Vector2{
|
||||
$this->y = $y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getX(){
|
||||
return $this->x;
|
||||
}
|
||||
|
||||
|
||||
public function getY(){
|
||||
return $this->y;
|
||||
}
|
||||
|
||||
|
||||
public function getFloorX(){
|
||||
return (int) $this->x;
|
||||
}
|
||||
|
||||
|
||||
public function getFloorY(){
|
||||
return (int) $this->y;
|
||||
}
|
||||
|
||||
|
||||
public function add($x = 0, $y = 0){
|
||||
if(($x instanceof Vector2) === true){
|
||||
return $this->add($x->x, $x->y);
|
||||
@ -62,7 +62,7 @@ class Vector2{
|
||||
return new Vector3($this->x + $x, $this->y + $y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function subtract($x = 0, $y = 0){
|
||||
if(($x instanceof Vector2) === true){
|
||||
return $this->add(-$x->x, -$x->y);
|
||||
@ -70,23 +70,23 @@ class Vector2{
|
||||
return $this->add(-$x, -$y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function ceil(){
|
||||
return new Vector2((int) ($this->x + 1), (int) ($this->y + 1));
|
||||
}
|
||||
|
||||
|
||||
public function floor(){
|
||||
return new Vector2((int) $this->x, (int) $this->y);
|
||||
}
|
||||
|
||||
|
||||
public function round(){
|
||||
return new Vector2(round($this->x), round($this->y));
|
||||
}
|
||||
|
||||
|
||||
public function abs(){
|
||||
return new Vector2(abs($this->x), abs($this->y));
|
||||
}
|
||||
|
||||
|
||||
public function distance($x = 0, $y = 0){
|
||||
if(($x instanceof Vector2) === true){
|
||||
return sqrt($this->distanceSquared($x->x, $x->y));
|
||||
@ -94,7 +94,7 @@ class Vector2{
|
||||
return sqrt($this->distanceSquared($x, $y));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function distanceSquared($x = 0, $y = 0){
|
||||
if(($x instanceof Vector2) === true){
|
||||
return $this->distanceSquared($x->x, $x->y);
|
||||
@ -102,9 +102,9 @@ class Vector2{
|
||||
return pow($this->x - $x, 2) + pow($this->y - $y, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function __toString(){
|
||||
return "Vector2(x=".$this->x.",y=".$this->y.")";
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -27,7 +27,7 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
class Vector3{
|
||||
public $x, $y, $z;
|
||||
|
||||
|
||||
public function __construct($x = 0, $y = 0, $z = 0){
|
||||
if(($x instanceof Vector3) === true){
|
||||
$this->__construct($x->x, $x->y, $x->z);
|
||||
@ -37,51 +37,51 @@ class Vector3{
|
||||
$this->z = $z;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getX(){
|
||||
return $this->x;
|
||||
}
|
||||
|
||||
|
||||
public function getY(){
|
||||
return $this->y;
|
||||
}
|
||||
|
||||
|
||||
public function getZ(){
|
||||
return $this->z;
|
||||
}
|
||||
|
||||
|
||||
public function getFloorX(){
|
||||
return (int) $this->x;
|
||||
}
|
||||
|
||||
|
||||
public function getFloorY(){
|
||||
return (int) $this->y;
|
||||
}
|
||||
|
||||
|
||||
public function getFloorZ(){
|
||||
return (int) $this->z;
|
||||
}
|
||||
|
||||
|
||||
public function getRight(){
|
||||
return $this->getX();
|
||||
}
|
||||
|
||||
|
||||
public function getUp(){
|
||||
return $this->getY();
|
||||
}
|
||||
|
||||
|
||||
public function getForward(){
|
||||
return $this->getZ();
|
||||
}
|
||||
|
||||
|
||||
public function getSouth(){
|
||||
return $this->getX();
|
||||
}
|
||||
|
||||
|
||||
public function getWest(){
|
||||
return $this->getZ();
|
||||
}
|
||||
|
||||
|
||||
public function add($x = 0, $y = 0, $z = 0){
|
||||
if(($x instanceof Vector3) === true){
|
||||
return $this->add($x->x, $x->y, $x->z);
|
||||
@ -92,7 +92,7 @@ class Vector3{
|
||||
return new Vector3($this->x + $x, $this->y + $y, $this->z + $z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function subtract($x = 0, $y = 0, $z = 0){
|
||||
if(($x instanceof Vector3) === true){
|
||||
return $this->add(-$x->x, -$x->y, -$x->z);
|
||||
@ -100,23 +100,42 @@ class Vector3{
|
||||
return $this->add(-$x, -$y, -$z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function ceil(){
|
||||
return new Vector3((int) ($this->x + 1), (int) ($this->y + 1), (int) ($this->z + 1));
|
||||
}
|
||||
|
||||
|
||||
public function floor(){
|
||||
return new Vector3((int) $this->x, (int) $this->y, (int) $this->z);
|
||||
}
|
||||
|
||||
|
||||
public function round(){
|
||||
return new Vector3(round($this->x), round($this->y), round($this->z));
|
||||
}
|
||||
|
||||
|
||||
public function abs(){
|
||||
return new Vector3(abs($this->x), abs($this->y), abs($this->z));
|
||||
}
|
||||
|
||||
public function getSide($side){
|
||||
switch((int) $side){
|
||||
case 0:
|
||||
return new Vector3($this->x, $this->y - 1, $this->z);
|
||||
case 1:
|
||||
return new Vector3($this->x, $this->y + 1, $this->z);
|
||||
case 2:
|
||||
return new Vector3($this->x, $this->y, $this->z - 1);
|
||||
case 3:
|
||||
return new Vector3($this->x, $this->y, $this->z + 1);
|
||||
case 4:
|
||||
return new Vector3($this->x - 1, $this->y, $this->z);
|
||||
case 5:
|
||||
return new Vector3($this->x + 1, $this->y, $this->z);
|
||||
default:
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
public function distance($x = 0, $y = 0, $z = 0){
|
||||
if(($x instanceof Vector3) === true){
|
||||
return sqrt($this->distanceSquared($x->x, $x->y, $x->z));
|
||||
@ -124,7 +143,7 @@ class Vector3{
|
||||
return sqrt($this->distanceSquared($x, $y, $z));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function distanceSquared($x = 0, $y = 0, $z = 0){
|
||||
if(($x instanceof Vector3) === true){
|
||||
return $this->distanceSquared($x->x, $x->y, $x->z);
|
||||
@ -133,8 +152,16 @@ class Vector3{
|
||||
}
|
||||
}
|
||||
|
||||
public function maxPlainDistance($x = 0, $z = 0){
|
||||
if(($x instanceof Vector3) === true){
|
||||
return $this->maxPlainDistance($x->x, $x->z);
|
||||
}else{
|
||||
return max(abs($this->x - $x), abs($this->z - $z));
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
return "Vector3(x=".$this->x.",y=".$this->y.",z=".$this->z.")";
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -42,7 +42,7 @@ class CustomPacketHandler{
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
public function __construct($pid, $raw = "", $data = array(), $create = false){
|
||||
$this->raw = $raw;
|
||||
$this->data = $data;
|
||||
@ -54,7 +54,7 @@ class CustomPacketHandler{
|
||||
$this->data["payload"] = Utils::readLong($this->get(8));
|
||||
}else{
|
||||
$this->raw .= Utils::writeLong($this->data["payload"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x03:
|
||||
if($this->c === false){
|
||||
@ -63,10 +63,10 @@ class CustomPacketHandler{
|
||||
}else{
|
||||
$this->raw .= Utils::writeLong($this->data["unknown1"]);
|
||||
$this->raw .= Utils::writeLong($this->data["unknown2"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_CLIENT_CONNECT:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["clientID"] = Utils::readLong($this->get(8));
|
||||
$this->data["session"] = Utils::readLong($this->get(8));
|
||||
$this->data["unknown2"] = $this->get(1);
|
||||
@ -105,7 +105,7 @@ class CustomPacketHandler{
|
||||
$this->raw .= "\x00\x00";
|
||||
$this->raw .= Utils::writeLong($this->data["session"]);
|
||||
$this->raw .= Utils::writeLong($this->data["session2"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_CLIENT_HANDSHAKE:
|
||||
if($this->c === false){
|
||||
@ -137,7 +137,7 @@ class CustomPacketHandler{
|
||||
//null
|
||||
break;
|
||||
case MC_LOGIN:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["username"] = $this->get(Utils::readShort($this->get(2), false));
|
||||
$this->data["maxX"] = Utils::readInt($this->get(4));
|
||||
$this->data["maxY"] = Utils::readInt($this->get(4));
|
||||
@ -147,35 +147,35 @@ class CustomPacketHandler{
|
||||
}
|
||||
break;
|
||||
case MC_LOGIN_STATUS:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["status"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["status"]);
|
||||
}
|
||||
break;
|
||||
case MC_READY:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["status"] = ord($this->get(1));
|
||||
}else{
|
||||
$this->raw .= chr($this->data["status"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_CHAT:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["message"] = $this->get(Utils::readShort($this->get(2), false));
|
||||
}else{
|
||||
$this->raw .= Utils::writeShort(strlen($this->data["message"])).$this->data["message"];
|
||||
}
|
||||
break;
|
||||
case MC_SET_TIME:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["time"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["time"]);
|
||||
}
|
||||
break;
|
||||
case MC_START_GAME:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["seed"] = Utils::readInt($this->get(4));
|
||||
$this->data["unknown1"] = Utils::readInt($this->get(4));
|
||||
$this->data["gamemode"] = Utils::readInt($this->get(4));
|
||||
@ -191,9 +191,9 @@ class CustomPacketHandler{
|
||||
$this->raw .= Utils::writeFloat($this->data["x"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["y"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["z"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_ADD_MOB:
|
||||
case MC_ADD_MOB:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["type"] = Utils::readInt($this->get(4));
|
||||
@ -214,7 +214,7 @@ class CustomPacketHandler{
|
||||
));
|
||||
}
|
||||
break;
|
||||
case MC_ADD_PLAYER:
|
||||
case MC_ADD_PLAYER:
|
||||
if($this->c === false){
|
||||
$this->data["clientID"] = Utils::readLong($this->get(8));
|
||||
$this->data["username"] = $this->get(Utils::readShort($this->get(2), false));
|
||||
@ -298,7 +298,7 @@ class CustomPacketHandler{
|
||||
}
|
||||
break;
|
||||
case MC_MOVE_ENTITY:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["x"] = Utils::readFloat($this->get(4));
|
||||
$this->data["y"] = Utils::readFloat($this->get(4));
|
||||
@ -311,7 +311,7 @@ class CustomPacketHandler{
|
||||
}
|
||||
break;
|
||||
case MC_MOVE_ENTITY_POSROT:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["x"] = Utils::readFloat($this->get(4));
|
||||
$this->data["y"] = Utils::readFloat($this->get(4));
|
||||
@ -328,7 +328,7 @@ class CustomPacketHandler{
|
||||
}
|
||||
break;
|
||||
case MC_MOVE_PLAYER:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["x"] = Utils::readFloat($this->get(4));
|
||||
$this->data["y"] = Utils::readFloat($this->get(4));
|
||||
@ -345,7 +345,7 @@ class CustomPacketHandler{
|
||||
}
|
||||
break;
|
||||
case MC_PLACE_BLOCK:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
@ -361,10 +361,10 @@ class CustomPacketHandler{
|
||||
$this->raw .= chr($this->data["block"]);
|
||||
$this->raw .= chr($this->data["meta"]);
|
||||
$this->raw .= chr($this->data["face"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_REMOVE_BLOCK:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
@ -374,7 +374,7 @@ class CustomPacketHandler{
|
||||
$this->raw .= Utils::writeInt($this->data["x"]);
|
||||
$this->raw .= Utils::writeInt($this->data["z"]);
|
||||
$this->raw .= chr($this->data["y"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_UPDATE_BLOCK:
|
||||
if($this->c === false){
|
||||
@ -389,10 +389,35 @@ class CustomPacketHandler{
|
||||
$this->raw .= chr($this->data["y"]);
|
||||
$this->raw .= chr($this->data["block"]);
|
||||
$this->raw .= chr($this->data["meta"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_EXPLOSION:
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readFloat($this->get(4));
|
||||
$this->data["y"] = Utils::readFloat($this->get(4));
|
||||
$this->data["z"] = Utils::readFloat($this->get(4));
|
||||
$this->data["radius"] = Utils::readFloat($this->get(4));
|
||||
$this->data["count"] = Utils::readInt($this->get(4));
|
||||
$this->data["records"] = array();
|
||||
for($r = 0; $r < $this->data["count"]; ++$r){
|
||||
$this->data["records"][] = array(Utils::readByte($this->get(1)), Utils::readByte($this->get(1)), Utils::readByte($this->get(1)));
|
||||
}
|
||||
}else{
|
||||
$this->raw .= Utils::writeFloat($this->data["x"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["y"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["z"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["radius"]);
|
||||
$this->data["records"] = (array) $this->data["records"];
|
||||
$this->raw .= Utils::writeInt(count($this->data["records"]));
|
||||
if(count($this->data["records"]) > 0){
|
||||
foreach($this->data["records"] as $record){
|
||||
$this->raw .= Utils::writeByte($record[0]) . Utils::writeByte($record[1]) . Utils::writeByte($record[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_REQUEST_CHUNK:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
@ -401,7 +426,7 @@ class CustomPacketHandler{
|
||||
}
|
||||
break;
|
||||
case MC_CHUNK_DATA:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
$this->data["data"] = $this->get(true);
|
||||
@ -412,7 +437,7 @@ class CustomPacketHandler{
|
||||
}
|
||||
break;
|
||||
case MC_PLAYER_EQUIPMENT:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["block"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["meta"] = Utils::readShort($this->get(2), false);
|
||||
@ -420,10 +445,10 @@ class CustomPacketHandler{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeShort($this->data["block"]);
|
||||
$this->raw .= Utils::writeShort($this->data["meta"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_INTERACT:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["action"] = Utils::readByte($this->get(1));
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["target"] = Utils::readInt($this->get(4));
|
||||
@ -431,10 +456,10 @@ class CustomPacketHandler{
|
||||
$this->raw .= Utils::writeByte($this->data["action"]);
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeInt($this->data["target"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_USE_ITEM:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["y"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
@ -449,33 +474,33 @@ class CustomPacketHandler{
|
||||
/*$this->raw .= Utils::writeByte($this->data["action"]);
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeInt($this->data["target"]);*/
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_SET_ENTITY_DATA:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeMetadata(array(
|
||||
|
||||
|
||||
));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_SET_HEALTH:
|
||||
if($this->c === false){
|
||||
$this->data["health"] = ord($this->get(1));
|
||||
if($this->c === false){
|
||||
$this->data["health"] = Utils::readByte($this->get(1));
|
||||
}else{
|
||||
$this->raw .= chr($this->data["health"]);
|
||||
$this->raw .= Utils::writeByte($this->data["health"]);
|
||||
}
|
||||
break;
|
||||
case MC_ANIMATE:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["action"] = Utils::readByte($this->get(1));
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeByte($this->data["action"]);
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_RESPAWN:
|
||||
if($this->c === false){
|
||||
@ -488,17 +513,67 @@ class CustomPacketHandler{
|
||||
$this->raw .= Utils::writeFloat($this->data["x"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["y"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["z"]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_DROP_ITEM:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["unknown1"] = ord($this->get(1));
|
||||
$this->data["block"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["stack"] = ord($this->get(1));
|
||||
$this->data["meta"] = Utils::readShort($this->get(2), false);
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= chr($this->data["unknown1"]);
|
||||
$this->raw .= Utils::writeShort($this->data["block"]);
|
||||
$this->raw .= chr($this->data["stack"]);
|
||||
$this->raw .= Utils::writeShort($this->data["meta"]);
|
||||
}
|
||||
break;
|
||||
case MC_CONTAINER_OPEN:
|
||||
if($this->c === false){
|
||||
$this->data["windowid"] = ord($this->get(1));
|
||||
$this->data["type"] = ord($this->get(1));
|
||||
$this->data["slots"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["title"] = $this->get(Utils::readShort($this->get(2), false));
|
||||
}else{
|
||||
$this->raw .= chr($this->data["windowid"]);
|
||||
$this->raw .= chr($this->data["type"]);
|
||||
$this->raw .= Utils::writeShort($this->data["slots"]);
|
||||
$this->raw .= Utils::writeShort(strlen($this->data["title"])).$this->data["title"];
|
||||
}
|
||||
break;
|
||||
case MC_CONTAINER_CLOSE:
|
||||
if($this->c === false){
|
||||
$this->data["windowid"] = ord($this->get(1));
|
||||
}else{
|
||||
$this->raw .= chr($this->data["windowid"]);
|
||||
}
|
||||
break;
|
||||
case MC_CONTAINER_SET_SLOT:
|
||||
if($this->c === false){
|
||||
$this->data["windowid"] = ord($this->get(1));
|
||||
$this->data["slot"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["block"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["stack"] = ord($this->get(1));
|
||||
$this->data["meta"] = Utils::readShort($this->get(2), false);
|
||||
}else{
|
||||
$this->raw .= chr($this->data["windowid"]);
|
||||
$this->raw .= Utils::writeShort($this->data["slot"]);
|
||||
$this->raw .= Utils::writeShort($this->data["block"]);
|
||||
$this->raw .= chr($this->data["stack"]);
|
||||
$this->raw .= Utils::writeShort($this->data["meta"]);
|
||||
}
|
||||
break;
|
||||
case MC_CLIENT_MESSAGE:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["message"] = $this->get(Utils::readShort($this->get(2), false));
|
||||
}else{
|
||||
$this->raw .= Utils::writeShort(strlen($this->data["message"])).$this->data["message"];
|
||||
}
|
||||
break;
|
||||
case MC_SIGN_UPDATE:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readShort($this->get(2));
|
||||
$this->data["y"] = ord($this->get(1));
|
||||
$this->data["z"] = Utils::readShort($this->get(2));
|
||||
@ -515,7 +590,7 @@ class CustomPacketHandler{
|
||||
}
|
||||
break;
|
||||
case MC_ADVENTURE_SETTINGS:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readShort($this->get(2));
|
||||
$this->data["y"] = ord($this->get(1));
|
||||
$this->data["z"] = Utils::readShort($this->get(2));
|
||||
@ -525,10 +600,10 @@ class CustomPacketHandler{
|
||||
}else{
|
||||
$this->raw .= $this->data["unknown1"];
|
||||
$this->raw .= $this->data["unknown2"];
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if($this->c === false){
|
||||
if($this->c === false){
|
||||
console("[DEBUG] Received unknown Data Packet ID 0x".dechex($pid), true, true, 2);
|
||||
}else{
|
||||
console("[DEBUG] Sent unknown Data Packet ID 0x".dechex($pid), true, true, 2);
|
@ -26,33 +26,36 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
class MinecraftInterface{
|
||||
var $pstruct, $name, $client, $dataName;
|
||||
private $socket, $data;
|
||||
var $pstruct;
|
||||
var $name;
|
||||
var $client;
|
||||
var $dataName;
|
||||
private $socket;
|
||||
private $data;
|
||||
function __construct($server, $port = 25565, $listen = false, $client = true){
|
||||
$this->socket = new UDPSocket($server, $port, (bool) $listen);
|
||||
require("pstruct/RakNet.php");
|
||||
require("pstruct/packetName.php");
|
||||
require("pstruct/protocol.php");
|
||||
require("pstruct/dataName.php");
|
||||
require("protocol/RakNet.php");
|
||||
require("protocol/packetName.php");
|
||||
require("protocol/current.php");
|
||||
require("protocol/dataName.php");
|
||||
$this->pstruct = $pstruct;
|
||||
$this->name = $packetName;
|
||||
$this->dataName = $dataName;
|
||||
$this->buffer = array();
|
||||
$this->client = (bool) $client;
|
||||
$this->start = microtime(true);
|
||||
}
|
||||
|
||||
|
||||
public function close(){
|
||||
return $this->socket->close();
|
||||
return $this->socket->close(false);
|
||||
}
|
||||
|
||||
|
||||
protected function getStruct($pid){
|
||||
if(isset($this->pstruct[$pid])){
|
||||
return $this->pstruct[$pid];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected function writeDump($pid, $raw, $data, $origin = "client", $ip = "", $port = 0){
|
||||
if(LOG === true and DEBUG >= 3){
|
||||
$p = "[".(microtime(true) - $this->start)."] [".((($origin === "client" and $this->client === true) or ($origin === "server" and $this->client === false)) ? "CLIENT->SERVER":"SERVER->CLIENT")." ".$ip.":".$port."]: ".(isset($data["id"]) ? "MC Packet ".$this->dataName[$pid]:$this->name[$pid])." (0x".Utils::strTohex(chr($pid)).") [length ".strlen($raw)."]".PHP_EOL;
|
||||
@ -65,9 +68,9 @@ class MinecraftInterface{
|
||||
$p .= PHP_EOL;
|
||||
logg($p, "packets", false);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function readPacket(){
|
||||
$p = $this->popPacket();
|
||||
if($p !== false){
|
||||
@ -90,13 +93,13 @@ class MinecraftInterface{
|
||||
logg($p, "packets", true, 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$packet = new Packet($pid, $struct, $data[0]);
|
||||
$packet->parse();
|
||||
@$packet->parse();
|
||||
$this->data[] = array($pid, $packet->data, $data[0], $data[1], $data[2]);
|
||||
return $this->popPacket();
|
||||
}
|
||||
|
||||
|
||||
public function popPacket(){
|
||||
if(count($this->data) > 0){
|
||||
$p = array_shift($this->data);
|
||||
@ -112,22 +115,22 @@ class MinecraftInterface{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function writePacket($pid, $data = array(), $raw = false, $dest = false, $port = false){
|
||||
$struct = $this->getStruct($pid);
|
||||
if($raw === false){
|
||||
$packet = new Packet($pid, $struct);
|
||||
$packet->data = $data;
|
||||
$packet->create();
|
||||
@$packet->create();
|
||||
$write = $this->socket->write($packet->raw, $dest, $port);
|
||||
$this->writeDump($pid, $packet->raw, $data, "client", $dest, $port);
|
||||
}else{
|
||||
$write = $this->socket->write($data, $dest, $port);
|
||||
$this->writeDump($pid, $data, false, "client", $dest, $port);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -30,7 +30,7 @@ class Packet{
|
||||
private $struct, $sock;
|
||||
protected $pid, $packet;
|
||||
public $data, $raw;
|
||||
|
||||
|
||||
function __construct($pid, $struct, $data = ""){
|
||||
$this->pid = $pid;
|
||||
$this->offset = 1;
|
||||
@ -42,7 +42,7 @@ class Packet{
|
||||
$this->struct = $struct;
|
||||
$this->sock = $sock;
|
||||
}
|
||||
|
||||
|
||||
public function create($raw = false){
|
||||
foreach($this->struct as $field => $type){
|
||||
if(!isset($this->data[$field])){
|
||||
@ -75,7 +75,7 @@ class Packet{
|
||||
case 0x40:
|
||||
$reply = new CustomPacketHandler($this->data[$field]["id"], "", $this->data[$field], true);
|
||||
$this->addRaw(Utils::writeShort((strlen($reply->raw) + 1) << 3));
|
||||
$this->addRaw(Utils::writeTriad($this->data[$field]["count"]));
|
||||
$this->addRaw(Utils::writeTriad(strrev($this->data[$field]["count"])));
|
||||
$this->addRaw(chr($this->data[$field]["id"]));
|
||||
$this->addRaw($reply->raw);
|
||||
break;
|
||||
@ -83,7 +83,7 @@ class Packet{
|
||||
$reply = new CustomPacketHandler($this->data[$field]["id"], "", $this->data[$field], true);
|
||||
$this->addRaw(Utils::writeShort((strlen($reply->raw) + 1) << 3));
|
||||
$this->addRaw(chr($this->data[$field]["id"]));
|
||||
$this->addRaw($reply->raw);
|
||||
$this->addRaw($reply->raw);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -136,10 +136,10 @@ class Packet{
|
||||
default:
|
||||
$this->addRaw(Utils::writeByte($this->data[$field]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function get($len = true){
|
||||
if($len === true){
|
||||
$data = substr($this->raw, $this->offset);
|
||||
@ -150,12 +150,12 @@ class Packet{
|
||||
$this->offset += $len;
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
protected function addRaw($str){
|
||||
$this->raw .= $str;
|
||||
return $str;
|
||||
}
|
||||
|
||||
|
||||
public function parse(){
|
||||
$continue = true;
|
||||
foreach($this->struct as $field => $type){
|
||||
@ -205,7 +205,7 @@ class Packet{
|
||||
break;
|
||||
case "byte":
|
||||
$this->data[] = Utils::readByte($this->get(1));
|
||||
break;
|
||||
break;
|
||||
case "ubyte":
|
||||
$this->data[] = ord($this->get(1));
|
||||
break;
|
||||
@ -231,8 +231,8 @@ class Packet{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -42,7 +42,7 @@ class SerializedPacketHandler{
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
public function __construct($pid, $raw = "", $data = array(), $create = false){
|
||||
$this->raw = $raw;
|
||||
$this->data = $data;
|
||||
@ -54,15 +54,15 @@ class SerializedPacketHandler{
|
||||
case 0x00:
|
||||
if($this->c === false){
|
||||
$this->data["packets"] = array();
|
||||
$i = 0;
|
||||
$i = 0;
|
||||
while($this->offset < strlen($this->raw)){
|
||||
if($i > 0){
|
||||
$pid = ord($this->get(1));
|
||||
}
|
||||
|
||||
|
||||
$len = ceil(Utils::readShort($this->get(2), false) / 8); //Utils::readShort($this->get(2), false) >> 3;
|
||||
if($pid !== 0x00){
|
||||
$c = Utils::readTriad($this->get(3));
|
||||
$c = Utils::readTriad(strrev($this->get(3)));
|
||||
}
|
||||
if($pid === 0x60 and $i === 0){
|
||||
$this->data["unknown1"] = $this->get(4);
|
@ -30,35 +30,27 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
class UDPSocket{
|
||||
private $encrypt;
|
||||
var $buffer, $connected, $errors, $sock, $server;
|
||||
|
||||
function __construct($server, $port, $listen = false, $socket = false){
|
||||
function __construct($server, $port, $listen = false){
|
||||
$this->errors = array_fill(88,(125 - 88) + 1, true);
|
||||
$this->server = $server;
|
||||
$this->port = $port;
|
||||
if($socket !== false){
|
||||
$this->sock = $socket;
|
||||
$this->sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
||||
socket_set_option($this->sock, SOL_SOCKET, SO_BROADCAST, 1); //Allow sending broadcast messages
|
||||
if($listen !== true){
|
||||
$this->connected = true;
|
||||
$this->buffer = array();
|
||||
$this->unblock();
|
||||
}else{
|
||||
$this->sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
||||
socket_set_option($this->sock, SOL_SOCKET, SO_BROADCAST, 1);
|
||||
if($listen !== true){
|
||||
$this->connected = true;
|
||||
$this->buffer = array();
|
||||
if(socket_bind($this->sock, "0.0.0.0", $port) === true){
|
||||
$this->unblock();
|
||||
}else{
|
||||
if(socket_bind($this->sock, "0.0.0.0", $port) === true){
|
||||
$this->unblock();
|
||||
}else{
|
||||
console("[ERROR] Couldn't bind to 0.0.0.0:".$port, true, true, 0);
|
||||
die();
|
||||
}
|
||||
console("[ERROR] Couldn't bind to 0.0.0.0:".$port, true, true, 0);
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function listenSocket(){
|
||||
|
||||
public function listenSocket(){
|
||||
$sock = @socket_accept($this->sock);
|
||||
if($sock !== false){
|
||||
$sock = new Socket(false, false, false, $sock);
|
||||
@ -67,17 +59,15 @@ class UDPSocket{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function close($error = 125){
|
||||
$this->connected = false;
|
||||
if($error === false){
|
||||
console("[ERROR] [Socket] Socket closed, Error: End of Stream");
|
||||
}else{
|
||||
if($error !== false){
|
||||
console("[ERROR] [Socket] Socket closed, Error $error: ".socket_strerror($error));
|
||||
}
|
||||
return @socket_close($this->sock);
|
||||
}
|
||||
|
||||
|
||||
public function block(){
|
||||
socket_set_block($this->sock);
|
||||
}
|
||||
@ -85,18 +75,18 @@ class UDPSocket{
|
||||
public function unblock(){
|
||||
socket_set_nonblock($this->sock);
|
||||
}
|
||||
|
||||
|
||||
public function read(){
|
||||
$source = false;
|
||||
$port = 1;
|
||||
$len = @socket_recvfrom($this->sock, $buf, 65536, 0, $source, $port);
|
||||
return array($buf, $source, $port, $len);
|
||||
}
|
||||
|
||||
|
||||
public function write($data, $dest = false, $port = false){
|
||||
return @socket_sendto($this->sock, $data, strlen($data), 0, ($dest === false ? $this->server:$dest), ($port === false ? $this->port:$port));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* {@internal (all DocBlock comments regarding implementation - such as the one that follows - refer to the
|
||||
* {@internal (all DocBlock comments regarding implementation - such as the one that follows - refer to the
|
||||
* {@link MATH_BIGINTEGER_MODE_INTERNAL MATH_BIGINTEGER_MODE_INTERNAL} mode)
|
||||
*
|
||||
* Math_BigInteger uses base-2**26 to perform operations such as multiplication and division and
|
||||
@ -53,10 +53,10 @@
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@ -234,7 +234,7 @@ class Math_BigInteger {
|
||||
/**
|
||||
* Mode independant value used for serialization.
|
||||
*
|
||||
* If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for
|
||||
* If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for
|
||||
* a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value,
|
||||
* however, $this->hex is only calculated when $this->__sleep() is called.
|
||||
*
|
||||
@ -750,7 +750,7 @@ class Math_BigInteger {
|
||||
$vars[] = 'precision';
|
||||
}
|
||||
return $vars;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2237,7 +2237,7 @@ class Math_BigInteger {
|
||||
/**
|
||||
* Montgomery Multiply
|
||||
*
|
||||
* Interleaves the montgomery reduction and long multiplication algorithms together as described in
|
||||
* Interleaves the montgomery reduction and long multiplication algorithms together as described in
|
||||
* {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
|
||||
*
|
||||
* @see _prepMontgomery()
|
||||
@ -2317,7 +2317,7 @@ class Math_BigInteger {
|
||||
* {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85}
|
||||
*
|
||||
* As for why we do all the bitmasking... strange things can happen when converting from floats to ints. For
|
||||
* instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields
|
||||
* instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields
|
||||
* int(-2147483648). To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't
|
||||
* auto-converted to floats. The outermost bitmask is present because without it, there's no guarantee that
|
||||
* the "residue" returned would be the so-called "common residue". We use fmod, in the last step, because the
|
||||
@ -3217,7 +3217,7 @@ class Math_BigInteger {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
* @internal Uses the
|
||||
* {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See
|
||||
* {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See
|
||||
* {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24}.
|
||||
*/
|
||||
function isPrime($t = false)
|
||||
@ -3266,16 +3266,16 @@ class Math_BigInteger {
|
||||
|
||||
if (!isset($primes)) {
|
||||
$primes = array(
|
||||
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
|
||||
61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
|
||||
139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
|
||||
229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313,
|
||||
317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
|
||||
421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
|
||||
521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617,
|
||||
619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727,
|
||||
733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
|
||||
839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
|
||||
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
|
||||
61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
|
||||
139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
|
||||
229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313,
|
||||
317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
|
||||
421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
|
||||
521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617,
|
||||
619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727,
|
||||
733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
|
||||
839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
|
||||
953, 967, 971, 977, 983, 991, 997
|
||||
);
|
||||
|
231
src/classes/utils/Config.php
Normal file
231
src/classes/utils/Config.php
Normal file
@ -0,0 +1,231 @@
|
||||
<?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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
define("CONFIG_DETECT", -1); //Detect by file extension
|
||||
define("CONFIG_PROPERTIES", 0); // .properties
|
||||
define("CONFIG_CNF", CONFIG_PROPERTIES); // .cnf
|
||||
define("CONFIG_JSON", 1); // .js, .json
|
||||
define("CONFIG_YAML", 2); // .yml, .yaml
|
||||
//define("CONFIG_EXPORT", 3); // .export, .xport
|
||||
define("CONFIG_SERIALIZED", 4); // .sl
|
||||
define("CONFIG_LIST", 5); // .txt, .list
|
||||
|
||||
class Config{
|
||||
private $config;
|
||||
private $file;
|
||||
private $correct;
|
||||
private $type = CONFIG_DETECT;
|
||||
public static $formats = array(
|
||||
"properties" => CONFIG_PROPERTIES,
|
||||
"cnf" => CONFIG_CNF,
|
||||
"conf" => CONFIG_CNF,
|
||||
"config" => CONFIG_CNF,
|
||||
"json" => CONFIG_JSON,
|
||||
"js" => CONFIG_JSON,
|
||||
"yml" => CONFIG_YAML,
|
||||
"yaml" => CONFIG_YAML,
|
||||
//"export" => CONFIG_EXPORT,
|
||||
//"xport" => CONFIG_EXPORT,
|
||||
"sl" => CONFIG_SERIALIZED,
|
||||
"serialize" => CONFIG_SERIALIZED,
|
||||
"txt" => CONFIG_LIST,
|
||||
"list" => CONFIG_LIST,
|
||||
);
|
||||
public function __construct($file, $type = CONFIG_DETECT, $default = array(), &$correct = null){
|
||||
$this->load($file, $type, $default);
|
||||
$correct = $this->check();
|
||||
}
|
||||
|
||||
public function load($file, $type = CONFIG_DETECT, $default = array()){
|
||||
$this->correct = true;
|
||||
$this->type = (int) $type;
|
||||
$this->file = $file;
|
||||
if(!is_array($default)){
|
||||
$default = array();
|
||||
}
|
||||
if(!file_exists($file)){
|
||||
$this->config = $default;
|
||||
}else{
|
||||
if($this->type === CONFIG_DETECT){
|
||||
$extension = explode(".", basename($this->file));
|
||||
$extension = strtolower(trim(array_pop($extension)));
|
||||
if(isset(Config::$formats[$extension])){
|
||||
$this->type = Config::$formats[$extension];
|
||||
}else{
|
||||
$this->correct = false;
|
||||
}
|
||||
}
|
||||
if($this->correct === true){
|
||||
$content = @file_get_contents($this->file);
|
||||
switch($this->type){
|
||||
case CONFIG_PROPERTIES:
|
||||
case CONFIG_CNF:
|
||||
$this->parseProperties($content);
|
||||
break;
|
||||
case CONFIG_JSON:
|
||||
$this->config = @json_decode($content, true);
|
||||
break;
|
||||
case CONFIG_YAML:
|
||||
$this->config = Spyc::YAMLLoad($content);
|
||||
break;
|
||||
case CONFIG_SERIALIZED:
|
||||
$this->config = @unserialize($content);
|
||||
break;
|
||||
case CONFIG_LIST:
|
||||
$this->parseList($content);
|
||||
break;
|
||||
default:
|
||||
$this->correct = false;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
if(!is_array($this->config)){
|
||||
$this->config = $default;
|
||||
}
|
||||
$this->fillDefaults($default, $this->config);
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function check(){
|
||||
return $this->correct === true;
|
||||
}
|
||||
|
||||
public function save(){
|
||||
if($this->correct === true){
|
||||
switch($this->type){
|
||||
case CONFIG_PROPERTIES:
|
||||
case CONFIG_CNF:
|
||||
$content = $this->writeProperties();
|
||||
break;
|
||||
case CONFIG_JSON:
|
||||
$content = json_encode($this->config);
|
||||
break;
|
||||
case CONFIG_YAML:
|
||||
$content = Spyc::YAMLDump($this->config);
|
||||
break;
|
||||
case CONFIG_SERIALIZED:
|
||||
$content = @serialize($this->config);
|
||||
break;
|
||||
case CONFIG_LIST:
|
||||
$content = implode("\r\n", array_keys($this->config));
|
||||
break;
|
||||
}
|
||||
@file_put_contents($this->file, $content, LOCK_EX);
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function get($k){
|
||||
if($this->correct === false or !isset($this->config[$k])){
|
||||
return false;
|
||||
}
|
||||
return ($this->config[$k]);
|
||||
}
|
||||
|
||||
public function set($k, $v = true){
|
||||
$this->config[$k] = $v;
|
||||
}
|
||||
|
||||
public function exists($k){
|
||||
return isset($this->config[$k]);
|
||||
}
|
||||
|
||||
public function remove($k){
|
||||
unset($this->config[$k]);
|
||||
}
|
||||
|
||||
public function getAll($keys = false){
|
||||
return ($keys === true ? array_keys($this->config):$this->config);
|
||||
}
|
||||
|
||||
private function fillDefaults($default, &$data){
|
||||
foreach($default as $k => $v){
|
||||
if(is_array($v)){
|
||||
if(!isset($data[$k]) or !is_array($data[$k])){
|
||||
$data[$k] = array();
|
||||
}
|
||||
$this->fillDefaults($v, $data[$k]);
|
||||
}elseif(!isset($data[$k])){
|
||||
$data[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function parseList($content){
|
||||
foreach(explode("\n", trim(str_replace("\r", "", $content))) as $v){
|
||||
$v = trim($v);
|
||||
if($v == ""){
|
||||
continue;
|
||||
}
|
||||
$this->config[$v] = true;
|
||||
}
|
||||
}
|
||||
|
||||
private function writeProperties(){
|
||||
$content = "#Properties Config file\r\n#".date("D M j H:i:s T Y")."\r\n";
|
||||
foreach($this->config as $k => $v){
|
||||
if(is_bool($v) === true){
|
||||
$v = $v === true ? "on":"off";
|
||||
}elseif(is_array($v)){
|
||||
$v = implode(";", $v);
|
||||
}
|
||||
$content .= $k."=".$v."\r\n";
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function parseProperties($content){
|
||||
if(preg_match_all('/([a-zA-Z0-9\-_]*)=([^\r\n]*)/u', $content, $matches) > 0){ //false or 0 matches
|
||||
foreach($matches[1] as $i => $k){
|
||||
$v = trim($matches[2][$i]);
|
||||
switch(strtolower($v)){
|
||||
case "on":
|
||||
case "true":
|
||||
case "yes":
|
||||
$v = true;
|
||||
break;
|
||||
case "off":
|
||||
case "false":
|
||||
case "no":
|
||||
$v = false;
|
||||
break;
|
||||
}
|
||||
if(isset($this->config[$k])){
|
||||
console("[NOTICE] [Config] Repeated property ".$k." on file ".$this->file, true, true, 2);
|
||||
}
|
||||
$this->config[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
73
src/classes/utils/Container.php
Normal file
73
src/classes/utils/Container.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?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 Container{
|
||||
private $payload = "", $whitelist = false, $blacklist = false;
|
||||
public function __construct($payload = "", $whitelist = false, $blacklist = false){
|
||||
$this->payload = $payload;
|
||||
if(is_array($whitelist)){
|
||||
$this->whitelist = $whitelist;
|
||||
}
|
||||
if(is_array($blacklist)){
|
||||
$this->blacklist = $blacklist;
|
||||
}
|
||||
}
|
||||
|
||||
public function get(){
|
||||
return $this->payload;
|
||||
}
|
||||
|
||||
public function check($target){
|
||||
$w = true;
|
||||
$b = false;
|
||||
if($this->whitelist !== false){
|
||||
$w = false;
|
||||
if(in_array($target, $this->whitelist, true)){
|
||||
$w = true;
|
||||
}
|
||||
}else{
|
||||
$w = true;
|
||||
}
|
||||
if($this->blacklist !== false){
|
||||
$b = true;
|
||||
if(in_array($target, $this->blacklist, true)){
|
||||
$b = false;
|
||||
}
|
||||
}else{
|
||||
$b = false;
|
||||
}
|
||||
if($w === false or $b === true){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(){
|
||||
return $this->payload;
|
||||
}
|
||||
}
|
@ -28,26 +28,26 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
class Java_String{
|
||||
private $value = "", $count = 0, $hash = 0;
|
||||
|
||||
|
||||
public function __construct($string = false){
|
||||
if($string !== false){
|
||||
$this->value = (string) $string;
|
||||
$this->count = strlen($this->value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function __toString(){
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
|
||||
public function lenght(){
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
|
||||
public function isEmpty(){
|
||||
return $this->count === 0;
|
||||
}
|
||||
|
||||
|
||||
public function charAt($index){
|
||||
$index = (int) $index;
|
||||
if($index < 0 or $index >= $this->count){
|
||||
@ -56,7 +56,7 @@ class Java_String{
|
||||
}
|
||||
return $this->value{$index};
|
||||
}
|
||||
|
||||
|
||||
public function hashCode(){
|
||||
$h = $this->hash;
|
||||
if($h === 0 and $this->count > 0){
|
||||
@ -68,13 +68,13 @@ class Java_String{
|
||||
$this->hash = $h;
|
||||
}
|
||||
return $h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Java_Random{
|
||||
private $haveNextNextGaussian, $nextNextGaussian, $seed, $n1, $n2, $n3, $zero;
|
||||
|
||||
|
||||
public function __construct($seed = false){
|
||||
$this->n1 = new Math_BigInteger(0x5DEECE66D);
|
||||
$this->n2 = new Math_BigInteger(1);
|
||||
@ -86,19 +86,19 @@ class Java_Random{
|
||||
}
|
||||
$this->setSeed($seed);
|
||||
}
|
||||
|
||||
|
||||
public function setSeed($seed){
|
||||
$seed = new Math_BigInteger($seed);
|
||||
$this->seed = $seed->bitwise_xor($this->n1)->bitwise_and($this->n2);
|
||||
$this->haveNextNextGaussian = false;
|
||||
}
|
||||
|
||||
|
||||
protected function next($bits){
|
||||
$bits = (int) $bits;
|
||||
$this->seed = $this->seed->multiply($this->n1)->add($this->n3)->bitwise_and($this->n2);
|
||||
return $this->_tripleRightShift($this->seed, (48 - $bits));
|
||||
}
|
||||
|
||||
|
||||
private function _tripleRightShift($number, $places){
|
||||
if($number->compare($this->zero) >= 0){
|
||||
return $number->bitwise_rightShift($places);
|
||||
@ -106,7 +106,7 @@ class Java_Random{
|
||||
$n1 = new Math_BigInteger(2);
|
||||
return $number->bitwise_rightShift($places)->add($n1->bitwise_leftShift(~$places));
|
||||
}
|
||||
|
||||
|
||||
public function nextBytes($bytes){
|
||||
$bytes = (int) $bytes;
|
||||
$b = b"";
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* Class for reading in NBT-format files.
|
||||
*
|
||||
*
|
||||
* @author Justin Martin <frozenfire@thefrozenfire.com>
|
||||
* @version 1.0
|
||||
* MODIFIED BY @shoghicp
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
class NBT {
|
||||
public $root = array();
|
||||
|
||||
|
||||
const TAG_END = 0;
|
||||
const TAG_BYTE = 1;
|
||||
const TAG_SHORT = 2;
|
||||
@ -24,7 +24,7 @@ class NBT {
|
||||
const TAG_STRING = 8;
|
||||
const TAG_LIST = 9;
|
||||
const TAG_COMPOUND = 10;
|
||||
|
||||
|
||||
public function loadFile($filename) {
|
||||
if(is_file($filename)) {
|
||||
$fp = fopen($filename, "rb");
|
||||
@ -44,7 +44,7 @@ class NBT {
|
||||
$this->traverseTag($fp, $this->root);
|
||||
return end($this->root);
|
||||
}
|
||||
|
||||
|
||||
public function traverseTag($fp, &$tree) {
|
||||
if(feof($fp)) {
|
||||
return false;
|
||||
@ -59,7 +59,7 @@ class NBT {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function readType($fp, $tagType) {
|
||||
switch($tagType) {
|
||||
case self::TAG_BYTE: // Signed byte (8 bit)
|
@ -88,7 +88,7 @@ class Spyc {
|
||||
/**
|
||||
* Setting this to true will force YAMLDump to enclose any string value in
|
||||
* quotes. False by default.
|
||||
*
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $setting_dump_force_quotes = false;
|
||||
@ -168,7 +168,7 @@ class Spyc {
|
||||
/**
|
||||
* Load a string of YAML into a PHP array statically
|
||||
*
|
||||
* The load method, when supplied with a YAML string, will do its best
|
||||
* The load method, when supplied with a YAML string, will do its best
|
||||
* to convert YAML in a string into a PHP array. Pretty simple.
|
||||
*
|
||||
* Note: use this function if you don't want files from the file system
|
||||
@ -257,7 +257,7 @@ class Spyc {
|
||||
|
||||
// Start at the base of the array and move through it.
|
||||
if ($array) {
|
||||
$array = (array)$array;
|
||||
$array = (array)$array;
|
||||
$previous_key = -1;
|
||||
foreach ($array as $key => $value) {
|
||||
if (!isset($first_key)) $first_key = $key;
|
||||
@ -346,7 +346,7 @@ class Spyc {
|
||||
if (is_bool($value)) {
|
||||
$value = ($value) ? "true" : "false";
|
||||
}
|
||||
|
||||
|
||||
if ($value === null) $value = 'null';
|
||||
if ($value === "'" . self::REMPTY . "'") $value = null;
|
||||
|
||||
@ -438,7 +438,7 @@ class Spyc {
|
||||
$cnt = count($Source);
|
||||
for ($i = 0; $i < $cnt; $i++) {
|
||||
$line = $Source[$i];
|
||||
|
||||
|
||||
$this->indent = strlen($line) - strlen(ltrim($line));
|
||||
$tempPath = $this->getParentPathByIndent($this->indent);
|
||||
$line = self::stripIndent($line, $this->indent);
|
||||
@ -530,9 +530,9 @@ class Spyc {
|
||||
return $this->returnArrayElement($line);
|
||||
|
||||
if ($this->isPlainArray($line))
|
||||
return $this->returnPlainArray($line);
|
||||
|
||||
|
||||
return $this->returnPlainArray($line);
|
||||
|
||||
|
||||
return $this->returnKeyValuePair($line);
|
||||
|
||||
}
|
||||
@ -558,7 +558,7 @@ class Spyc {
|
||||
|
||||
if ($is_quoted)
|
||||
return strtr(substr ($value, 1, -1), array ('\\"' => '"', '\'\'' => '\'', '\\\'' => '\''));
|
||||
|
||||
|
||||
if (strpos($value, ' #') !== false && !$is_quoted)
|
||||
$value = preg_replace('/\s+#(.+)$/','',$value);
|
||||
|
||||
@ -585,7 +585,7 @@ class Spyc {
|
||||
$value = $this->_toType($value);
|
||||
return array($key => $value);
|
||||
}
|
||||
|
||||
|
||||
if ($first_character == '{' && $last_character == '}') {
|
||||
$innerValue = trim(substr ($value, 1, -1));
|
||||
if ($innerValue === '') return array();
|
||||
@ -632,7 +632,7 @@ class Spyc {
|
||||
$value = (float)$value;
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
@ -735,7 +735,7 @@ class Spyc {
|
||||
if ($finished) break;
|
||||
|
||||
$i++;
|
||||
if ($i > 10)
|
||||
if ($i > 10)
|
||||
break; // Prevent infinite loops.
|
||||
}
|
||||
|
||||
@ -763,7 +763,7 @@ class Spyc {
|
||||
private function addArrayInline ($array, $indent) {
|
||||
$CommonGroupPath = $this->path;
|
||||
if (empty ($array)) return false;
|
||||
|
||||
|
||||
foreach ($array as $k => $_) {
|
||||
$this->addArray(array($k => $_), $indent);
|
||||
$this->path = $CommonGroupPath;
|
||||
@ -777,7 +777,7 @@ class Spyc {
|
||||
|
||||
if (count ($incoming_data) > 1)
|
||||
return $this->addArrayInline ($incoming_data, $incoming_indent);
|
||||
|
||||
|
||||
$key = key ($incoming_data);
|
||||
$value = isset($incoming_data[$key]) ? $incoming_data[$key] : null;
|
||||
if ($key === '__!YAMLZero') $key = '0';
|
||||
@ -793,7 +793,7 @@ class Spyc {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$history = array();
|
||||
// Unfolding inner array tree.
|
||||
$history[] = $_arr = $this->result;
|
||||
@ -940,7 +940,7 @@ class Spyc {
|
||||
if ($line[0] != '-') return false;
|
||||
if (strlen ($line) > 3)
|
||||
if (substr($line,0,3) == '---') return false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -985,14 +985,14 @@ class Spyc {
|
||||
private function startsMappedValue ($line) {
|
||||
return (substr ($line, -1, 1) == ':');
|
||||
}
|
||||
|
||||
|
||||
private function isPlainArray ($line) {
|
||||
return ($line[0] == '[' && substr ($line, -1, 1) == ']');
|
||||
}
|
||||
|
||||
|
||||
private function returnPlainArray ($line) {
|
||||
return $this->_toType($line);
|
||||
}
|
||||
return $this->_toType($line);
|
||||
}
|
||||
|
||||
private function returnKeyValuePair ($line) {
|
||||
$array = array();
|
||||
@ -1032,7 +1032,7 @@ class Spyc {
|
||||
}
|
||||
|
||||
|
||||
private function nodeContainsGroup ($line) {
|
||||
private function nodeContainsGroup ($line) {
|
||||
$symbolsForReference = 'A-z0-9_\-';
|
||||
if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-)
|
||||
if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1];
|
49
src/classes/utils/TickLoop.php
Normal file
49
src/classes/utils/TickLoop.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?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 TickLoop extends Thread{
|
||||
public $tick, $stop, $lastTic;
|
||||
private $server;
|
||||
public function __construct(PocketMinecraftServer $server){
|
||||
$this->tick = false;
|
||||
$this->lastTick = 0;
|
||||
$this->server = $server;
|
||||
}
|
||||
public function run(){
|
||||
while($this->stop !== true){
|
||||
usleep(1);
|
||||
$time = microtime(true);
|
||||
if($this->lastTick <= ($time - 0.05)){
|
||||
$this->lastTick = $time;
|
||||
$this->tick = true;
|
||||
$this->wait();
|
||||
$this->tick = false;
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
}
|
67
src/classes/utils/UPnP.php
Normal file
67
src/classes/utils/UPnP.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
function UPnP_PortForward($port){
|
||||
if(Utils::$online === false){
|
||||
return false;
|
||||
}
|
||||
if(Utils::getOS() != "win" or !class_exists("COM")){
|
||||
return false;
|
||||
}
|
||||
$port = (int) $port;
|
||||
$myLocalIP = gethostbyname(trim(`hostname`));
|
||||
try{
|
||||
$com = new COM("HNetCfg.NATUPnP");
|
||||
if($com === false or !is_object($com->StaticPortMappingCollection)){
|
||||
return false;
|
||||
}
|
||||
$com->StaticPortMappingCollection->Add($port, "UDP", $port, $myLocalIP, true, "PocketMine-MP");
|
||||
}catch(Exception $e){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function UPnP_RemovePortForward($port){
|
||||
if(Utils::$online === false){
|
||||
return false;
|
||||
}
|
||||
if(Utils::getOS() != "win" or !class_exists("COM")){
|
||||
return false;
|
||||
}
|
||||
$port = (int) $port;
|
||||
try{
|
||||
$com = new COM("HNetCfg.NATUPnP") or false;
|
||||
if($com === false or !is_object($com->StaticPortMappingCollection)){
|
||||
return false;
|
||||
}
|
||||
$com->StaticPortMappingCollection->Remove($port, "UDP");
|
||||
}catch(Exception $e){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -35,8 +35,43 @@ define("BIG_ENDIAN", 0x00);
|
||||
define("LITTLE_ENDIAN", 0x01);
|
||||
define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? BIG_ENDIAN:LITTLE_ENDIAN));
|
||||
|
||||
abstract class Utils{
|
||||
class Utils extends Thread{
|
||||
public static $online = true;
|
||||
public function run(){
|
||||
|
||||
}
|
||||
|
||||
public static function isOnline(){
|
||||
return (checkdnsrr("google.com", "ANY") && checkdnsrr("yahoo.com", "ANY") && checkdnsrr("microsoft.com", "ANY"));
|
||||
}
|
||||
|
||||
public static function getIP(){
|
||||
if(Utils::$online === false){
|
||||
return false;
|
||||
}
|
||||
$ip = "";//trim(Utils::curl_get("http://automation.whatismyip.com/n09230945.asp"));
|
||||
if($ip != ""){
|
||||
return $ip;
|
||||
}else{
|
||||
trim(strip_tags(Utils::curl_get("http://checkip.dyndns.org/")));
|
||||
if(preg_match('#Current IP Address\: ([0-9a-fA-F\:\.]*)#', $ip, $matches) > 0){
|
||||
return $matches[1];
|
||||
}else{
|
||||
$ip = Utils::curl_get("http://www.checkip.org/");
|
||||
if(preg_match('#">([0-9a-fA-F\:\.]*)</span>#', $ip, $matches) > 0){
|
||||
return $matches[1];
|
||||
}else{
|
||||
$ip = Utils::curl_get("http://checkmyip.org/");
|
||||
if(preg_match('#Your IP address is ([0-9a-fA-F\:\.]*)#', $ip, $matches) > 0){
|
||||
return $matches[1];
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getOS(){
|
||||
$uname = strtoupper(php_uname("s"));
|
||||
if(strpos($uname, "WIN") !== false){
|
||||
@ -47,22 +82,22 @@ abstract class Utils{
|
||||
return "linux";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function hexdump($bin){
|
||||
$output = "";
|
||||
$bin = str_split($bin, 16);
|
||||
foreach($bin as $counter => $line){
|
||||
$hex = chunk_split(chunk_split(str_pad(bin2hex($line), 32, " ", STR_PAD_RIGHT), 2, " "), 24, " ");
|
||||
$ascii = preg_replace('#([^\x20-\x7E])#', ".", $line);
|
||||
$output .= str_pad(dechex($counter << 4), 4, "0", STR_PAD_LEFT). " " . $hex . " " . $ascii . PHP_EOL;
|
||||
$output .= str_pad(dechex($counter << 4), 4, "0", STR_PAD_LEFT). " " . $hex . " " . $ascii . PHP_EOL;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
public static function printable($str){
|
||||
return preg_replace('#([^\x20-\x7E])#', '.', $str);
|
||||
}
|
||||
|
||||
|
||||
public static function readTriad($str){
|
||||
list(,$unpacked) = unpack("N", "\x00".$str);
|
||||
return (int) $unpacked;
|
||||
@ -103,18 +138,18 @@ abstract class Utils{
|
||||
$m .= Utils::writeLInt($data["value"][$i]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
$m .= "\x7f";
|
||||
return $m;
|
||||
return $m;
|
||||
}
|
||||
|
||||
|
||||
public static function readMetadata($value, $types = false){
|
||||
$offset = 0;
|
||||
$m = array();
|
||||
$b = ord($value{$offset});
|
||||
++$offset;
|
||||
++$offset;
|
||||
while($b !== 127){
|
||||
$bottom = $b & 0x1F;
|
||||
$type = $b >> 5;
|
||||
@ -157,7 +192,7 @@ abstract class Utils{
|
||||
$offset += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
if($types === true){
|
||||
$m[$bottom] = array($r, $type);
|
||||
@ -167,9 +202,9 @@ abstract class Utils{
|
||||
$b = ord($value{$offset});
|
||||
++$offset;
|
||||
}
|
||||
return $m;
|
||||
return $m;
|
||||
}
|
||||
|
||||
|
||||
public static function readDataArray($str, $len = 10, &$offset = null){
|
||||
$data = array();
|
||||
$offset = 0;
|
||||
@ -181,7 +216,7 @@ abstract class Utils{
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
public static function writeDataArray($data){
|
||||
$raw = "";
|
||||
foreach($data as $v){
|
||||
@ -190,7 +225,7 @@ abstract class Utils{
|
||||
}
|
||||
return $raw;
|
||||
}
|
||||
|
||||
|
||||
public static function getRandomBytes($length = 16, $secure = true, $raw = true, $startEntropy = "", &$rounds = 0, &$drop = 0){
|
||||
$output = b"";
|
||||
$length = abs((int) $length);
|
||||
@ -219,7 +254,6 @@ abstract class Utils{
|
||||
(string) mt_rand(),
|
||||
(string) rand(),
|
||||
function_exists("zend_thread_id") ? ((string) zend_thread_id()):microtime(),
|
||||
var_export(@get_browser(), true),
|
||||
function_exists("sys_getloadavg") ? implode(";", sys_getloadavg()):microtime(),
|
||||
serialize(get_loaded_extensions()),
|
||||
sys_get_temp_dir(),
|
||||
@ -227,7 +261,7 @@ abstract class Utils{
|
||||
(string) disk_total_space("."),
|
||||
uniqid(microtime(),true),
|
||||
);
|
||||
|
||||
|
||||
shuffle($weakEntropy);
|
||||
$value = hash("sha256", implode($weakEntropy), true);
|
||||
foreach($weakEntropy as $k => $c){ //mixing entropy values with XOR and hash randomness extractor
|
||||
@ -237,7 +271,7 @@ abstract class Utils{
|
||||
$value ^= hash("sha256", $c . microtime() . $k, true);
|
||||
}
|
||||
unset($weakEntropy);
|
||||
|
||||
|
||||
if($secure === true){
|
||||
$strongEntropy = array(
|
||||
is_array($startEntropy) ? $startEntropy[($rounds + $drop) % count($startEntropy)]:$startEntropy, //Get a random index of the startEntropy, or just read it
|
||||
@ -275,15 +309,15 @@ abstract class Utils{
|
||||
}
|
||||
return $raw === false ? bin2hex($output):$output;
|
||||
}
|
||||
|
||||
|
||||
public static function round($number){
|
||||
return round($number, 0, PHP_ROUND_HALF_DOWN);
|
||||
}
|
||||
|
||||
|
||||
public static function distance($pos1, $pos2){
|
||||
return sqrt(pow($pos1["x"] - $pos2["x"], 2) + pow($pos1["y"] - $pos2["y"], 2) + pow($pos1["z"] - $pos2["z"], 2));
|
||||
}
|
||||
|
||||
|
||||
public static function angle3D($pos1, $pos2){
|
||||
$X = $pos1["x"] - $pos2["x"];
|
||||
$Z = $pos1["z"] - $pos2["z"];
|
||||
@ -293,20 +327,23 @@ abstract class Utils{
|
||||
$vAngle = rad2deg(-atan2($Y, $dXZ));
|
||||
return array("yaw" => $hAngle, "pitch" => $vAngle);
|
||||
}
|
||||
|
||||
|
||||
public static function sha1($input){
|
||||
$number = new Math_BigInteger(sha1($input, true), -256);
|
||||
$zero = new Math_BigInteger(0);
|
||||
return ($zero->compare($number) <= 0 ? "":"-") . ltrim($number->toHex(), "0");
|
||||
}
|
||||
|
||||
|
||||
public static function microtime(){
|
||||
return microtime(true);
|
||||
}
|
||||
|
||||
|
||||
public static function curl_get($page){
|
||||
if(Utils::$online === false){
|
||||
return false;
|
||||
}
|
||||
$ch = curl_init($page);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array("User-Agent: Minecraft PHP Client 2"));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0 PocketMine-MP"));
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
@ -317,40 +354,43 @@ abstract class Utils{
|
||||
curl_close($ch);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
public static function curl_post($page, $args, $timeout = 10){
|
||||
if(Utils::$online === false){
|
||||
return false;
|
||||
}
|
||||
$ch = curl_init($page);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array("User-Agent: Minecraft PHP Client 2"));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0 PocketMine-MP"));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (int) $timeout);
|
||||
$ret = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
public static function strToHex($str){
|
||||
return bin2hex($str);
|
||||
}
|
||||
|
||||
|
||||
public static function hexToStr($hex){
|
||||
if(HEX2BIN === true){
|
||||
return hex2bin($hex);
|
||||
}
|
||||
}
|
||||
return pack("H*" , $hex);
|
||||
}
|
||||
|
||||
public static function readBool($b){
|
||||
return Utils::readByte($b, false) === 0 ? false:true;
|
||||
}
|
||||
|
||||
|
||||
public static function writeBool($b){
|
||||
return Utils::writeByte($b === true ? 1:0);
|
||||
}
|
||||
|
||||
|
||||
public static function readByte($c, $signed = true){
|
||||
$b = ord($c{0});
|
||||
if($signed === true and ($b & 0x80) === 0x80){ //calculate Two's complement
|
||||
@ -358,7 +398,7 @@ abstract class Utils{
|
||||
}
|
||||
return $b;
|
||||
}
|
||||
|
||||
|
||||
public static function writeByte($c){
|
||||
if($c > 0xff){
|
||||
return false;
|
||||
@ -376,14 +416,14 @@ abstract class Utils{
|
||||
}
|
||||
return $unpacked;
|
||||
}
|
||||
|
||||
|
||||
public static function writeShort($value){
|
||||
if($value < 0){
|
||||
$value += 0x10000;
|
||||
$value += 0x10000;
|
||||
}
|
||||
return pack("n", $value);
|
||||
}
|
||||
|
||||
|
||||
public static function readLShort($str, $signed = true){
|
||||
list(,$unpacked) = unpack("v", $str);
|
||||
if($unpacked > 0x7fff and $signed === true){
|
||||
@ -391,10 +431,10 @@ abstract class Utils{
|
||||
}
|
||||
return $unpacked;
|
||||
}
|
||||
|
||||
|
||||
public static function writeLShort($value){
|
||||
if($value < 0){
|
||||
$value += 0x10000;
|
||||
$value += 0x10000;
|
||||
}
|
||||
return pack("v", $value);
|
||||
}
|
||||
@ -406,14 +446,14 @@ abstract class Utils{
|
||||
}
|
||||
return (int) $unpacked;
|
||||
}
|
||||
|
||||
|
||||
public static function writeInt($value){
|
||||
if($value < 0){
|
||||
$value += 0x100000000;
|
||||
$value += 0x100000000;
|
||||
}
|
||||
return pack("N", $value);
|
||||
}
|
||||
|
||||
|
||||
public static function readLInt($str){
|
||||
list(,$unpacked) = unpack("V", $str);
|
||||
if($unpacked >= 2147483648){
|
||||
@ -421,50 +461,50 @@ abstract class Utils{
|
||||
}
|
||||
return (int) $unpacked;
|
||||
}
|
||||
|
||||
|
||||
public static function writeLInt($value){
|
||||
if($value < 0){
|
||||
$value += 0x100000000;
|
||||
$value += 0x100000000;
|
||||
}
|
||||
return pack("V", $value);
|
||||
}
|
||||
|
||||
|
||||
public static function readFloat($str){
|
||||
list(,$value) = ENDIANNESS === BIG_ENDIAN ? unpack("f", $str):unpack("f", strrev($str));
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
public static function writeFloat($value){
|
||||
return ENDIANNESS === BIG_ENDIAN ? pack("f", $value):strrev(pack("f", $value));
|
||||
}
|
||||
|
||||
|
||||
public static function readLFloat($str){
|
||||
list(,$value) = ENDIANNESS === BIG_ENDIAN ? unpack("f", strrev($str)):unpack("f", $str);
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
public static function writeLFloat($value){
|
||||
return ENDIANNESS === BIG_ENDIAN ? strrev(pack("f", $value)):pack("f", $value);
|
||||
}
|
||||
|
||||
|
||||
public static function printFloat($value){
|
||||
return preg_replace("/(\.\d+?)0+$/", "$1", sprintf("%F", $value));
|
||||
}
|
||||
|
||||
|
||||
public static function readDouble($str){
|
||||
list(,$value) = ENDIANNESS === BIG_ENDIAN ? unpack("d", $str):unpack("d", strrev($str));
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
public static function writeDouble($value){
|
||||
return ENDIANNESS === BIG_ENDIAN ? pack("d", $value):strrev(pack("d", $value));
|
||||
}
|
||||
|
||||
|
||||
public static function readLDouble($str){
|
||||
list(,$value) = ENDIANNESS === BIG_ENDIAN ? unpack("d", strrev($str)):unpack("d", $str);
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
public static function writeLDouble($value){
|
||||
return ENDIANNESS === BIG_ENDIAN ? strrev(pack("d", $value)):pack("d", $value);
|
||||
}
|
||||
@ -473,20 +513,24 @@ abstract class Utils{
|
||||
$long = new Math_BigInteger($str, -256);
|
||||
return $long->toString();
|
||||
}
|
||||
|
||||
|
||||
public static function writeLong($value){
|
||||
$long = new Math_BigInteger($value, -10);
|
||||
return str_pad($long->toBytes(true), 8, "\x00", STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
|
||||
public static function readLLong($str){
|
||||
$long = new Math_BigInteger(strrev($str), -256);
|
||||
return $long->toString();
|
||||
}
|
||||
|
||||
|
||||
public static function writeLLong($value){
|
||||
$long = new Math_BigInteger($value, -10);
|
||||
return strrev(str_pad($long->toBytes(true), 8, "\x00", STR_PAD_LEFT));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(Utils::isOnline() === false){
|
||||
Utils::$online = false;
|
||||
}
|
111
src/classes/utils/VersionString.php
Normal file
111
src/classes/utils/VersionString.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?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 VersionString{
|
||||
public static $stageOrder = array(
|
||||
"alpha" => 0,
|
||||
"a" => 0,
|
||||
"beta" => 1,
|
||||
"b" => 1,
|
||||
"final" => 2,
|
||||
"f" => 2,
|
||||
);
|
||||
private $stage;
|
||||
private $major;
|
||||
private $release;
|
||||
private $minor;
|
||||
private $development = false;
|
||||
public function __construct($version = MAJOR_VERSION){
|
||||
if(is_int($version)){
|
||||
$this->minor = $version & 0x1F;
|
||||
$this->major = ($version >> 5) & 0x0F;
|
||||
$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);
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
public function getNumber(){
|
||||
return (int) (VersionString::$stageOrder[$this->stage] << 13) + ($this->generation << 9) + ($this->major << 5) + $this->minor;
|
||||
}
|
||||
|
||||
public function getStage(){
|
||||
return $this->stage;
|
||||
}
|
||||
|
||||
public function getGeneration(){
|
||||
return $this->generation;
|
||||
}
|
||||
|
||||
public function getMajor(){
|
||||
return $this->major;
|
||||
}
|
||||
|
||||
public function getMinor(){
|
||||
return $this->minor;
|
||||
}
|
||||
|
||||
public function getRelease(){
|
||||
return $this->generation . "." . $this->major . "." . $this->minor;
|
||||
}
|
||||
|
||||
public function isDev(){
|
||||
return $this->development === true;
|
||||
}
|
||||
|
||||
public function get(){
|
||||
return ucfirst($this->stage) . "_" . $this->getRelease() . ($this->development === true ? "dev":"");
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
public function compare($target, $diff = false){
|
||||
if(($target instanceof VersionString) === false){
|
||||
$target = new VersionString($target);
|
||||
}
|
||||
$number = $this->getNumber();
|
||||
$tNumber = $target->getNumber();
|
||||
if($diff === true){
|
||||
return $tNumber - $number;
|
||||
}
|
||||
if($number > $tNumber){
|
||||
return -1; //Target is older
|
||||
}elseif($number < $tNumber){
|
||||
return 1; //Target is newer
|
||||
}else{
|
||||
return 0; //Same version
|
||||
}
|
||||
}
|
||||
}
|
@ -30,11 +30,11 @@ class ChunkParser{
|
||||
var $sectorLength = 4096; //16 * 16 * 16
|
||||
var $chunkLength = 86016; //21 * $sectorLength
|
||||
var $map;
|
||||
|
||||
|
||||
function __construct(){
|
||||
$map = array();
|
||||
}
|
||||
|
||||
|
||||
private function loadLocationTable(){
|
||||
$this->location = array();
|
||||
console("[DEBUG] Loading Chunk Location table...", true, true, 2);
|
||||
@ -57,48 +57,52 @@ class ChunkParser{
|
||||
++$chunkCnt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function loadFile($file){
|
||||
if(ZLIB_EXTENSION === true and file_exists($file.".gz")){
|
||||
$this->raw = gzinflate(file_get_contents($file.".gz"));
|
||||
$r = @gzinflate($this->raw);
|
||||
if($r !== false and $r != ""){
|
||||
$this->raw = $r;
|
||||
}
|
||||
@unlink($file.".gz");
|
||||
file_put_contents($file, $this->raw);
|
||||
}elseif(!file_exists($file)){
|
||||
return false;
|
||||
}else{
|
||||
}else{
|
||||
$this->raw = file_get_contents($file);
|
||||
}
|
||||
$this->file = $file;
|
||||
$this->chunkLength = $this->sectorLength * ord($this->raw{0});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function loadRaw($raw, $file){
|
||||
$this->file = $file;
|
||||
$this->raw = $raw;
|
||||
$this->chunkLength = $this->sectorLength * ord($this->raw{0});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private function getOffsetPosition($X, $Z){
|
||||
$data = substr($this->raw, ($X << 2) + ($Z << 7), 4); //$X * 4 + $Z * 128
|
||||
return array(ord($data{0}), ord($data{1}), ord($data{2}), ord($data{3}));
|
||||
}
|
||||
|
||||
|
||||
private function getOffset($X, $Z, $sectors = 21){
|
||||
return 0x1000 + (($X * $sectors) << 12) + (($Z * $sectors) << 16);
|
||||
}
|
||||
|
||||
|
||||
private function getOffsetLocation($X, $Z){
|
||||
return $X << 2 + $Z << 7;
|
||||
}
|
||||
|
||||
|
||||
public function getChunk($X, $Z){
|
||||
$X = (int) $X;
|
||||
$Z = (int) $Z;
|
||||
return substr($this->raw, $this->getOffset($X, $Z), $this->chunkLength);
|
||||
}
|
||||
|
||||
|
||||
public function writeChunk($X, $Z){
|
||||
$X = (int) $X;
|
||||
$Z = (int) $Z;
|
||||
@ -113,7 +117,7 @@ class ChunkParser{
|
||||
}
|
||||
return Utils::writeLInt(strlen($chunk)).$chunk;
|
||||
}
|
||||
|
||||
|
||||
public function parseChunk($X, $Z){
|
||||
$X = (int) $X;
|
||||
$Z = (int) $Z;
|
||||
@ -135,7 +139,7 @@ class ChunkParser{
|
||||
}
|
||||
return $chunk;
|
||||
}
|
||||
|
||||
|
||||
public function loadMap(){
|
||||
if($this->raw == ""){
|
||||
return false;
|
||||
@ -151,10 +155,10 @@ class ChunkParser{
|
||||
$this->raw = b"";
|
||||
console("[DEBUG] Chunks loaded!", true, true, 2);
|
||||
}
|
||||
|
||||
|
||||
public function saveMap($final = false){
|
||||
console("[DEBUG] Saving chunks...", true, true, 2);
|
||||
|
||||
|
||||
$fp = fopen($this->file, "r+b");
|
||||
flock($fp, LOCK_EX);
|
||||
foreach($this->map as $x => $d){
|
||||
@ -166,13 +170,16 @@ class ChunkParser{
|
||||
flock($fp, LOCK_UN);
|
||||
fclose($fp);
|
||||
if(ZLIB_EXTENSION === true){
|
||||
file_put_contents($this->file .".gz", gzdeflate(file_get_contents($this->file), 9));
|
||||
$original = filesize($this->file);
|
||||
file_put_contents($this->file .".gz", gzdeflate(gzdeflate(file_get_contents($this->file),9),9)); //Double compression for flat maps
|
||||
$compressed = filesize($this->file .".gz");
|
||||
console("[DEBUG] Saved chunks.dat.gz with ".round(($compressed/$original)*100, 2)."% (".round($compressed/1024, 2)."KB) of the original size", true, true, 2);
|
||||
if($final === true){
|
||||
@unlink($this->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getFloor($x, $z){
|
||||
$X = $x >> 4;
|
||||
$Z = $z >> 4;
|
||||
@ -186,7 +193,7 @@ class ChunkParser{
|
||||
}
|
||||
return $y;
|
||||
}
|
||||
|
||||
|
||||
public function getBlock($x, $y, $z){
|
||||
$x = (int) $x;
|
||||
$y = (int) $y;
|
||||
@ -205,12 +212,12 @@ class ChunkParser{
|
||||
}
|
||||
return array($block, $meta);
|
||||
}
|
||||
|
||||
|
||||
public function getChunkColumn($X, $Z, $x, $z, $type = 0){
|
||||
$index = $z + ($x << 4);
|
||||
return $this->map[$X][$Z][$type][$index];
|
||||
}
|
||||
|
||||
|
||||
public function setBlock($x, $y, $z, $block, $meta = 0){
|
||||
$x = (int) $x;
|
||||
$y = (int) $y;
|
@ -2,20 +2,20 @@
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ PocketMine \
|
||||
/ MP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
/ 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
|
||||
@ -33,8 +33,8 @@ define("ENTITY_ITEM", 3);
|
||||
define("ENTITY_PAINTING", 4);
|
||||
|
||||
class Entity extends stdClass{
|
||||
var $eid, $type, $name, $x, $y, $z, $yaw, $pitch, $dead, $data, $class, $attach, $metadata, $closed, $player, $onTick;
|
||||
private $ev, $server;
|
||||
var $invincible = false, $eid, $type, $name, $x, $y, $z, $speedX, $speedY, $speedZ, $speed, $last = array(0, 0, 0, 0), $yaw, $pitch, $dead, $data, $class, $attach, $metadata, $closed, $player, $onTick;
|
||||
private $server;
|
||||
function __construct($server, $eid, $class, $type = 0, $data = array()){
|
||||
$this->server = $server;
|
||||
$this->eid = (int) $eid;
|
||||
@ -49,11 +49,15 @@ class Entity extends stdClass{
|
||||
$this->closed = false;
|
||||
$this->name = "";
|
||||
$this->server->query("INSERT OR REPLACE INTO entities (EID, type, class, health) VALUES (".$this->eid.", ".$this->type.", ".$this->class.", ".$this->health.");");
|
||||
$this->server->schedule(20, array($this, "update"), array(), true);
|
||||
$this->server->schedule(4, array($this, "update"), array(), true);
|
||||
$this->metadata = array();
|
||||
$this->x = isset($this->data["x"]) ? $this->data["x"]:0;
|
||||
$this->y = isset($this->data["y"]) ? $this->data["y"]:0;
|
||||
$this->z = isset($this->data["z"]) ? $this->data["z"]:0;
|
||||
$this->speedX = isset($this->data["speedX"]) ? $this->data["speedX"]:0;
|
||||
$this->speedY = isset($this->data["speedY"]) ? $this->data["speedY"]:0;
|
||||
$this->speedZ = isset($this->data["speedZ"]) ? $this->data["speedZ"]:0;
|
||||
$this->speed = 0;
|
||||
$this->yaw = isset($this->data["yaw"]) ? $this->data["yaw"]:0;
|
||||
$this->pitch = isset($this->data["pitch"]) ? $this->data["pitch"]:0;
|
||||
$this->position = array("x" => &$this->x, "y" => &$this->y, "z" => &$this->z, "yaw" => &$this->yaw, "pitch" => &$this->pitch);
|
||||
@ -74,21 +78,26 @@ class Entity extends stdClass{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function update(){
|
||||
if($this->class === ENTITY_ITEM){
|
||||
$this->calculateVelocity();
|
||||
$this->server->api->dhandle("entity.move", $this);
|
||||
if($this->class === ENTITY_ITEM and $this->closed === false and $this->server->gamemode === 0){
|
||||
$player = $this->server->query("SELECT EID FROM entities WHERE class == ".ENTITY_PLAYER." AND abs(x - {$this->x}) <= 1.5 AND abs(y - {$this->y}) <= 1.5 AND abs(z - {$this->z}) <= 1.5 LIMIT 1;", true);
|
||||
if($player !== true and $player !== false){
|
||||
if($this->server->api->dhandle("player.item.pick", array(
|
||||
if($this->server->api->dhandle("player.pickup", array(
|
||||
"eid" => $player["EID"],
|
||||
"entity" => $this,
|
||||
"block" => $this->type,
|
||||
"meta" => $this->meta,
|
||||
"target" => $this->eid
|
||||
)) !== false){
|
||||
$this->close();
|
||||
$this->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getDirection(){
|
||||
$rotation = ($this->yaw - 90) % 360;
|
||||
if ($rotation < 0) {
|
||||
@ -108,7 +117,7 @@ class Entity extends stdClass{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function spawn($player){
|
||||
if(!is_object($player)){
|
||||
$player = $this->server->api->player->get($player);
|
||||
@ -142,7 +151,7 @@ class Entity extends stdClass{
|
||||
"meta" => $this->meta,
|
||||
"stack" => $this->stack,
|
||||
));
|
||||
break;
|
||||
break;
|
||||
case ENTITY_MOB:
|
||||
$player->dataPacket(MC_ADD_MOB, array(
|
||||
"type" => $this->type,
|
||||
@ -157,32 +166,31 @@ class Entity extends stdClass{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function close(){
|
||||
if($this->closed === false){
|
||||
$this->server->query("DELETE FROM entities WHERE EID = ".$this->eid.";");
|
||||
$this->server->api->dhandle("entity.remove", $this->eid);
|
||||
$this->server->api->entity->remove($this->eid);
|
||||
$this->closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function __destruct(){
|
||||
$this->close();
|
||||
}
|
||||
|
||||
|
||||
public function getEID(){
|
||||
return $this->eid;
|
||||
}
|
||||
|
||||
|
||||
public function getName(){
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
public function setName($name){
|
||||
$this->name = $name;
|
||||
$this->server->query("UPDATE entities SET name = '".str_replace("'", "", $this->name)."' WHERE EID = ".$this->eid.";");
|
||||
}
|
||||
|
||||
|
||||
public function look($pos2){
|
||||
$pos = $this->getPosition();
|
||||
$angle = Utils::angle3D($pos2, $pos);
|
||||
@ -190,14 +198,14 @@ class Entity extends stdClass{
|
||||
$this->pitch = $angle["pitch"];
|
||||
$this->server->query("UPDATE entities SET pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
|
||||
}
|
||||
|
||||
|
||||
public function setCoords($x, $y, $z){
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
$this->z = $z;
|
||||
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z." WHERE EID = ".$this->eid.";");
|
||||
}
|
||||
|
||||
|
||||
public function move($x, $y, $z, $yaw = 0, $pitch = 0){
|
||||
$this->x += $x;
|
||||
$this->y += $y;
|
||||
@ -208,22 +216,47 @@ class Entity extends stdClass{
|
||||
$this->pitch %= 90;
|
||||
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z.", pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
|
||||
}
|
||||
|
||||
|
||||
public function setPosition($x, $y, $z, $yaw, $pitch){
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
$this->z = $z;
|
||||
$this->yaw = $yaw;
|
||||
$this->pitch = $pitch;
|
||||
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z.", pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
|
||||
return true;
|
||||
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z.", pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
|
||||
}
|
||||
|
||||
public function inBlock($x, $y, $z){
|
||||
$block = new Vector3($x + 0.5, $y, $z + 0.5);
|
||||
$me = new Vector3($this->x, $this->y, $this->z);
|
||||
if(($y == ((int) $this->y) or $y == (((int) $this->y) + 1)) and $block->maxPlainDistance($me) < 0.8){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function calculateVelocity(){
|
||||
$diffTime = microtime(true) - $this->last[3];
|
||||
$this->last[3] = microtime(true);
|
||||
$origin = new Vector3($this->last[0], $this->last[1], $this->last[2]);
|
||||
$final = new Vector3($this->x, $this->y, $this->z);
|
||||
$speedX = abs($this->x - $this->last[0]) / $diffTime;
|
||||
$this->last[0] = $this->x;
|
||||
$speedY = ($this->y - $this->last[1]) / $diffTime;
|
||||
$this->last[1] = $this->y;
|
||||
$speedZ = abs($this->z - $this->last[2]) / $diffTime;
|
||||
$this->last[2] = $this->z;
|
||||
$this->speedX = $speedX;
|
||||
$this->speedY = $speedY;
|
||||
$this->speedZ = $speedZ;
|
||||
$this->speed = $origin->distance($final) / $diffTime;
|
||||
}
|
||||
|
||||
public function getPosition($round = false){
|
||||
return !isset($this->position) ? false:($round === true ? array_map("floor", $this->position):$this->position);
|
||||
}
|
||||
|
||||
public function setHealth($health, $cause = ""){
|
||||
|
||||
public function setHealth($health, $cause = ""){
|
||||
$this->health = (int) $health;
|
||||
$this->server->query("UPDATE entities SET health = ".$this->health." WHERE EID = ".$this->eid.";");
|
||||
$this->server->api->dhandle("entity.health.change", array("eid" => $this->eid, "health" => $health, "cause" => $cause));
|
||||
@ -241,7 +274,7 @@ class Entity extends stdClass{
|
||||
$this->dead = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getHealth(){
|
||||
return $this->health;
|
||||
}
|
36
src/classes/world/TileEntity.php
Normal file
36
src/classes/world/TileEntity.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?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 TileEntity extends stdClass{
|
||||
private $server;
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -33,15 +33,15 @@ class WorldGenerator{
|
||||
$this->genName = $genName;
|
||||
$this->gen = new $genName($this->seed);
|
||||
}
|
||||
|
||||
|
||||
public function getSpawn(){
|
||||
return $this->gen->getSpawn();
|
||||
}
|
||||
|
||||
|
||||
public function set($name, $value){
|
||||
$this->gen->set($name, $value);
|
||||
}
|
||||
|
||||
|
||||
public function init(){
|
||||
$this->raw = "\x15\x01\x00\x00\x15\x16\x00\x00\x15\x2b\x00\x00\x15\x40\x00\x00". //Location Header
|
||||
"\x15\x55\x00\x00\x15\x6a\x00\x00\x15\x7f\x00\x00\x15\x94\x00\x00".
|
||||
@ -301,18 +301,18 @@ class WorldGenerator{
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
$this->gen->init();
|
||||
}
|
||||
|
||||
|
||||
public function generate(){
|
||||
for($Z = 0; $Z < 16; ++$Z){
|
||||
for($X = 0; $X < 16; ++$X){
|
||||
$chunk = str_pad($this->getChunk($X, $Z), 86012, "\x00", STR_PAD_RIGHT);
|
||||
$this->raw .= Utils::writeLInt(strlen($chunk)) . $chunk;
|
||||
$this->raw .= Utils::writeLInt(strlen($chunk)) . $chunk;
|
||||
}
|
||||
console("[DEBUG] Generating level ".ceil(($Z + 1)/0.16)."%", true, true, 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private function getChunk($X, $Z){
|
||||
$chunk = b"";
|
||||
$columns = array();
|
||||
@ -333,7 +333,7 @@ class WorldGenerator{
|
||||
unset($columns);
|
||||
return $chunk;
|
||||
}
|
||||
|
||||
|
||||
public function save($dir, $name){
|
||||
@mkdir($dir, 0777, true);
|
||||
file_put_contents($dir."chunks.dat", $this->raw);
|
@ -33,19 +33,19 @@ class NormalGenerator{
|
||||
"seed" => (int) $seed,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function set($name, $value){
|
||||
$this->config[$name] = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->spawn = array(128, 128, 128);
|
||||
}
|
||||
|
||||
|
||||
public function getSpawn(){
|
||||
return $this->spawn;
|
||||
}
|
||||
|
||||
|
||||
public function getColumn($x, $z){
|
||||
$x = (int) $x;
|
||||
$z = (int) $z;
|
@ -38,14 +38,14 @@ class SuperflatGenerator{
|
||||
);
|
||||
$this->parsePreset();
|
||||
}
|
||||
|
||||
|
||||
public function set($name, $value){
|
||||
$this->config[$name] = $value;
|
||||
if($name === "preset"){
|
||||
$this->parsePreset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function parsePreset(){
|
||||
$this->structure = array(
|
||||
0 => "",
|
||||
@ -53,7 +53,7 @@ class SuperflatGenerator{
|
||||
2 => str_repeat("\x00", 64),
|
||||
3 => str_repeat("\x00", 64),
|
||||
);
|
||||
$preset = explode(";", trim($this->config["preset"]));
|
||||
$preset = explode(";", trim($this->config["preset"]));
|
||||
foreach($preset as $i => $data){
|
||||
$num = 1;
|
||||
if(preg_match('#([a-zA-Z\-_]*)\((.*)\)#', $data, $matches) > 0){ //Property
|
||||
@ -78,15 +78,15 @@ class SuperflatGenerator{
|
||||
$this->structure[2] = substr($this->structure[2], 0, 64);
|
||||
$this->structure[3] = substr($this->structure[3], 0, 64);
|
||||
}
|
||||
|
||||
|
||||
public function init(){
|
||||
$this->spawn = array(128, strlen($this->structure[0]), 128);
|
||||
}
|
||||
|
||||
|
||||
public function getSpawn(){
|
||||
return $this->spawn;
|
||||
}
|
||||
|
||||
|
||||
public function getColumn($x, $z){
|
||||
$x = (int) $x;
|
||||
$z = (int) $z;
|
@ -26,7 +26,7 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
|
||||
require_once("misc/world/generator/object/tree/TreeObject.php");
|
||||
require_once("classes/world/generator/object/tree/TreeObject.php");
|
||||
|
||||
class BigTreeObject extends TreeObject{
|
||||
private $trunkHeightMultiplier = 0.618;
|
||||
@ -35,20 +35,20 @@ class BigTreeObject extends TreeObject{
|
||||
private $leafDistanceLimit = 5;
|
||||
private $widthScale = 1;
|
||||
private $branchSlope = 0.381;
|
||||
|
||||
|
||||
private $totalHeight = 6;
|
||||
private $leavesHeight = 3;
|
||||
protected $radiusIncrease = 0;
|
||||
private $addLeavesVines = false;
|
||||
private $addLogVines = false;
|
||||
private $addCocoaPlants = false;
|
||||
|
||||
private $addCocoaPlants = false;
|
||||
|
||||
public function canPlaceObject(LevelAPI $level, $x, $y, $z){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function placeObject(LevelAPI $level, $x, $y, $z, $type){
|
||||
|
||||
|
||||
$this->trunkHeight = (int) ($this->totalHeight * $this->trunkHeightMultiplier);
|
||||
$leaves = $this->getLeafGroupPoints($level, $x, $y, $z);
|
||||
foreach($leaves as $leafGroup){
|
||||
@ -64,7 +64,7 @@ class BigTreeObject extends TreeObject{
|
||||
trunk.next().setMaterial(VanillaMaterials.LOG, logMetadata);
|
||||
}
|
||||
generateBranches(w, x, y, z, leaves);
|
||||
|
||||
|
||||
$level->setBlock($x, $y - 1, $z, 3, 0);
|
||||
$this->totalHeight += mt_rand(-1, 3);
|
||||
$this->leavesHeight += mt_rand(0, 1);
|
@ -26,18 +26,18 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
|
||||
require_once("misc/world/generator/object/tree/TreeObject.php");
|
||||
require_once("classes/world/generator/object/tree/TreeObject.php");
|
||||
|
||||
class PineTreeObject extends TreeObject{
|
||||
var $type = 1;
|
||||
private $totalHeight = 8;
|
||||
private $leavesSizeY = -1;
|
||||
private $leavesAbsoluteMaxRadius = -1;
|
||||
|
||||
|
||||
public function canPlaceObject(LevelAPI $level, $x, $y, $z){
|
||||
$this->findRandomLeavesSize();
|
||||
$checkRadius = 0;
|
||||
for($yy = 0; $yy < ($this->totalHeight + 2); ++$yy) {
|
||||
for($yy = 0; $yy < $this->totalHeight; ++$yy) {
|
||||
if($yy === $this->leavesSizeY) {
|
||||
$checkRadius = $this->leavesAbsoluteMaxRadius;
|
||||
}
|
||||
@ -52,13 +52,13 @@ class PineTreeObject extends TreeObject{
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private function findRandomLeavesSize(){
|
||||
$this->totalHeight += mt_rand(-1, 2);
|
||||
$this->leavesSizeY = 1 + mt_rand(0,2);
|
||||
$this->leavesAbsoluteMaxRadius = 2 + mt_rand(0, 2);
|
||||
}
|
||||
|
||||
|
||||
public function placeObject(LevelAPI $level, $x, $y, $z){
|
||||
if($this->leavesSizeY === -1 or $this->leavesAbsoluteMaxRadius === -1) {
|
||||
$this->findRandomLeavesSize();
|
||||
@ -90,7 +90,7 @@ class PineTreeObject extends TreeObject{
|
||||
$trunkHeightReducer = mt_rand(0,3);
|
||||
for($yy = 0; $yy < ($this->totalHeight - $trunkHeightReducer); ++$yy){
|
||||
$level->setBlock($x, $y + $yy, $z, 17, $this->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
|
||||
require_once("misc/world/generator/object/tree/TreeObject.php");
|
||||
require_once("classes/world/generator/object/tree/TreeObject.php");
|
||||
|
||||
class SmallTreeObject extends TreeObject{
|
||||
var $type = 0;
|
||||
@ -35,8 +35,8 @@ class SmallTreeObject extends TreeObject{
|
||||
protected $radiusIncrease = 0;
|
||||
private $addLeavesVines = false;
|
||||
private $addLogVines = false;
|
||||
private $addCocoaPlants = false;
|
||||
|
||||
private $addCocoaPlants = false;
|
||||
|
||||
public function canPlaceObject(LevelAPI $level, $x, $y, $z){
|
||||
$radiusToCheck = $this->radiusIncrease;
|
||||
for ($yy = 0; $yy < $this->totalHeight + 2; ++$yy) {
|
||||
@ -54,7 +54,7 @@ class SmallTreeObject extends TreeObject{
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function placeObject(LevelAPI $level, $x, $y, $z){
|
||||
$level->setBlock($x, $y - 1, $z, 3, 0);
|
||||
$this->totalHeight += mt_rand(-1, 3);
|
||||
@ -72,7 +72,7 @@ class SmallTreeObject extends TreeObject{
|
||||
}
|
||||
for($yy = 0; $yy < ($this->totalHeight - 1); ++$yy){
|
||||
$level->setBlock($x, $y + $yy, $z, 17, $this->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,14 +26,14 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
|
||||
require_once("misc/world/generator/object/tree/TreeObject.php");
|
||||
require_once("classes/world/generator/object/tree/TreeObject.php");
|
||||
|
||||
class SpruceTreeObject extends TreeObject{
|
||||
var $type = 1;
|
||||
private $totalHeight = 8;
|
||||
private $leavesBottomY = -1;
|
||||
private $leavesMaxRadius = -1;
|
||||
|
||||
|
||||
public function canPlaceObject(LevelAPI $level, $x, $y, $z){
|
||||
$this->findRandomLeavesSize();
|
||||
$checkRadius = 0;
|
||||
@ -52,13 +52,13 @@ class SpruceTreeObject extends TreeObject{
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private function findRandomLeavesSize(){
|
||||
$this->totalHeight += mt_rand(-1, 2);
|
||||
$this->leavesBottomY = (int) ($this->totalHeight - mt_rand(1,2) - 3);
|
||||
$this->leavesMaxRadius = 1 + mt_rand(0, 1);
|
||||
}
|
||||
|
||||
|
||||
public function placeObject(LevelAPI $level, $x, $y, $z){
|
||||
if($this->leavesBottomY === -1 or $this->leavesMaxRadius === -1) {
|
||||
$this->findRandomLeavesSize();
|
||||
@ -81,7 +81,7 @@ class SpruceTreeObject extends TreeObject{
|
||||
}
|
||||
for($yy = 0; $yy < ($this->totalHeight - 1); ++$yy){
|
||||
$level->setBlock($x, $y + $yy, $z, 17, $this->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,12 +31,12 @@ class TreeObject{
|
||||
0 => true,
|
||||
6 => true,
|
||||
17 => true,
|
||||
18 => true,
|
||||
18 => true,
|
||||
);
|
||||
public static function growTree(LevelAPI $level, $block, $type){
|
||||
switch($type){
|
||||
case Sapling::SPRUCE:
|
||||
if(mt_rand(0,1) == 2){
|
||||
if(mt_rand(0,1) == 1){
|
||||
$tree = new SpruceTreeObject();
|
||||
}else{
|
||||
$tree = new PineTreeObject();
|
@ -35,9 +35,9 @@ ini_set('default_charset', 'utf-8');
|
||||
define("FILE_PATH", dirname(__FILE__)."/../../");
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . FILE_PATH . PATH_SEPARATOR . FILE_PATH . "/src/" . PATH_SEPARATOR . FILE_PATH . "/src/classes/");
|
||||
ini_set("memory_limit", "256M");
|
||||
define("CURRENT_PROTOCOL", 5);
|
||||
define("CURRENT_VERSION", 1);
|
||||
define("LOG", true);
|
||||
define("MAGIC", "\x00\xff\xff\x00\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\x12\x34\x56\x78");
|
||||
define("TEST_MD5", "5ca8eced50a5801619f7ae86d631a4e7");
|
||||
define("MAJOR_VERSION", "Alpha_1.0.3");
|
||||
define("TEST_MD5", "d0ca3786e53b615bb4fb9f5094d5c9a7");
|
||||
define("MAJOR_VERSION", "Alpha_1.0.7");
|
||||
define("CURRENT_PROTOCOL", 5);
|
||||
define("CURRENT_MINECRAFT_VERSION", "v0.5.0 alpha");
|
@ -1,20 +0,0 @@
|
||||
#PocketMine-MP default server properties
|
||||
server-name=A Minecraft Server
|
||||
description=Server made using PocketMine-MP
|
||||
motd=Welcome @username to this server!
|
||||
invisible=false
|
||||
port=19132
|
||||
memory-limit=512M
|
||||
last-update=false
|
||||
update-channel=stable
|
||||
white-list=false
|
||||
debug=2
|
||||
max-players=20
|
||||
server-type=normal
|
||||
time-per-second=20
|
||||
gamemode=1
|
||||
difficulty=1
|
||||
generator=
|
||||
generator-settings=
|
||||
level-name=false
|
||||
server-id=false
|
@ -27,7 +27,12 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
require_once(dirname(__FILE__)."/config.php");
|
||||
require_once("common/functions.php");
|
||||
//set_error_handler("error_handler");
|
||||
if(strpos(strtoupper(php_uname("s")), "WIN") === false or arg("enable-ansi", false) === true){
|
||||
define("ENABLE_ANSI", true);
|
||||
}else{
|
||||
define("ENABLE_ANSI", false);
|
||||
}
|
||||
set_error_handler("fatal_handler", E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_DEPRECATED);
|
||||
|
||||
$errors = 0;
|
||||
|
||||
@ -57,7 +62,7 @@ if(!extension_loaded("sockets") and @dl((PHP_SHLIB_SUFFIX === "dll" ? "php_":"")
|
||||
}
|
||||
|
||||
if(!extension_loaded("pthreads") and @dl((PHP_SHLIB_SUFFIX === "dll" ? "php_":"") . "pthreads." . PHP_SHLIB_SUFFIX) === false){
|
||||
console("[ERROR] Unable to find pthreads extension. [https://github.com/krakjoe/pthreads]", true, true, 0);
|
||||
console("[ERROR] Unable to find pthreads extension. Use the Installer available in the Homepage", true, true, 0);
|
||||
++$errors;
|
||||
}
|
||||
|
||||
@ -82,23 +87,6 @@ if($errors > 0){
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
require_once("classes/Async.class.php");
|
||||
require_once("classes/Data.class.php");
|
||||
require_once("classes/Player.class.php");
|
||||
require_once("classes/Generator.class.php");
|
||||
require_once("classes/SuperflatGenerator.class.php");
|
||||
require_once("classes/Utils.class.php");
|
||||
require_once("classes/UDPSocket.class.php");
|
||||
require_once("classes/Packet.class.php");
|
||||
require_once("classes/Entity.class.php");
|
||||
require_once("classes/ChunkParser.class.php");
|
||||
require_once("classes/NBT.class.php");
|
||||
require_once("classes/Java.class.php");
|
||||
require_once("classes/SerializedPacketHandler.class.php");
|
||||
require_once("classes/CustomPacketHandler.class.php");
|
||||
require_once("classes/MinecraftInterface.class.php");
|
||||
require_once("classes/BigInteger.class.php");
|
||||
require_all(FILE_PATH . "src/misc/");
|
||||
require_all(FILE_PATH . "src/classes/");
|
||||
|
||||
?>
|
@ -25,6 +25,8 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function kill($pid){
|
||||
switch(Utils::getOS()){
|
||||
case "win":
|
||||
@ -105,12 +107,12 @@ function parseNBTData($data){
|
||||
}
|
||||
|
||||
|
||||
function arg($name, $default){
|
||||
function arg($name, $default = false){
|
||||
global $arguments, $argv;
|
||||
if(!isset($arguments)){
|
||||
$arguments = arguments($argv);
|
||||
}
|
||||
|
||||
|
||||
if(isset($arguments["commands"][$name])){
|
||||
return $arguments["commands"][$name];
|
||||
}else{
|
||||
@ -125,7 +127,7 @@ function arguments ( $args ){
|
||||
array_shift( $args );
|
||||
$args = join( $args, ' ' );
|
||||
|
||||
preg_match_all('/ (--\w+ (?:[= ] [^-]+ [^\s-] )? ) | (-\w+) | (\w+) /x', $args, $match );
|
||||
preg_match_all('/ (--[\w\-]+ (?:[= ] [^-]+ [^\s-] )? ) | (-\w+) | (\w+) /x', $args, $match );
|
||||
$args = array_shift( $match );
|
||||
|
||||
$ret = array(
|
||||
@ -163,19 +165,52 @@ function arguments ( $args ){
|
||||
}
|
||||
|
||||
function console($message, $EOL = true, $log = true, $level = 1){
|
||||
//global $path;
|
||||
if(!defined("DEBUG") or DEBUG >= $level){
|
||||
$message .= $EOL === true ? PHP_EOL:"";
|
||||
$message = date("H:i:s"). " ". $message;
|
||||
$time = (ENABLE_ANSI === true ? "\x1b[36m".date("H:i:s")."\x1b[0m":date("H:i:s")) . " ";
|
||||
$replaced = preg_replace('/\x1b\[[0-9;]*m/', "", $time . $message);
|
||||
if($log === true and (!defined("LOG") or LOG === true)){
|
||||
logg($message, "console", false, $level);
|
||||
}
|
||||
logg($replaced, "console", false, $level);
|
||||
}
|
||||
if(ENABLE_ANSI === true){
|
||||
if(preg_match("/\[([a-zA-Z0-9]*)\]/", $message, $matches) > 0){
|
||||
$add = "\x1b";
|
||||
switch($matches[1]){
|
||||
case "ERROR":
|
||||
$add .= "[31;1m";
|
||||
break;
|
||||
case "INTERNAL":
|
||||
case "DEBUG":
|
||||
$add .= "[30;1m";
|
||||
break;
|
||||
case "WARNING":
|
||||
$add .= "[33;1m";
|
||||
break;
|
||||
case "NOTICE":
|
||||
$add .= "[37;1m";
|
||||
break;
|
||||
default:
|
||||
$add = "";
|
||||
break;
|
||||
}
|
||||
$message = $time . $add . $message . "\x1b[0m";
|
||||
}
|
||||
}else{
|
||||
$message = $replaced;
|
||||
}
|
||||
echo $message;
|
||||
}
|
||||
}
|
||||
|
||||
function error_handler($errno, $errstr, $errfile, $errline){
|
||||
function fatal_handler($errno, $errstr, $errfile, $errline){
|
||||
global $lasttrace;
|
||||
console("[ERROR] A level ".$errno." error happened: \"$errstr\" in \"$errfile\" at line $errline", true, true, 0);
|
||||
ob_start();
|
||||
debug_print_backtrace();
|
||||
$lasttrace = ob_get_contents();
|
||||
ob_end_clean();
|
||||
console("[ERROR] [Backtrace] $lasttrace", true, true, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
function logg($message, $name, $EOL = true, $level = 2, $close = false){
|
||||
|
@ -30,20 +30,20 @@ $pstruct = array(
|
||||
"long", //Ping ID
|
||||
"magic",
|
||||
),
|
||||
|
||||
|
||||
0x05 => array(
|
||||
"magic",
|
||||
"byte", //Protocol Version
|
||||
"special1", //MTU Size Null Lenght
|
||||
),
|
||||
|
||||
|
||||
0x06 => array(
|
||||
"magic",
|
||||
"long", //Server GUID
|
||||
"byte", //Server Security
|
||||
"short", //MTU Size
|
||||
),
|
||||
|
||||
|
||||
0x07 => array(
|
||||
"magic",
|
||||
5, //Security Cookie (idk why it's sent here)
|
||||
@ -51,7 +51,7 @@ $pstruct = array(
|
||||
"short", //MTU Size
|
||||
"long", //Client GUID
|
||||
),
|
||||
|
||||
|
||||
0x08 => array(
|
||||
"magic",
|
||||
"long", //Server GUID
|
||||
@ -59,20 +59,20 @@ $pstruct = array(
|
||||
"short", //MTU Size
|
||||
"byte", //Security
|
||||
),
|
||||
|
||||
|
||||
0x1a => array(
|
||||
"byte", //Server Version
|
||||
"magic",
|
||||
"long", //Server GUID
|
||||
),
|
||||
|
||||
|
||||
0x1c => array(
|
||||
"long", //Ping ID
|
||||
"long", //Server GUID
|
||||
"magic",
|
||||
"string", //Data
|
||||
),
|
||||
|
||||
|
||||
0x1d => array(
|
||||
"long", //Ping ID
|
||||
"long", //Server GUID
|
||||
@ -85,50 +85,50 @@ $pstruct = array(
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
|
||||
|
||||
0x81 => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x82 => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x83 => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x84 => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x85 => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x86 => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x87 => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x88 => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
@ -140,52 +140,52 @@ $pstruct = array(
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x8a => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x8b => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x8c => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x8d => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x8e => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
0x8f => array(
|
||||
"itriad",
|
||||
"ubyte",
|
||||
"customData",
|
||||
),
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
0xa0 => array(
|
||||
"short",
|
||||
"bool",
|
||||
"itriad",
|
||||
"special1",
|
||||
),
|
||||
|
||||
|
||||
0xc0 => array(
|
||||
"short",
|
||||
"bool",
|
@ -28,8 +28,6 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
//Protocol Version: 5
|
||||
|
||||
|
||||
define("MC_KEEP_ALIVE", 0x00);
|
||||
|
||||
define("MC_KEEP_ALIVE", 0x00);
|
||||
|
||||
define("MC_CLIENT_CONNECT", 0x09);
|
||||
@ -62,6 +60,8 @@ define("MC_PLACE_BLOCK", 0x95);
|
||||
define("MC_REMOVE_BLOCK", 0x96);
|
||||
define("MC_UPDATE_BLOCK", 0x97);
|
||||
|
||||
define("MC_EXPLOSION", 0x99);
|
||||
|
||||
define("MC_REQUEST_CHUNK", 0x9d);
|
||||
define("MC_CHUNK_DATA", 0x9e);
|
||||
|
||||
@ -77,6 +77,11 @@ define("MC_SET_SPAWN_POSITION", 0xa6);
|
||||
define("MC_ANIMATE", 0xa7);
|
||||
define("MC_RESPAWN", 0xa8);
|
||||
|
||||
define("MC_DROP_ITEM", 0xaa);
|
||||
define("MC_CONTAINER_OPEN", 0xab);
|
||||
define("MC_CONTAINER_CLOSE", 0xac);
|
||||
define("MC_CONTAINER_SET_SLOT", 0xad);
|
||||
|
||||
define("MC_CLIENT_MESSAGE", 0xb1);
|
||||
define("MC_SIGN_UPDATE", 0xb2);
|
||||
define("MC_ADVENTURE_SETTINGS", 0xb3);
|
@ -27,44 +27,46 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
$dataName = array(
|
||||
MC_KEEP_ALIVE => "KeepAlive",
|
||||
|
||||
|
||||
MC_CLIENT_CONNECT => "ClientConnect",
|
||||
MC_SERVER_HANDSHAKE => "ServerHandshake",
|
||||
|
||||
|
||||
MC_CLIENT_HANDSHAKE => "ClientHandshake",
|
||||
|
||||
|
||||
MC_DISCONNECT => "Disconnect",
|
||||
|
||||
|
||||
0x18 => "Unknown",
|
||||
|
||||
|
||||
MC_LOGIN => "Login",
|
||||
MC_LOGIN_STATUS => "LoginStatus",
|
||||
MC_READY => "Ready",
|
||||
MC_CHAT => "Chat",
|
||||
MC_SET_TIME => "SetTime",
|
||||
MC_START_GAME => "StartGame",
|
||||
|
||||
|
||||
MC_ADD_MOB => "AddMob",
|
||||
MC_ADD_PLAYER => "AddPlayer",
|
||||
|
||||
|
||||
MC_ADD_ENTITY => "AddEntity",
|
||||
MC_REMOVE_ENTITY => "RemoveEntity",
|
||||
MC_ADD_ITEM_ENTITY => "AddItemEntity",
|
||||
MC_TAKE_ITEM_ENTITY => "TakeItemEntity",
|
||||
|
||||
|
||||
MC_MOVE_ENTITY => "MoveEntity",
|
||||
|
||||
|
||||
MC_MOVE_ENTITY_POSROT => "MoveEntity_PosRot",
|
||||
MC_MOVE_PLAYER => "MovePlayer",
|
||||
MC_PLACE_BLOCK => "PlaceBlock",
|
||||
MC_PLACE_BLOCK => "PlaceBlock",
|
||||
MC_REMOVE_BLOCK => "RemoveBlock",
|
||||
MC_UPDATE_BLOCK => "UpdateBlock",
|
||||
|
||||
MC_EXPLOSION => "Explosion",
|
||||
|
||||
MC_REQUEST_CHUNK => "RequestChunk",
|
||||
MC_CHUNK_DATA => "ChunkData",
|
||||
|
||||
|
||||
MC_PLAYER_EQUIPMENT => "PlayerEquipment",
|
||||
|
||||
|
||||
MC_INTERACT => "Interact",
|
||||
MC_USE_ITEM => "UseItem",
|
||||
MC_PLAYER_ACTION => "PlayerAction",
|
||||
@ -74,7 +76,12 @@ $dataName = array(
|
||||
MC_SET_SPAWN_POSITION => "SetSpawnPosition",
|
||||
MC_ANIMATE => "Animate",
|
||||
MC_RESPAWN => "Respawn",
|
||||
|
||||
|
||||
MC_DROP_ITEM => "DropItem",
|
||||
MC_CONTAINER_OPEN => "ContainerOpen",
|
||||
MC_CONTAINER_CLOSE => "ContainerClose",
|
||||
MC_CONTAINER_SET_SLOT => "ContainerSetSlot",
|
||||
|
||||
MC_CLIENT_MESSAGE => "ClientMessage",
|
||||
MC_SIGN_UPDATE => "SignUpdate",
|
||||
MC_ADVENTURE_SETTINGS => "AdventureSettings",
|
19
start.cmd
19
start.cmd
@ -1,6 +1,6 @@
|
||||
@echo off
|
||||
TITLE PocketMine-MP Server - by @shoghicp
|
||||
COLOR F0
|
||||
COLOR 0F
|
||||
mode con: cols=90
|
||||
|
||||
echo.
|
||||
@ -26,5 +26,18 @@ if not "%PHPOUTPUT%"=="1" (
|
||||
echo [ERROR] Couldn't find PHP binary in PATH.
|
||||
ping 127.0.0.1 -n 3 -w 1000>nul
|
||||
) else (
|
||||
START /B /WAIT php -d enable_dl=On PocketMine-MP.php
|
||||
)
|
||||
if exist php.cmd (
|
||||
if exist bin\ansicon.exe (
|
||||
bin\ansicon.exe php.cmd -d enable_dl=On PocketMine-MP.php --enable-ansi
|
||||
) else (
|
||||
php.cmd -d enable_dl=On PocketMine-MP.php
|
||||
)
|
||||
) else (
|
||||
if exist bin\ansicon.exe (
|
||||
bin\ansicon.exe php -d enable_dl=On PocketMine-MP.php --enable-ansi
|
||||
) else (
|
||||
php -d enable_dl=On PocketMine-MP.php
|
||||
)
|
||||
)
|
||||
)
|
||||
pause
|
||||
|
5
start.sh
5
start.sh
@ -3,6 +3,9 @@ DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd $DIR
|
||||
if [ -f php5/bin/php ]; then
|
||||
./php5/bin/php -d enable_dl=On PocketMine-MP.php
|
||||
read -p "Press [Enter] to continue..."
|
||||
exit 0
|
||||
fi
|
||||
php -d enable_dl=On PocketMine-MP.php
|
||||
php -d enable_dl=On PocketMine-MP.php
|
||||
read -p "Press [Enter] to continue..."
|
||||
exit 0
|
Reference in New Issue
Block a user