mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 03:06:55 +00:00
Compare commits
96 Commits
pocketmine
...
Alpha_1.0.
Author | SHA1 | Date | |
---|---|---|---|
a7cc37ead6 | |||
2353457b5b | |||
8f6ed22158 | |||
be78530175 | |||
22d7f856d8 | |||
c8a0315c52 | |||
356c5a6a72 | |||
dfd06ac3f7 | |||
941f1479c7 | |||
b7af93ca17 | |||
2d8b56fb5e | |||
41e8df5b88 | |||
d367a9b517 | |||
ead624274b | |||
80fda57c79 | |||
38c7a6bf33 | |||
b505a23acf | |||
5b057654a7 | |||
968b1becd7 | |||
8930b361eb | |||
5042289ff7 | |||
cae6285f64 | |||
3a0db10d6b | |||
4e9df899c2 | |||
196b0a4263 | |||
39d5fea0ef | |||
d90f317590 | |||
28048db141 | |||
145d0707e6 | |||
987a6e635e | |||
00fea6461c | |||
6742273644 | |||
bf7913f630 | |||
c82072c998 | |||
cecdf7e28f | |||
06a3db9b45 | |||
7ce0209b6c | |||
b169e269b8 | |||
618e9c58c7 | |||
1b47a716d3 | |||
ea6fe8312a | |||
92c64db1b5 | |||
16be7d42a7 | |||
46ded9e675 | |||
ed42ba5176 | |||
0329e6d217 | |||
af1e3e7767 | |||
cb7e9bb572 | |||
504b37cfaa | |||
bf24a937b2 | |||
b79374c13d | |||
2d9c400392 | |||
f987ff232b | |||
9f3523a920 | |||
0cb8f28122 | |||
cf5d8e5009 | |||
6ed6c98c64 | |||
5dd0666436 | |||
e8519f954d | |||
4695949ddd | |||
5be1b78a7f | |||
c4b8a7350c | |||
333035c285 | |||
28383deeee | |||
8b918a7bce | |||
c646b786e5 | |||
a1b51c3da4 | |||
332202c4e8 | |||
849cfcb01b | |||
b0b39b2357 | |||
f2868f386e | |||
c3eec804f0 | |||
022e25ff05 | |||
30a13fb1b4 | |||
529bb8a262 | |||
067147f750 | |||
30d2b41264 | |||
52810a11ba | |||
dfa9f55115 | |||
bcb65c2960 | |||
b867ba559e | |||
e47bacce74 | |||
44546fd11d | |||
d44ca14eb5 | |||
8c82f9f9c1 | |||
bbe7aacfaf | |||
fe3c054c83 | |||
fbfbd53204 | |||
e0c245d86e | |||
99151981db | |||
7fef49fbfc | |||
009ff61208 | |||
67c9181a06 | |||
3b800ff6b4 | |||
1cf47d0328 | |||
61cfbaf3fd |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
data/players/*
|
||||
data/maps/*
|
||||
data/plugins/*
|
||||
*.log
|
||||
server.properties
|
||||
white-list.txt
|
||||
|
41
README.md
41
README.md
@ -35,32 +35,19 @@ Github repo: https://github.com/shoghicp/PocketMine-MP
|
||||
Server (and client) Minecraft Pocket Edition library written in PHP.
|
||||
Currently a work in progress, and used to document http://www.wiki.vg/Pocket_Minecraft_Protocol
|
||||
|
||||
How to install it: https://github.com/shoghicp/PocketMine-MP/wiki/Tutorial:-Setting-up-a-Server
|
||||
Check the wiki! https://github.com/shoghicp/PocketMine-MP/wiki
|
||||
|
||||
**Project Status: `PRE-ALPHA`**
|
||||
**Project Status: `ALPHA`**
|
||||
|
||||
**Tested in: `v4.0.0, v5.0.0`**
|
||||
|
||||
|
||||
Current features of the server:
|
||||
-------------------------------
|
||||
* Players can connect and move around the world (and see each other)
|
||||
* Support for reading/sending chunks!
|
||||
* Map saving! Place & remove blocks
|
||||
* Multiple worlds and importing!
|
||||
* PvP, life regeneration and death cause!
|
||||
* Extensible API!
|
||||
* Online list broadcast
|
||||
* Configurable day/night cycle
|
||||
* Mob spawning!
|
||||
* Health and position saving
|
||||
* server.properties configuration file
|
||||
* Whitelist and IP Ban files
|
||||
* Survival & Creative
|
||||
* Awesome features in server list!
|
||||
* Automatic new version checking
|
||||
* Implemented packet loss recovery algorithm
|
||||
* + more!
|
||||
* Full Creative mode!
|
||||
* Plugin API
|
||||
* Custom world generation
|
||||
* Update Channels!! (stable / dev)
|
||||
|
||||
|
||||
How to contact me
|
||||
@ -70,13 +57,9 @@ How to contact me
|
||||
* Via IRC - #mcdevs or #mcpedevs on *irc.freenode.net* (or just /msg me there)
|
||||
* [MinecraftForums profile](http://www.minecraftforum.net/user/1476633-shoghicp/)
|
||||
|
||||
|
||||
---------------------------------------
|
||||
|
||||
|
||||
Third-party Tools:
|
||||
------------------
|
||||
* [How to connect to internet servers](http://www.minecraftforum.net/topic/1256915-legit-minecraftpe-online-multiplayer/)
|
||||
* [Video-Tutorial made by ChrisMCMine](http://www.youtube.com/watch?v=GC9MBVaHge0)
|
||||
* [User-made program to merge server I/O done in C++](https://github.com/filfat/MCPES_CPP_INPUT/)
|
||||
* [Proxy to allow devices in your local network join online servers using node.js](https://github.com/brandon15811/Minecraft-PE-Proxy)
|
||||
|
||||
Third-party Libraries Used
|
||||
--------------------------
|
||||
* __[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
|
||||
* __[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
|
4
TODO
4
TODO
@ -1,4 +0,0 @@
|
||||
- Fix spawn position resetting
|
||||
- Mob spawning, item pick up
|
||||
- Inventory loading and saving
|
||||
- Entity saving
|
33
TODO.md
Normal file
33
TODO.md
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
__Check Milestones [here](https://github.com/shoghicp/PocketMine-MP/issues/milestones)__
|
||||
|
||||
|
||||
## Not Fixing
|
||||
- Random strips and chunks of different land not sticking (the ones shown before world chunks are loaded)
|
||||
|
||||
## Known Bugs
|
||||
- Players jerk sometimes
|
||||
- Some chunk columns doesn't get loaded
|
||||
- Players don't despawn
|
||||
- Players can often hear "echos" of their own block interactions' SFX (torch placed, block destroyed, etc. most noticeable when moving around as you place.)
|
||||
|
||||
## Alpha (full Creative)
|
||||
* Done!
|
||||
|
||||
### Alpha v1.1
|
||||
|
||||
|
||||
## Beta (Survival)
|
||||
- Random Chunk Updates
|
||||
- Mob spawning, item pick up
|
||||
- Mob behavior
|
||||
- Placing Paintings
|
||||
- Inventory loading and saving
|
||||
- Entity saving
|
||||
- Wheat growth
|
||||
- Melon growth
|
||||
- Sapling growth
|
||||
- Mob interaction (hitting)
|
||||
- Firing Arrows
|
||||
- Eating
|
||||
- Nether???
|
820
classes/API/BlockAPI.php
Normal file
820
classes/API/BlockAPI.php
Normal file
@ -0,0 +1,820 @@
|
||||
<?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("BLOCK_UPDATE_NORMAL", 0);
|
||||
define("BLOCK_UPDATE_RANDOM", 1);
|
||||
define("BLOCK_UPDATE_SCHEDULED", 2);
|
||||
define("BLOCK_UPDATE_WEAK", 3);
|
||||
|
||||
|
||||
|
||||
class BlockAPI{
|
||||
private $server;
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->server->addHandler("world.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);
|
||||
}
|
||||
|
||||
public function blockBreak($data, $event){
|
||||
if($event !== "player.block.break"){
|
||||
return;
|
||||
}
|
||||
$target = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"]);
|
||||
if(isset(Material::$unbreakable[$target[0]])){
|
||||
return false;
|
||||
}
|
||||
$drop = array(
|
||||
$target[0], //Block
|
||||
$target[1], //Meta
|
||||
1, //Count
|
||||
);
|
||||
switch($target[0]){
|
||||
case 16:
|
||||
$drop = array(263, 0, 1);
|
||||
break;
|
||||
case 21:
|
||||
$drop = array(351, 4, mt_rand(4, 8));
|
||||
break;
|
||||
case 56:
|
||||
$drop = array(264, 0, 1);
|
||||
break;
|
||||
case 73:
|
||||
case 74:
|
||||
$drop = array(351, 4, mt_rand(4, 5));
|
||||
break;
|
||||
case 18:
|
||||
$drop = false;
|
||||
if(mt_rand(1,20) === 1){ //Saplings
|
||||
$drop = array(6, $target[1], 1);
|
||||
}
|
||||
if($target[1] === 0 and mt_rand(1,200) === 1){ //Apples
|
||||
$this->drop($data["x"], $data["y"], $data["z"], 260, 0, 1);
|
||||
}
|
||||
break;
|
||||
case 59:
|
||||
if($target[1] >= 0x07){ //Seeds
|
||||
$drop = array(296, 0, 1);
|
||||
$this->drop($data["x"], $data["y"], $data["z"], 295, 0, mt_rand(0,3));
|
||||
}else{
|
||||
$drop = array(295, 0, 1);
|
||||
}
|
||||
break;
|
||||
case 31:
|
||||
$drop = false;
|
||||
if(mt_rand(1,10) === 1){ //Seeds
|
||||
$drop = array(295, 0, 1);
|
||||
}
|
||||
break;
|
||||
case 20:
|
||||
$drop = false;
|
||||
break;
|
||||
case 30:
|
||||
$drop = false;
|
||||
break;
|
||||
case 51:
|
||||
$drop = false;
|
||||
break;
|
||||
case 52:
|
||||
$drop = false;
|
||||
break;
|
||||
case 43:
|
||||
$drop = array(
|
||||
44,
|
||||
$target[1],
|
||||
2,
|
||||
);
|
||||
break;
|
||||
case 60:
|
||||
case 2:
|
||||
$drop = array(3, 0, 1);
|
||||
break;
|
||||
case 64: //Door
|
||||
$drop = array(324, 0, 1);
|
||||
if(($target[1] & 0x08) === 0x08){
|
||||
$down = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
|
||||
if($down[0] === 64){
|
||||
$data2 = $data;
|
||||
--$data2["y"];
|
||||
$this->server->trigger("player.block.break", $data2);
|
||||
$this->updateBlocksAround($data2["x"], $data2["y"], $data2["z"], BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
}else{
|
||||
$up = $this->server->api->level->getBlock($data["x"], $data["y"] + 1, $data["z"]);
|
||||
if($up[0] === 64){
|
||||
$data2 = $data;
|
||||
++$data2["y"];
|
||||
$this->server->trigger("player.block.break", $data2);
|
||||
$this->updateBlocksAround($data2["x"], $data2["y"], $data2["z"], BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if($drop !== false and $drop[0] !== 0 and $drop[2] > 0){
|
||||
$this->drop($data["x"], $data["y"], $data["z"], $drop[0], $drop[1] & 0x0F, $drop[2] & 0xFF);
|
||||
}
|
||||
$this->server->trigger("player.block.break", $data);
|
||||
$this->updateBlocksAround($data["x"], $data["y"], $data["z"], BLOCK_UPDATE_NORMAL);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function drop($x, $y, $z, $block, $meta, $stack = 1){
|
||||
if($block === 0 or $stack <= 0 or $this->server->gamemode === 1){
|
||||
return;
|
||||
}
|
||||
$data = array(
|
||||
"x" => $x,
|
||||
"y" => $y,
|
||||
"z" => $z,
|
||||
"meta" => $meta,
|
||||
"stack" => $stack,
|
||||
);
|
||||
$data["x"] += mt_rand(2, 8) / 10;
|
||||
$data["y"] += mt_rand(2, 8) / 10;
|
||||
$data["z"] += mt_rand(2, 8) / 10;
|
||||
$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;
|
||||
}
|
||||
if($data["face"] < 0 or $data["face"] > 5){
|
||||
return false;
|
||||
}
|
||||
$target = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"]);
|
||||
$cancelPlace = false;
|
||||
if(isset(Material::$activable[$target[0]])){
|
||||
switch($target[0]){
|
||||
case 6:
|
||||
if($data["block"] === 351 and $data["meta"] === 0x0F){ //Bonemeal
|
||||
Sapling::growTree($this->server->api->level, $target, $target[1] & 0x03);
|
||||
$cancelPlace = true;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
if($data["block"] === 292){ //Hoe
|
||||
$data["block"] = 60;
|
||||
$data["meta"] = 0;
|
||||
$this->server->trigger("player.block.place", $data);
|
||||
$this->updateBlocksAround($data["x"], $data["y"], $data["z"], BLOCK_UPDATE_NORMAL);
|
||||
$cancelPlace = true;
|
||||
}
|
||||
case 59:
|
||||
case 105:
|
||||
if($data["block"] === 351 and $data["meta"] === 0x0F){ //Bonemeal
|
||||
switch($target[0]){
|
||||
case 59:
|
||||
case 105:
|
||||
$data["block"] = $target[0];
|
||||
$data["meta"] = 0x07;
|
||||
$this->server->trigger("player.block.place", $data);
|
||||
$this->updateBlocksAround($data["x"], $data["y"], $data["z"], BLOCK_UPDATE_NORMAL);
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
}
|
||||
$cancelPlace = true;
|
||||
}
|
||||
break;
|
||||
case 64: //Door
|
||||
if(($target[1] & 0x08) === 0x08){
|
||||
$down = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
|
||||
if($down[0] === 64){
|
||||
$down[1] = $down[1] ^ 0x04;
|
||||
$data2 = array(
|
||||
"x" => $data["x"],
|
||||
"z" => $data["z"],
|
||||
"y" => $data["y"] - 1,
|
||||
"block" => $down[0],
|
||||
"meta" => $down[1],
|
||||
"eid" => $data["eid"],
|
||||
);
|
||||
$this->server->trigger("player.block.update", $data2);
|
||||
$this->updateBlocksAround($data2["x"], $data2["y"], $data2["z"], BLOCK_UPDATE_NORMAL);
|
||||
$this->updateBlocksAround($data["x"], $data["y"], $data["z"], BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
}else{
|
||||
$data["block"] = $target[0];
|
||||
$data["meta"] = $target[1] ^ 0x04;
|
||||
$this->server->trigger("player.block.update", $data);
|
||||
$up = $this->server->api->level->getBlock($data["x"], $data["y"] + 1, $data["z"]);
|
||||
if($up[0] === 64){
|
||||
$data2 = $data;
|
||||
$data2["meta"] = $up[1];
|
||||
++$data2["y"];
|
||||
$this->updateBlocksAround($data2["x"], $data2["y"], $data2["z"], BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
$this->updateBlocksAround($data["x"], $data["y"], $data["z"], BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
$cancelPlace = true;
|
||||
break;
|
||||
case 96: //Trapdoor
|
||||
case 107: //Fence gates
|
||||
$data["block"] = $target[0];
|
||||
$data["meta"] = $target[1] ^ 0x04;
|
||||
$this->server->trigger("player.block.update", $data);
|
||||
$this->updateBlocksAround($data["x"], $data["y"], $data["z"], BLOCK_UPDATE_NORMAL);
|
||||
$cancelPlace = true;
|
||||
break;
|
||||
default:
|
||||
$cancelPlace = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if($cancelPlace === true){
|
||||
return false;
|
||||
}
|
||||
|
||||
$replace = false;
|
||||
switch($target[0]){
|
||||
case 44: //Slabs
|
||||
if($data["face"] !== 1){
|
||||
break;
|
||||
}
|
||||
if(($target[1] & 0x07) === ($data["meta"] & 0x07)){
|
||||
$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 false;
|
||||
}
|
||||
|
||||
if(isset(Material::$placeable[$data["block"]])){
|
||||
$data["block"] = Material::$placeable[$data["block"]] === true ? $data["block"]:Material::$placeable[$data["block"]];
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
|
||||
$direction = $this->server->api->entity->get($data["eid"])->getDirection();
|
||||
|
||||
switch($data["block"]){
|
||||
case 6:
|
||||
if($target[0] === 60){
|
||||
return false;
|
||||
}
|
||||
case 37:
|
||||
case 38:
|
||||
if($target[0] !== 2 and $target[0] !== 3){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 39://Mushrooms
|
||||
case 40:
|
||||
$blockDown = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
|
||||
if(isset(Material::$transparent[$blockDown[0]])){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 83: //Sugarcane
|
||||
$blockDown = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
|
||||
if($blockDown[0] !== 2 and $blockDown[0] !== 3 and $blockDown[0] !== 12){
|
||||
return false;
|
||||
}
|
||||
$block0 = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"] + 1);
|
||||
$block1 = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"] - 1);
|
||||
$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;
|
||||
}
|
||||
break;
|
||||
case 50: //Torch
|
||||
if(isset(Material::$transparent[$target[0]])){
|
||||
return false;
|
||||
}
|
||||
$faces = array(
|
||||
0 => 6,
|
||||
1 => 5,
|
||||
2 => 4,
|
||||
3 => 3,
|
||||
4 => 2,
|
||||
5 => 1,
|
||||
);
|
||||
if(!isset($faces[$data["face"]])){
|
||||
return false;
|
||||
}
|
||||
$data["meta"] = $faces[$data["face"]];
|
||||
break;
|
||||
case 53://Stairs
|
||||
case 67:
|
||||
case 108:
|
||||
$faces = array(
|
||||
0 => 0,
|
||||
1 => 2,
|
||||
2 => 1,
|
||||
3 => 3,
|
||||
);
|
||||
$data["meta"] = $faces[$direction] & 0x03;
|
||||
break;
|
||||
case 96: //trapdoor
|
||||
if(isset(Material::$transparent[$target[0]])){
|
||||
return false;
|
||||
}
|
||||
$faces = array(
|
||||
2 => 0,
|
||||
3 => 1,
|
||||
4 => 2,
|
||||
5 => 3,
|
||||
);
|
||||
if(!isset($faces[$data["face"]])){
|
||||
return false;
|
||||
}
|
||||
$data["meta"] = $faces[$data["face"]] & 0x03;
|
||||
break;
|
||||
case 107: //Fence gate
|
||||
$faces = array(
|
||||
0 => 3,
|
||||
1 => 0,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
);
|
||||
$data["meta"] = $faces[$direction] & 0x03;
|
||||
break;
|
||||
case 64://Door placing
|
||||
$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]])){
|
||||
return false;
|
||||
}else{
|
||||
$data2 = $data;
|
||||
$data2["meta"] = 0x08;
|
||||
$data["meta"] = $direction & 0x03;
|
||||
++$data2["y"];
|
||||
$this->server->trigger("player.block.place", $data2);
|
||||
$this->updateBlocksAround($data2["x"], $data2["y"], $data2["z"], BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
break;
|
||||
case 54:
|
||||
case 61:
|
||||
$faces = array(
|
||||
0 => 4,
|
||||
1 => 2,
|
||||
2 => 5,
|
||||
3 => 3,
|
||||
);
|
||||
$data["meta"] = $faces[$direction];
|
||||
break;
|
||||
case 26: //bed
|
||||
$face = array(
|
||||
0 => 3,
|
||||
1 => 4,
|
||||
2 => 2,
|
||||
3 => 5,
|
||||
);
|
||||
$next = $this->server->api->level->getBlockFace($block, $face[(($direction + 3) % 4)]);
|
||||
if(!isset(Material::$replaceable[$next[0]])){
|
||||
return false;
|
||||
}
|
||||
$data["meta"] = (($direction + 3) % 4) & 0x3;
|
||||
$data2 = $data;
|
||||
$data2["meta"] = $data2["meta"] | 0x08;
|
||||
$data2["x"] = $next[2][0];
|
||||
$data2["y"] = $next[2][1];
|
||||
$data2["z"] = $next[2][2];
|
||||
$this->server->trigger("player.block.place", $data2);
|
||||
$this->updateBlocksAround($data2["x"], $data2["y"], $data2["z"], BLOCK_UPDATE_NORMAL);
|
||||
break;
|
||||
case 65: //Ladder
|
||||
if(isset(Material::$transparent[$target[0]])){
|
||||
return false;
|
||||
}
|
||||
$faces = array(
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
5 => 5,
|
||||
);
|
||||
if(!isset($faces[$data["face"]])){
|
||||
return false;
|
||||
}
|
||||
$data["meta"] = $faces[$data["face"]];
|
||||
break;
|
||||
case 59://Seeds
|
||||
case 105:
|
||||
$blockDown = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
|
||||
if($blockDown[0] !== 60){
|
||||
return false;
|
||||
}
|
||||
$data["meta"] = 0;
|
||||
break;
|
||||
case 81: //Cactus
|
||||
$blockDown = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
|
||||
$block0 = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"] + 1);
|
||||
$block1 = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"] - 1);
|
||||
$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($blockDown[0] !== 12 or !isset(Material::$transparent[$block0[0]]) or !isset(Material::$transparent[$block1[0]]) or !isset(Material::$transparent[$block2[0]]) or !isset(Material::$transparent[$block3[0]])){
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
$this->server->trigger("player.block.place", $data);
|
||||
$this->updateBlock($data["x"], $data["y"], $data["z"], BLOCK_UPDATE_NORMAL);
|
||||
$this->updateBlocksAround($data["x"], $data["y"], $data["z"], BLOCK_UPDATE_NORMAL);
|
||||
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"){
|
||||
return;
|
||||
}
|
||||
$this->updateBlock($data["x"], $data["y"], $data["z"], isset($data["type"]) ? $data["type"]:BLOCK_UPDATE_RANDOM);
|
||||
}
|
||||
|
||||
public function flowLavaOn($source, $face){
|
||||
$down = 0;
|
||||
if($face === BlockFace::BOTTOM){
|
||||
$level = 0;
|
||||
$down = 1;
|
||||
}else{
|
||||
$level = ($source[1] & 0x07) + 2;
|
||||
if($level > 0x07){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$spread = $this->server->api->level->getBlockFace($source, $face);
|
||||
if(($source[0] === 10 or $source[0] === 11) and $spread[0] === 10){
|
||||
if($level < ($spread[1] & 0x07)){
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $spread[2][0],
|
||||
"y" => $spread[2][1],
|
||||
"z" => $spread[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], $spread[0], $level | $down);
|
||||
return true;
|
||||
}
|
||||
}elseif(isset(Material::$flowable[$spread[0]])){
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $spread[2][0],
|
||||
"y" => $spread[2][1],
|
||||
"z" => $spread[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], 10, $level | $down);
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function flowWaterOn($source, $face){
|
||||
$down = 0;
|
||||
if($face === BlockFace::BOTTOM){
|
||||
$level = 0;
|
||||
$down = 1;
|
||||
}else{
|
||||
$level = ($source[1] & 0x07) + 1;
|
||||
if($level > 0x07){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$spread = $this->server->api->level->getBlockFace($source, $face);
|
||||
if(($source[0] === 8 or $source[0] === 9) and $spread[0] === 8){
|
||||
if($level < ($spread[1] & 0x07)){
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $spread[2][0],
|
||||
"y" => $spread[2][1],
|
||||
"z" => $spread[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], $spread[0], $level | $down);
|
||||
return true;
|
||||
}
|
||||
}elseif(isset(Material::$flowable[$spread[0]])){
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $spread[2][0],
|
||||
"y" => $spread[2][1],
|
||||
"z" => $spread[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], 8, $level | $down);
|
||||
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);
|
||||
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;
|
||||
|
||||
switch($block[0]){
|
||||
case 8:
|
||||
case 9:
|
||||
if(!$this->flowWaterOn($block, 0) or $block[0] === 9){
|
||||
$this->flowWaterOn($block, 2);
|
||||
$this->flowWaterOn($block, 3);
|
||||
$this->flowWaterOn($block, 4);
|
||||
$this->flowWaterOn($block, 5);
|
||||
}
|
||||
if($block[0] === 8){
|
||||
$drained = true;
|
||||
$level = $block[1] & 0x07;
|
||||
$up = $this->server->api->level->getBlockFace($block, BlockFace::UP);
|
||||
if($up[0] === 8 or $up[0] === 9){
|
||||
$drained = false;
|
||||
}else{
|
||||
$b = $this->server->api->level->getBlockFace($block, BlockFace::NORTH);
|
||||
if($b[0] === 9 or ($b[0] === 8 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
|
||||
$drained = false;
|
||||
}else{
|
||||
$b = $this->server->api->level->getBlockFace($block, BlockFace::SOUTH);
|
||||
if($b[0] === 9 or ($b[0] === 8 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
|
||||
$drained = false;
|
||||
}else{
|
||||
$b = $this->server->api->level->getBlockFace($block, BlockFace::EAST);
|
||||
if($b[0] === 9 or ($b[0] === 8 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
|
||||
$drained = false;
|
||||
}else{
|
||||
$b = $this->server->api->level->getBlockFace($block, BlockFace::WEST);
|
||||
if($b[0] === 9 or ($b[0] === 8 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
|
||||
$drained = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($drained === true){
|
||||
++$level;
|
||||
if($level > 0x07){
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0] + 1,
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0] - 1,
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2] + 1,
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2] - 1,
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1] - 1,
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], 0, 0);
|
||||
}else{
|
||||
$block[1] = ($block[1] & 0x08) | $level;
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0] + 1,
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0] - 1,
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2] + 1,
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2] - 1,
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1] - 1,
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(10, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], $block[0], $block[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
case 11:
|
||||
if(!$this->flowLavaOn($block, 0) or $block[0] === 11){
|
||||
$this->flowLavaOn($block, 2);
|
||||
$this->flowLavaOn($block, 3);
|
||||
$this->flowLavaOn($block, 4);
|
||||
$this->flowLavaOn($block, 5);
|
||||
}
|
||||
if($block[0] === 10){
|
||||
$drained = true;
|
||||
$level = $block[1] & 0x07;
|
||||
$up = $this->server->api->level->getBlockFace($block, BlockFace::UP);
|
||||
if($up[0] === 10 or $up[0] === 11){
|
||||
$drained = false;
|
||||
}else{
|
||||
$b = $this->server->api->level->getBlockFace($block, BlockFace::NORTH);
|
||||
if($b[0] === 11 or ($b[0] === 10 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
|
||||
$drained = false;
|
||||
}else{
|
||||
$b = $this->server->api->level->getBlockFace($block, BlockFace::SOUTH);
|
||||
if($b[0] === 11 or ($b[0] === 10 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
|
||||
$drained = false;
|
||||
}else{
|
||||
$b = $this->server->api->level->getBlockFace($block, BlockFace::EAST);
|
||||
if($b[0] === 11 or ($b[0] === 10 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
|
||||
$drained = false;
|
||||
}else{
|
||||
$b = $this->server->api->level->getBlockFace($block, BlockFace::WEST);
|
||||
if($b[0] === 11 or ($b[0] === 10 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
|
||||
$drained = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($drained === true){
|
||||
++$level;
|
||||
if($level > 0x07){
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0] + 1,
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0] - 1,
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2] + 1,
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2] - 1,
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1] - 1,
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], 0, 0);
|
||||
}else{
|
||||
$block[1] = ($block[1] & 0x08) | $level;
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0] + 1,
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0] - 1,
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2] + 1,
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2] - 1,
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1] - 1,
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->schedule(20, array($this, "blockScheduler"), array(
|
||||
"x" => $block[2][0],
|
||||
"y" => $block[2][1],
|
||||
"z" => $block[2][2],
|
||||
"type" => BLOCK_UPDATE_NORMAL,
|
||||
));
|
||||
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], $block[0], $block[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 74:
|
||||
if($type === BLOCK_UPDATE_SCHEDULED or $type === BLOCK_UPDATE_RANDOM){
|
||||
$changed = true;
|
||||
$this->server->api->level->setBlock($x, $y, $z, 73, $block[1]);
|
||||
$type = BLOCK_UPDATE_WEAK;
|
||||
}
|
||||
break;
|
||||
case 73:
|
||||
if($type === BLOCK_UPDATE_NORMAL){
|
||||
$changed = true;
|
||||
$this->server->api->level->setBlock($x, $y, $z, 74, $block[1]);
|
||||
$this->server->schedule(mt_rand(40, 100), array($this, "blockScheduler"), array(
|
||||
"x" => $x,
|
||||
"y" => $y,
|
||||
"z" => $z,
|
||||
));
|
||||
$type = BLOCK_UPDATE_WEAK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if($type === BLOCK_TYPE_SCHEDULED){
|
||||
$type = BLOCK_UPDATE_WEAK;
|
||||
}
|
||||
if($changed === true){
|
||||
$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);
|
||||
$this->updateBlock($x, $y, $z + 1, $type);
|
||||
$this->updateBlock($x - 1, $y, $z, $type);
|
||||
$this->updateBlock($x, $y - 1, $z, $type);
|
||||
$this->updateBlock($x, $y, $z - 1, $type);
|
||||
}
|
||||
}
|
@ -25,21 +25,7 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
*/
|
||||
|
||||
require_once("common/dependencies.php");
|
||||
require_once("classes/PocketMinecraftClient.class.php");
|
||||
file_put_contents("packets.log", "");
|
||||
define("DEBUG", 2);
|
||||
class ChatAPI{
|
||||
|
||||
|
||||
$client = new PocketMinecraftClient("shoghicp");
|
||||
console("[INFO] Searching servers...");
|
||||
$list = $client->getServerList();
|
||||
foreach($list as $i => $info){
|
||||
console("[Server] #".$i." ".$info["ip"]." ".$info["username"]);
|
||||
}
|
||||
console("[Select Server] #", false, false);
|
||||
$i = (int) trim(fgets(STDIN));
|
||||
if(isset($list[$i])){
|
||||
$client->start($list[$i]["ip"]);
|
||||
}else{
|
||||
console("[Error] Unknown ID");
|
||||
}
|
@ -27,7 +27,7 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
class ConsoleAPI{
|
||||
private $input, $server, $event;
|
||||
function __construct($server){
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->help = array();
|
||||
$this->server = $server;
|
||||
$this->input = fopen(FILE_PATH."console.in", "w+b");
|
||||
@ -35,7 +35,7 @@ class ConsoleAPI{
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->event = $this->server->event("onTick", array($this, "handle"));
|
||||
$this->event = $this->server->event("server.tick", array($this, "handle"));
|
||||
}
|
||||
|
||||
function __destroy(){
|
||||
@ -221,7 +221,10 @@ class ConsoleAPI{
|
||||
}
|
||||
}
|
||||
|
||||
public function register($cmd, $help, $callback){
|
||||
public function register($cmd, $help,$callback){
|
||||
if(!is_callable($callback)){
|
||||
return false;
|
||||
}
|
||||
$this->help[strtolower(trim($cmd))] = array($help, $callback);
|
||||
}
|
||||
|
||||
@ -236,7 +239,7 @@ class ConsoleAPI{
|
||||
console("[INFO] Issued server command: /$cmd ".implode(" ", $params));
|
||||
if(isset($this->help[$cmd]) and is_callable($this->help[$cmd][1])){
|
||||
call_user_func($this->help[$cmd][1], $cmd, $params);
|
||||
}elseif($this->server->trigger("onCommand", array("cmd" => $cmd, "params" => $params)) !== false){
|
||||
}elseif($this->server->trigger("api.console.command", array("cmd" => $cmd, "params" => $params)) !== false){
|
||||
$this->defaultCommands($cmd, $params);
|
||||
}
|
||||
}
|
||||
|
@ -27,18 +27,18 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
class EntityAPI{
|
||||
private $server;
|
||||
function __construct($server){
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
$this->server->addHandler("onPlayerDeath", array($this, "handle"), 1);
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->server->api->console->register("give", "Give items to a player", array($this, "commandHandler"));
|
||||
$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 "onPlayerDeath":
|
||||
case "player.death":
|
||||
$message = $data["name"];
|
||||
if(is_numeric($data["cause"]) and isset($this->entities[$data["cause"]])){
|
||||
$e = $this->api->entity->get($data["cause"]);
|
||||
|
@ -26,28 +26,27 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
class LevelAPI{
|
||||
private $server, $map, $active = false;
|
||||
function __construct($server){
|
||||
private $server, $map;
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
$this->map = $this->server->map;
|
||||
if($this->map !== false){
|
||||
$this->active = true;
|
||||
}
|
||||
$this->heightMap = array_fill(0, 256, array());
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->server->addHandler("onBlockBreak", array($this, "handle"));
|
||||
$this->server->addHandler("onBlockPlace", array($this, "handle"));
|
||||
$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 "onBlockPlace":
|
||||
$block = $this->getBlock($data["x"], $data["y"], $data["z"]);
|
||||
console("[DEBUG] EID ".$data["eid"]." placed ".$data["block"].":".$data["meta"]." into ".$block[0].":".$block[1]." at X ".$data["x"]." Y ".$data["y"]." Z ".$data["z"], true, true, 2);
|
||||
case "player.block.place":
|
||||
case "player.block.update":
|
||||
console("[DEBUG] EID ".$data["eid"]." placed ".$data["block"].":".$data["meta"]." at X ".$data["x"]." Y ".$data["y"]." Z ".$data["z"], true, true, 2);
|
||||
$this->setBlock($data["x"], $data["y"], $data["z"], $data["block"], $data["meta"]);
|
||||
break;
|
||||
case "onBlockBreak":
|
||||
case "player.block.break":
|
||||
$block = $this->getBlock($data["x"], $data["y"], $data["z"]);
|
||||
console("[DEBUG] EID ".$data["eid"]." broke block ".$block[0].":".$block[1]." at X ".$data["x"]." Y ".$data["y"]." Z ".$data["z"], true, true, 2);
|
||||
|
||||
@ -55,54 +54,41 @@ class LevelAPI{
|
||||
break;
|
||||
}
|
||||
$this->setBlock($data["x"], $data["y"], $data["z"], 0, 0);
|
||||
$data["block"] = $block[0];
|
||||
$data["meta"] = $block[1];
|
||||
$data["stack"] = 1;
|
||||
$data["x"] += mt_rand(2, 8) / 10;
|
||||
$data["y"] += mt_rand(2, 8) / 10;
|
||||
$data["z"] += mt_rand(2, 8) / 10;
|
||||
$e = $this->server->api->entity->add(ENTITY_ITEM, $block[0], $data);
|
||||
$this->server->api->entity->spawnToAll($e->eid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function check(){
|
||||
if($this->active === true){
|
||||
return true;
|
||||
}elseif($this->active === false and $this->server->map === false){
|
||||
return false;
|
||||
}
|
||||
$this->active = true;
|
||||
return true;
|
||||
public function getSpawn(){
|
||||
return $this->server->spawn;
|
||||
}
|
||||
|
||||
public function getChunk($X, $Z){
|
||||
if($this->check() and isset($this->map->map[$X][$Z])){
|
||||
return $this->map->map[$X][$Z];
|
||||
}
|
||||
return false;
|
||||
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){
|
||||
if($this->check()){
|
||||
return $this->map->getBlock($x, $y, $z);
|
||||
}
|
||||
return array(0,0);
|
||||
$b = $this->map->getBlock($x, $y, $z);
|
||||
$b[2] = array($x, $y, $z);
|
||||
return $b;
|
||||
}
|
||||
|
||||
public function getFloor($x, $z){
|
||||
if($this->check()){
|
||||
return $this->map->getFloor($x, $z);
|
||||
if(!isset($this->heightMap[$z][$x])){
|
||||
$this->heightMap[$z][$x] = $this->map->getFloor($x, $z);
|
||||
}
|
||||
return 0;
|
||||
return $this->heightMap[$z][$x];
|
||||
}
|
||||
|
||||
public function setBlock($x, $y, $z, $block, $meta = 0){
|
||||
if($this->check()){
|
||||
$this->map->setBlock($x, $y, $z, $block, $meta);
|
||||
}
|
||||
$this->server->trigger("onBlockUpdate", array(
|
||||
$this->map->setBlock($x, $y, $z, $block, $meta);
|
||||
$this->heightMap[$z][$x] = $this->map->getFloor($x, $z);
|
||||
$this->server->trigger("world.block.change", array(
|
||||
"x" => $x,
|
||||
"y" => $y,
|
||||
"z" => $z,
|
||||
@ -114,9 +100,6 @@ class LevelAPI{
|
||||
public function getOrderedChunk($X, $Z, $columnsPerPacket = 2){
|
||||
$columnsPerPacket = max(1, (int) $columnsPerPacket);
|
||||
$c = $this->getChunk($X, $Z);
|
||||
if($c === false){
|
||||
return array(str_repeat("\x00", 256));
|
||||
}
|
||||
$ordered = array();
|
||||
$i = 0;
|
||||
$cnt = 0;
|
||||
|
@ -27,12 +27,12 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
class PlayerAPI{
|
||||
private $server;
|
||||
function __construct($server){
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
$this->server->event("onHealthRegeneration", array($this, "handle"));
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->server->event("server.regeneration", array($this, "handle"));
|
||||
$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"));
|
||||
@ -41,7 +41,7 @@ class PlayerAPI{
|
||||
|
||||
public function handle($data, $event){
|
||||
switch($event){
|
||||
case "onHealthRegeneration":
|
||||
case "server.regeneration":
|
||||
$result = $this->server->query("SELECT ip,port FROM players WHERE EID = (SELECT EID FROM entities WHERE health < 20);", true);
|
||||
if($result !== true and $result !== false){
|
||||
while(false !== ($player = $result->fetchArray())){
|
||||
@ -93,7 +93,7 @@ class PlayerAPI{
|
||||
case "list":
|
||||
console("[INFO] Player list:");
|
||||
foreach($this->server->clients as $c){
|
||||
console("[INFO] ".$c->username." (".$c->ip.":".$c->port."), ClientID ".$c->clientID.", (".round($c->username->entity->x, 2).", ".round($c->username->entity->y, 2).", ".round($c->username->entity->z, 2).")");
|
||||
console("[INFO] ".$c->username." (".$c->ip.":".$c->port."), ClientID ".$c->clientID.", (".round($c->entity->x, 2).", ".round($c->entity->y, 2).", ".round($c->entity->z, 2).")");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -199,16 +199,18 @@ class PlayerAPI{
|
||||
),
|
||||
"health" => 20,
|
||||
"lastIP" => "",
|
||||
"lastID" => "",
|
||||
"lastID" => 0,
|
||||
);
|
||||
$this->saveOffline($name, $data);
|
||||
}else{
|
||||
$data = unserialize(file_get_contents(FILE_PATH."data/players/".$name.".dat"));
|
||||
}
|
||||
$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."data/players/".str_replace("/", "", $name).".dat", serialize($data));
|
||||
}
|
||||
}
|
179
classes/API/PluginAPI.php
Normal file
179
classes/API/PluginAPI.php
Normal file
@ -0,0 +1,179 @@
|
||||
<?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 PluginAPI extends stdClass{
|
||||
private $server, $plugins;
|
||||
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){
|
||||
$list[] = $p[1];
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function getInfo($className){
|
||||
if(!isset($this->plugins[$className])){
|
||||
return false;
|
||||
}
|
||||
$plugin = $this->plugins[$className];
|
||||
return array($plugin[1], get_class_methods($plugin[0]));
|
||||
}
|
||||
|
||||
public function load($file){
|
||||
$content = file_get_contents($file);
|
||||
$info = strstr($content, "*/", true);
|
||||
$content = substr(strstr($content, "*/"),2);
|
||||
if(preg_match_all('#([a-zA-Z0-9\-_]*)=([^\r\n]*)#u', $info, $matches) == 0){ //false or 0 matches
|
||||
console("[ERROR] [PluginAPI] Failed parsing of ".basename($file));
|
||||
return false;
|
||||
}
|
||||
$info = array();
|
||||
foreach($matches[1] as $k => $i){
|
||||
$v = $matches[2][$k];
|
||||
switch(strtolower($v)){
|
||||
case "on":
|
||||
case "true":
|
||||
case "yes":
|
||||
$v = true;
|
||||
break;
|
||||
case "off":
|
||||
case "false":
|
||||
case "no":
|
||||
$v = false;
|
||||
break;
|
||||
}
|
||||
$info[$i] = $v;
|
||||
}
|
||||
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"]);
|
||||
if(class_exists($info["class"])){
|
||||
console("[ERROR] [PluginAPI] Failed loading plugin: class exists");
|
||||
}
|
||||
if(eval($content) === false or !class_exists($info["class"])){
|
||||
console("[ERROR] [PluginAPI] Failed loading plugin: evaluation error");
|
||||
}
|
||||
$className = trim($info["class"]);
|
||||
if(isset($info["api"]) and $info["api"] !== true){
|
||||
console("[NOTICE] [PluginAPI] Plugin \"".$info["name"]."\" 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");
|
||||
if(method_exists($object, "__destruct")){
|
||||
$object->__destruct();
|
||||
}
|
||||
$object = null;
|
||||
unset($object);
|
||||
}else{
|
||||
$this->plugins[$className] = array($object, $info);
|
||||
}
|
||||
}
|
||||
|
||||
public function get(Plugin $plugin){
|
||||
foreach($this->plugins as &$p){
|
||||
if($p[0] === $plugin){
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function createConfig(Plugin $plugin, $default = array()){
|
||||
$p = $this->get($plugin);
|
||||
if($p === false){
|
||||
return false;
|
||||
}
|
||||
$path = FILE_PATH."data/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);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
private function fillDefaults($default, &$yaml){
|
||||
foreach($default as $k => $v){
|
||||
if(is_array($v)){
|
||||
if(!isset($yaml[$k]) or !is_array($yaml[$k])){
|
||||
$yaml[$k] = array();
|
||||
}
|
||||
$this->fillDefaults($v, $yaml[$k]);
|
||||
}elseif(!isset($yaml[$k])){
|
||||
$yaml[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function readYAML($file){
|
||||
return Spyc::YAMLLoad(file_get_contents($file));
|
||||
}
|
||||
|
||||
public function writeYAML($file, $data){
|
||||
return file_put_contents($file, Spyc::YAMLDump($data));
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->server->event("server.start", array($this, "loadAll"));
|
||||
}
|
||||
|
||||
public function loadAll(){
|
||||
console("[INFO] Loading Plugins...");
|
||||
$dir = dir(FILE_PATH."data/plugins/");
|
||||
while(false !== ($file = $dir->read())){
|
||||
if($file !== "." and $file !== ".."){
|
||||
if(strtolower(substr($file, -3)) === "php"){
|
||||
$this->load(FILE_PATH."data/plugins/" . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach($this->plugins as $p){
|
||||
if(method_exists($p[0], "init")){
|
||||
$p[0]->init();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface Plugin{
|
||||
public function __construct(ServerAPI $api, $server = false);
|
||||
public function init();
|
||||
public function __destruct();
|
||||
}
|
@ -26,8 +26,8 @@ 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!
|
||||
var $server, $restart = false;
|
||||
private $config, $apiList = array();
|
||||
var $restart = false;
|
||||
private $server, $config, $apiList = array();
|
||||
function __construct(){
|
||||
console("[INFO] Starting ServerAPI server handler...");
|
||||
file_put_contents(FILE_PATH."packets.log", "");
|
||||
@ -90,22 +90,52 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
console("[DEBUG] Loading server.properties...", true, true, 2);
|
||||
$this->parseProperties();
|
||||
define("DEBUG", $this->config["debug"]);
|
||||
$this->server = new PocketMinecraftServer($this->getProperty("server-name"), $this->getProperty("gamemode"), $this->getProperty("seed"), $this->getProperty("protocol"), $this->getProperty("port"), $this->getProperty("server-id"));
|
||||
$this->server = new PocketMinecraftServer($this->getProperty("server-name"), $this->getProperty("gamemode"), false, CURRENT_PROTOCOL, $this->getProperty("port"), $this->getProperty("server-id"));
|
||||
$this->server->api = $this;
|
||||
if($this->getProperty("last-update") === false or ($this->getProperty("last-update") + 3600) < time()){
|
||||
console("[INFO] Checking for new version...");
|
||||
$info = json_decode(Utils::curl_get("https://api.github.com/repos/shoghicp/PocketMine-MP"), true);
|
||||
$last = new DateTime($info["updated_at"]);
|
||||
$last = $last->getTimestamp();
|
||||
if($last >= $this->getProperty("last-update") and $this->getProperty("last-update") !== false){
|
||||
console("[NOTICE] PocketMine-MP has been updated at ".date("Y-m-d H:i:s", $last));
|
||||
console("[NOTICE] If 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);
|
||||
console("[INFO] Checking for new server version");
|
||||
console("[INFO] Last check: ".date("Y-m-d H:i:s", $this->getProperty("last-update")));
|
||||
$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"])){
|
||||
console("[ERROR] GitHub API Error");
|
||||
}else{
|
||||
$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] 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");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$last = time();
|
||||
$this->setProperty("last-update", $last);
|
||||
console("[INFO] Last check at ".date("Y-m-d H:i:s", $last));
|
||||
$info = json_decode(Utils::curl_get("https://api.github.com/repos/shoghicp/PocketMine-MP/tags"), true);
|
||||
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"]);
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if(file_exists(FILE_PATH."data/maps/level.dat")){
|
||||
@ -113,7 +143,26 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
$this->importMap(FILE_PATH."data/maps/", true);
|
||||
}
|
||||
$this->server->mapName = $this->getProperty("level-name");
|
||||
$this->server->mapDir = FILE_PATH."data/maps/".$this->getProperty("level-name")."/";
|
||||
$this->server->mapDir = FILE_PATH."data/maps/".$this->server->mapName."/";
|
||||
if($this->server->mapName === false or trim($this->server->mapName) === "" or !file_exists($this->server->mapDir."chunks.dat")){
|
||||
if($this->server->mapName === false or trim($this->server->mapName) === ""){
|
||||
$this->server->mapName = "world";
|
||||
}
|
||||
$this->server->mapDir = FILE_PATH."data/maps/".$this->server->mapName."/";
|
||||
$generator = "SuperflatGenerator";
|
||||
if($this->getProperty("generator") !== false and class_exists($this->getProperty("generator"))){
|
||||
$generator = $this->getProperty("generator");
|
||||
}
|
||||
$this->gen = new WorldGenerator($generator, $this->server->seed);
|
||||
if($this->getProperty("generator-settings") !== false and trim($this->getProperty("generator-settings")) != ""){
|
||||
$this->gen->set("preset", $this->getProperty("generator-settings"));
|
||||
}
|
||||
$this->gen->init();
|
||||
$this->gen->generate();
|
||||
$this->gen->save($this->server->mapDir, $this->server->mapName);
|
||||
$this->setProperty("level-name", $this->server->mapName);
|
||||
$this->setProperty("gamemode", 1);
|
||||
}
|
||||
$this->loadProperties();
|
||||
$this->server->loadMap();
|
||||
|
||||
@ -129,32 +178,136 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach($this->apiList as $a){
|
||||
if(method_exists($this->$a, "init")){
|
||||
$this->$a->init();
|
||||
foreach($this->apiList as $ob){
|
||||
if(is_callable(array($ob, "init"))){
|
||||
$ob->init();
|
||||
}
|
||||
}
|
||||
|
||||
$this->server->loadEntities();
|
||||
}
|
||||
|
||||
public function getList(){
|
||||
return $this->apiList;
|
||||
private function loadProperties(){
|
||||
if(isset($this->config["memory-limit"])){
|
||||
@ini_set("memory_limit", $this->config["memory-limit"]);
|
||||
}else{
|
||||
$this->config["memory-limit"] = "256M";
|
||||
}
|
||||
if(!isset($this->config["invisible"])){
|
||||
$this->config["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->reloadConfig();
|
||||
}
|
||||
}
|
||||
|
||||
public function loadAPI($name, $class, $dir = false){
|
||||
if($dir === false){
|
||||
$dir = FILE_PATH."classes/API/";
|
||||
private function writeProperties(){
|
||||
if(is_object($this->server)){
|
||||
$this->config["server-id"] = $this->server->serverID;
|
||||
}
|
||||
$file = $dir.$class.".php";
|
||||
if(!file_exists($file)){
|
||||
console("[ERROR] API ".$name." [".$class."] in ".$dir." doesn't exist", true, true, 0);
|
||||
return false;
|
||||
$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";
|
||||
}
|
||||
require_once($file);
|
||||
$this->$name = new $class($this->server);
|
||||
$this->apiList[] = $name;
|
||||
console("[INFO] API ".$name." [".$class."] loaded");
|
||||
file_put_contents(FILE_PATH."server.properties", $prop);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
switch($n){
|
||||
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;
|
||||
}
|
||||
$this->config[$n] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
public function start(){
|
||||
$this->server->start();
|
||||
unregister_tick_function(array($this->server, "tick"));
|
||||
unset($this->server);
|
||||
return $this->restart;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
public function addHandler($e, $c, $p = 5){
|
||||
return $this->server->addHandler($e, $c, $p);
|
||||
}
|
||||
|
||||
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){
|
||||
@ -188,7 +341,7 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
$this->setProperty("level-name", $level["LevelName"]);
|
||||
$this->setProperty("gamemode", $level["GameType"]);
|
||||
$this->server->seed = $level["RandomSeed"];
|
||||
$this->setProperty("spawn", array("x" => $level["SpawnX"], "y" => $level["SpawnY"], "z" => $level["SpawnZ"]));
|
||||
$this->server->spawn = array("x" => $level["SpawnX"], "y" => $level["SpawnY"], "z" => $level["SpawnZ"]);
|
||||
$this->writeProperties();
|
||||
}
|
||||
console("[INFO] Map \"".$level["LevelName"]."\" importing done!");
|
||||
@ -211,118 +364,23 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
$this->loadProperties();
|
||||
}
|
||||
|
||||
private function loadProperties(){
|
||||
if(isset($this->config["memory-limit"])){
|
||||
@ini_set("memory_limit", $this->config["memory-limit"]);
|
||||
}else{
|
||||
$this->config["memory-limit"] = "256M";
|
||||
}
|
||||
if(!isset($this->config["invisible"])){
|
||||
$this->config["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->spawn = $this->config["spawn"];
|
||||
$this->server->whitelist = $this->config["white-list"];
|
||||
$this->server->reloadConfig();
|
||||
}
|
||||
public function getList(){
|
||||
return $this->apiList;
|
||||
}
|
||||
|
||||
private function writeProperties(){
|
||||
if(is_object($this->server)){
|
||||
$this->config["seed"] = $this->server->seed;
|
||||
$this->config["server-id"] = $this->server->serverID;
|
||||
public function loadAPI($name, $class, $dir = false){
|
||||
if($dir === false){
|
||||
$dir = FILE_PATH."classes/API/";
|
||||
}
|
||||
$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){
|
||||
if($n == "spawn"){
|
||||
$v = implode(";", $v);
|
||||
}
|
||||
$prop .= $n."=".$v."\r\n";
|
||||
$file = $dir.$class.".php";
|
||||
if(!file_exists($file)){
|
||||
console("[ERROR] API ".$name." [".$class."] in ".$dir." doesn't exist", true, true, 0);
|
||||
return false;
|
||||
}
|
||||
file_put_contents(FILE_PATH."server.properties", $prop);
|
||||
require_once($file);
|
||||
$this->$name = new $class($this->server);
|
||||
$this->apiList[] = $this->$name;
|
||||
console("[INFO] API ".$name." [".$class."] loaded");
|
||||
}
|
||||
|
||||
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($n){
|
||||
case "last-update":
|
||||
if(trim($v) == "false"){
|
||||
$v = time();
|
||||
}else{
|
||||
$v = (int) $v;
|
||||
}
|
||||
break;
|
||||
case "protocol":
|
||||
if(trim($v) == "CURRENT"){
|
||||
$v = CURRENT_PROTOCOL;
|
||||
break;
|
||||
}
|
||||
case "gamemode":
|
||||
case "max-players":
|
||||
case "port":
|
||||
case "debug":
|
||||
case "difficulty":
|
||||
case "time-per-second":
|
||||
$v = (int) $v;
|
||||
break;
|
||||
case "seed":
|
||||
$v = trim($v);
|
||||
if($v == "false"){
|
||||
$v = false;
|
||||
}elseif(preg_match("/[^0-9\-]/", $v) > 0){
|
||||
$str = new Java_String($v);
|
||||
$v = $str->hashCode();
|
||||
}else{
|
||||
$v = (int) $v;
|
||||
}
|
||||
break;
|
||||
case "server-id":
|
||||
$v = trim($v);
|
||||
$v = $v == "false" ? false:(preg_match("/[^0-9\-]/", $v) > 0 ? Utils::readInt(substr(md5($v, true), 0, 4)):$v);
|
||||
break;
|
||||
case "level-name":
|
||||
$v = trim($v);
|
||||
$v = $v == "false" ? false:$v;
|
||||
break;
|
||||
case "spawn":
|
||||
$v = explode(";", $v);
|
||||
$v = array("x" => floatval($v[0]), "y" => floatval($v[1]), "z" => floatval($v[2]));
|
||||
break;
|
||||
case "white-list":
|
||||
case "invisible":
|
||||
$v = trim($v) == "true" ? true:false;
|
||||
break;
|
||||
}
|
||||
$this->config[$n] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
public function start(){
|
||||
$this->server->start();
|
||||
unregister_tick_function(array($this->server, "tick"));
|
||||
unset($this->server);
|
||||
return $this->restart;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -33,7 +33,7 @@ class TimeAPI{
|
||||
"sunrise" => 17800,
|
||||
);
|
||||
private $server;
|
||||
function __construct($server){
|
||||
function __construct(PocketMinecraftServer $server){
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVI Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @version $Id: BigInteger.php 326530 2012-07-07 22:05:25Z terrafrost $
|
||||
* @version $Id: BigInteger.php,v 1.33 2010/03/22 22:32:03 terrafrost Exp $
|
||||
* @link http://pear.php.net/package/Math_BigInteger
|
||||
*/
|
||||
|
||||
@ -282,6 +282,10 @@ class Math_BigInteger {
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('openssl_public_encrypt') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
|
||||
define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
|
||||
}
|
||||
|
||||
switch ( MATH_BIGINTEGER_MODE ) {
|
||||
case MATH_BIGINTEGER_MODE_GMP:
|
||||
if (is_resource($x) && get_resource_type($x) == 'GMP integer') {
|
||||
@ -601,13 +605,19 @@ class Math_BigInteger {
|
||||
{
|
||||
$hex = $this->toHex($twos_compliment);
|
||||
$bits = '';
|
||||
for ($i = 0, $end = strlen($hex) & 0xFFFFFFF8; $i < $end; $i+=8) {
|
||||
$bits.= str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT);
|
||||
for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) {
|
||||
$bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits;
|
||||
}
|
||||
if ($end != strlen($hex)) { // hexdec('') == 0
|
||||
$bits.= str_pad(decbin(hexdec(substr($hex, $end))), strlen($hex) & 7, '0', STR_PAD_LEFT);
|
||||
if ($start) { // hexdec('') == 0
|
||||
$bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits;
|
||||
}
|
||||
return $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
|
||||
$result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
|
||||
|
||||
if ($twos_compliment && $this->compare(new Math_BigInteger()) > 0 && $this->precision <= 0) {
|
||||
return '0' . $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1591,6 +1601,53 @@ class Math_BigInteger {
|
||||
return $this->_normalize($temp->modPow($e, $n));
|
||||
}
|
||||
|
||||
if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP) {
|
||||
$temp = new Math_BigInteger();
|
||||
$temp->value = gmp_powm($this->value, $e->value, $n->value);
|
||||
|
||||
return $this->_normalize($temp);
|
||||
}
|
||||
|
||||
if ($this->compare(new Math_BigInteger()) < 0 || $this->compare($n) > 0) {
|
||||
list(, $temp) = $this->divide($n);
|
||||
return $temp->modPow($e, $n);
|
||||
}
|
||||
|
||||
if (defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
|
||||
$components = array(
|
||||
'modulus' => $n->toBytes(true),
|
||||
'publicExponent' => $e->toBytes(true)
|
||||
);
|
||||
|
||||
$components = array(
|
||||
'modulus' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['modulus'])), $components['modulus']),
|
||||
'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent'])
|
||||
);
|
||||
|
||||
$RSAPublicKey = pack('Ca*a*a*',
|
||||
48, $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])),
|
||||
$components['modulus'], $components['publicExponent']
|
||||
);
|
||||
|
||||
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
|
||||
$RSAPublicKey = chr(0) . $RSAPublicKey;
|
||||
$RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey;
|
||||
|
||||
$encapsulated = pack('Ca*a*',
|
||||
48, $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey
|
||||
);
|
||||
|
||||
$RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
|
||||
chunk_split(base64_encode($encapsulated)) .
|
||||
'-----END PUBLIC KEY-----';
|
||||
|
||||
$plaintext = str_pad($this->toBytes(), strlen($n->toBytes(true)) - 1, "\0", STR_PAD_LEFT);
|
||||
|
||||
if (openssl_public_encrypt($plaintext, $result, $RSAPublicKey, OPENSSL_NO_PADDING)) {
|
||||
return new Math_BigInteger($result, 256);
|
||||
}
|
||||
}
|
||||
|
||||
switch ( MATH_BIGINTEGER_MODE ) {
|
||||
case MATH_BIGINTEGER_MODE_GMP:
|
||||
$temp = new Math_BigInteger();
|
||||
@ -3550,4 +3607,24 @@ class Math_BigInteger {
|
||||
$temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT));
|
||||
return $temp['int'];
|
||||
}
|
||||
|
||||
/**
|
||||
* DER-encode an integer
|
||||
*
|
||||
* The ability to DER-encode integers is needed to create RSA public keys for use with OpenSSL
|
||||
*
|
||||
* @see modPow()
|
||||
* @access private
|
||||
* @param Integer $length
|
||||
* @return String
|
||||
*/
|
||||
function _encodeASN1Length($length)
|
||||
{
|
||||
if ($length <= 0x7F) {
|
||||
return chr($length);
|
||||
}
|
||||
|
||||
$temp = ltrim(pack('N', $length), chr(0));
|
||||
return pack('Ca*', 0x80 | strlen($temp), $temp);
|
||||
}
|
||||
}
|
@ -68,6 +68,13 @@ class ChunkParser{
|
||||
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}));
|
||||
|
@ -424,9 +424,9 @@ class CustomPacketHandler{
|
||||
$this->data["block"] = Utils::readShort($this->get(2));
|
||||
$this->data["meta"] = Utils::readByte($this->get(1));
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["unknown2"] = Utils::readFloat($this->get(4));
|
||||
$this->data["unknown3"] = Utils::readFloat($this->get(4));
|
||||
$this->data["unknown4"] = Utils::readFloat($this->get(4));
|
||||
$this->data["fx"] = Utils::readFloat($this->get(4));
|
||||
$this->data["fy"] = Utils::readFloat($this->get(4));
|
||||
$this->data["fz"] = Utils::readFloat($this->get(4));
|
||||
}else{
|
||||
/*$this->raw .= Utils::writeByte($this->data["action"]);
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
|
241
classes/Data.class.php
Normal file
241
classes/Data.class.php
Normal file
@ -0,0 +1,241 @@
|
||||
<?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 BlockFace{
|
||||
const BOTTOM = 0;
|
||||
const TOP = 1;
|
||||
const DOWN = 0;
|
||||
const UP = 1;
|
||||
const SOUTH = 3;
|
||||
const EAST = 5;
|
||||
const NORTH = 2;
|
||||
const WEST = 4;
|
||||
public static function setPosition(&$data, $face){
|
||||
switch((int) $face){
|
||||
case 0:
|
||||
--$data["y"];
|
||||
break;
|
||||
case 1:
|
||||
++$data["y"];
|
||||
break;
|
||||
case 2:
|
||||
--$data["z"];
|
||||
break;
|
||||
case 3:
|
||||
++$data["z"];
|
||||
break;
|
||||
case 4:
|
||||
--$data["x"];
|
||||
break;
|
||||
case 5:
|
||||
++$data["x"];
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class Material{
|
||||
static $flowable = array(
|
||||
0 => true,
|
||||
6 => true,
|
||||
30 => true,
|
||||
31 => true,
|
||||
32 => true,
|
||||
37 => true,
|
||||
38 => true,
|
||||
39 => true,
|
||||
40 => true,
|
||||
50 => true,
|
||||
51 => true,
|
||||
55 => true,
|
||||
59 => true,
|
||||
78 => true,
|
||||
105 => true,
|
||||
);
|
||||
static $unbreakable = array(
|
||||
0 => true,
|
||||
7 => true,
|
||||
8 => true,
|
||||
9 => true,
|
||||
10 => true,
|
||||
11 => true,
|
||||
);
|
||||
static $transparent = array(
|
||||
0 => true,
|
||||
6 => true,
|
||||
8 => true,
|
||||
9 => true,
|
||||
10 => true,
|
||||
11 => true,
|
||||
18 => true,
|
||||
20 => true,
|
||||
26 => true,
|
||||
30 => true,
|
||||
31 => true,
|
||||
32 => true,
|
||||
37 => true,
|
||||
38 => true,
|
||||
39 => true,
|
||||
40 => true,
|
||||
46 => true,
|
||||
50 => true,
|
||||
51 => true,
|
||||
53 => true,
|
||||
59 => true,
|
||||
65 => true,
|
||||
67 => true,
|
||||
78 => true,
|
||||
79 => true,
|
||||
81 => true,
|
||||
83 => true,
|
||||
89 => true,
|
||||
96 => true,
|
||||
102 => true,
|
||||
105 => true,
|
||||
107 => true,
|
||||
108 => true,
|
||||
);
|
||||
static $replaceable = array(
|
||||
0 => true,
|
||||
8 => true,
|
||||
9 => true,
|
||||
10 => true,
|
||||
11 => true,
|
||||
31 => true,
|
||||
51 => true,
|
||||
78 => true,
|
||||
);
|
||||
static $activable = array(
|
||||
2 => true,
|
||||
3 => true,
|
||||
6 => true,
|
||||
26 => true,
|
||||
31 => true,
|
||||
46 => true,
|
||||
51 => true,
|
||||
54 => true,
|
||||
58 => true,
|
||||
59 => true,
|
||||
61 => true,
|
||||
62 => true,
|
||||
64 => true,
|
||||
78 => true,
|
||||
96 => true,
|
||||
105 => true,
|
||||
107 => true,
|
||||
247 => true,
|
||||
);
|
||||
static $placeable = array(
|
||||
1 => true,
|
||||
2 => true,
|
||||
3 => true,
|
||||
4 => true,
|
||||
5 => true,
|
||||
6 => true,
|
||||
//7 => true,
|
||||
8 => true,
|
||||
9 => true,
|
||||
10 => true,
|
||||
11 => true,
|
||||
12 => true,
|
||||
13 => true,
|
||||
14 => true,
|
||||
15 => true,
|
||||
16 => true,
|
||||
17 => true,
|
||||
18 => true,
|
||||
19 => true,
|
||||
20 => true,
|
||||
21 => true,
|
||||
22 => true,
|
||||
24 => true,
|
||||
355 => 26,
|
||||
30 => true,
|
||||
35 => true,
|
||||
37 => true,
|
||||
38 => true,
|
||||
39 => true,
|
||||
40 => true,
|
||||
41 => true,
|
||||
42 => true,
|
||||
43 => true,
|
||||
44 => true,
|
||||
45 => true,
|
||||
46 => true,
|
||||
47 => true,
|
||||
48 => true,
|
||||
49 => true,
|
||||
50 => true,
|
||||
53 => true,
|
||||
54 => true,
|
||||
56 => true,
|
||||
59 => true,
|
||||
57 => true,
|
||||
58 => true,
|
||||
295 => 59,
|
||||
61 => true,
|
||||
324 => 64,
|
||||
65 => true,
|
||||
67 => true,
|
||||
73 => true,
|
||||
79 => true,
|
||||
80 => true,
|
||||
81 => true,
|
||||
82 => true,
|
||||
83 => true,
|
||||
85 => true,
|
||||
86 => true,
|
||||
87 => true,
|
||||
88 => true,
|
||||
89 => true,
|
||||
91 => true,
|
||||
96 => true,
|
||||
98 => true,
|
||||
102 => true,
|
||||
103 => true,
|
||||
362 => 105,
|
||||
107 => true,
|
||||
108 => true,
|
||||
246 => true,
|
||||
247 => true,
|
||||
);
|
||||
static $blocks = array(
|
||||
0 => "Air",
|
||||
1 => "Stone",
|
||||
2 => "Grass",
|
||||
3 => "Dirt",
|
||||
4 => "Cobblestone",
|
||||
5 => "Wooden Planks",
|
||||
6 => "Sapling",
|
||||
7 => "Bedrock",
|
||||
);
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
@ -74,6 +74,26 @@ class Entity extends stdClass{
|
||||
}
|
||||
}
|
||||
|
||||
public function getDirection(){
|
||||
$rotation = ($this->yaw - 90) % 360;
|
||||
if ($rotation < 0) {
|
||||
$rotation += 360.0;
|
||||
}
|
||||
if(0 <= $rotation && $rotation < 45) {
|
||||
return 2;
|
||||
}elseif(45 <= $rotation && $rotation < 135) {
|
||||
return 3;
|
||||
}elseif(135 <= $rotation && $rotation < 225) {
|
||||
return 0;
|
||||
}elseif(225 <= $rotation && $rotation < 315) {
|
||||
return 1;
|
||||
}elseif(315 <= $rotation && $rotation < 360) {
|
||||
return 2;
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function spawn($player){
|
||||
if(!is_object($player)){
|
||||
$player = $this->server->api->player->get($player);
|
||||
@ -91,6 +111,11 @@ class Entity extends stdClass{
|
||||
"y" => $this->y,
|
||||
"z" => $this->z,
|
||||
));
|
||||
$player->dataPacket(MC_PLAYER_EQUIPMENT, array(
|
||||
"eid" => $this->eid,
|
||||
"block" => $this->player->equipment[0],
|
||||
"meta" => $this->player->equipment[1],
|
||||
));
|
||||
break;
|
||||
case ENTITY_ITEM:
|
||||
$player->dataPacket(MC_ADD_ITEM_ENTITY, array(
|
||||
@ -121,7 +146,7 @@ class Entity extends stdClass{
|
||||
public function close(){
|
||||
if($this->closed === false){
|
||||
$this->server->query("DELETE FROM entities WHERE EID = ".$this->eid.";");
|
||||
$this->server->trigger("onEntityRemove", $this->eid);
|
||||
$this->server->trigger("entity.remove", $this->eid);
|
||||
$this->closed = true;
|
||||
}
|
||||
}
|
||||
@ -186,7 +211,7 @@ class Entity extends stdClass{
|
||||
public function setHealth($health, $cause = ""){
|
||||
$this->health = (int) $health;
|
||||
$this->server->query("UPDATE entities SET health = ".$this->health." WHERE EID = ".$this->eid.";");
|
||||
$this->server->trigger("onHealthChange", array("eid" => $this->eid, "health" => $health, "cause" => $cause));
|
||||
$this->server->trigger("entity.health.change", array("eid" => $this->eid, "health" => $health, "cause" => $cause));
|
||||
if($this->player !== false){
|
||||
$this->player->dataPacket(MC_SET_HEALTH, array(
|
||||
"health" => $this->health,
|
||||
@ -195,7 +220,7 @@ class Entity extends stdClass{
|
||||
if($this->health <= 0 and $this->dead === false){
|
||||
$this->dead = true;
|
||||
if($this->player !== false){
|
||||
$this->server->handle("onPlayerDeath", array("name" => $this->name, "cause" => $cause));
|
||||
$this->server->handle("player.death", array("name" => $this->name, "cause" => $cause));
|
||||
}
|
||||
}elseif($this->health > 0){
|
||||
$this->dead = false;
|
||||
|
355
classes/Generator.class.php
Normal file
355
classes/Generator.class.php
Normal file
@ -0,0 +1,355 @@
|
||||
<?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 WorldGenerator{
|
||||
private $gen, $seed, $raw;
|
||||
public function __construct($genName, $seed){
|
||||
$this->seed = (int) $seed;
|
||||
$this->raw = b"";
|
||||
$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".
|
||||
"\x15\xa9\x00\x00\x15\xbe\x00\x00\x15\xd3\x00\x00\x15\xe8\x00\x00".
|
||||
"\x15\xfd\x00\x00\x15\x12\x01\x00\x15\x27\x01\x00\x15\x3c\x01\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\x51\x01\x00\x15\x66\x01\x00\x15\x7b\x01\x00\x15\x90\x01\x00".
|
||||
"\x15\xa5\x01\x00\x15\xba\x01\x00\x15\xcf\x01\x00\x15\xe4\x01\x00".
|
||||
"\x15\xf9\x01\x00\x15\x0e\x02\x00\x15\x23\x02\x00\x15\x38\x02\x00".
|
||||
"\x15\x4d\x02\x00\x15\x62\x02\x00\x15\x77\x02\x00\x15\x8c\x02\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\xa1\x02\x00\x15\xb6\x02\x00\x15\xcb\x02\x00\x15\xe0\x02\x00".
|
||||
"\x15\xf5\x02\x00\x15\x0a\x03\x00\x15\x1f\x03\x00\x15\x34\x03\x00".
|
||||
"\x15\x49\x03\x00\x15\x5e\x03\x00\x15\x73\x03\x00\x15\x88\x03\x00".
|
||||
"\x15\x9d\x03\x00\x15\xb2\x03\x00\x15\xc7\x03\x00\x15\xdc\x03\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\xf1\x03\x00\x15\x06\x04\x00\x15\x1b\x04\x00\x15\x30\x04\x00".
|
||||
"\x15\x45\x04\x00\x15\x5a\x04\x00\x15\x6f\x04\x00\x15\x84\x04\x00".
|
||||
"\x15\x99\x04\x00\x15\xae\x04\x00\x15\xc3\x04\x00\x15\xd8\x04\x00".
|
||||
"\x15\xed\x04\x00\x15\x02\x05\x00\x15\x17\x05\x00\x15\x2c\x05\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\x41\x05\x00\x15\x56\x05\x00\x15\x6b\x05\x00\x15\x80\x05\x00".
|
||||
"\x15\x95\x05\x00\x15\xaa\x05\x00\x15\xbf\x05\x00\x15\xd4\x05\x00".
|
||||
"\x15\xe9\x05\x00\x15\xfe\x05\x00\x15\x13\x06\x00\x15\x28\x06\x00".
|
||||
"\x15\x3d\x06\x00\x15\x52\x06\x00\x15\x67\x06\x00\x15\x7c\x06\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\x91\x06\x00\x15\xa6\x06\x00\x15\xbb\x06\x00\x15\xd0\x06\x00".
|
||||
"\x15\xe5\x06\x00\x15\xfa\x06\x00\x15\x0f\x07\x00\x15\x24\x07\x00".
|
||||
"\x15\x39\x07\x00\x15\x4e\x07\x00\x15\x63\x07\x00\x15\x78\x07\x00".
|
||||
"\x15\x8d\x07\x00\x15\xa2\x07\x00\x15\xb7\x07\x00\x15\xcc\x07\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\xe1\x07\x00\x15\xf6\x07\x00\x15\x0b\x08\x00\x15\x20\x08\x00".
|
||||
"\x15\x35\x08\x00\x15\x4a\x08\x00\x15\x5f\x08\x00\x15\x74\x08\x00".
|
||||
"\x15\x89\x08\x00\x15\x9e\x08\x00\x15\xb3\x08\x00\x15\xc8\x08\x00".
|
||||
"\x15\xdd\x08\x00\x15\xf2\x08\x00\x15\x07\x09\x00\x15\x1c\x09\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\x31\x09\x00\x15\x46\x09\x00\x15\x5b\x09\x00\x15\x70\x09\x00".
|
||||
"\x15\x85\x09\x00\x15\x9a\x09\x00\x15\xaf\x09\x00\x15\xc4\x09\x00".
|
||||
"\x15\xd9\x09\x00\x15\xee\x09\x00\x15\x03\x0a\x00\x15\x18\x0a\x00".
|
||||
"\x15\x2d\x0a\x00\x15\x42\x0a\x00\x15\x57\x0a\x00\x15\x6c\x0a\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\x81\x0a\x00\x15\x96\x0a\x00\x15\xab\x0a\x00\x15\xc0\x0a\x00".
|
||||
"\x15\xd5\x0a\x00\x15\xea\x0a\x00\x15\xff\x0a\x00\x15\x14\x0b\x00".
|
||||
"\x15\x29\x0b\x00\x15\x3e\x0b\x00\x15\x53\x0b\x00\x15\x68\x0b\x00".
|
||||
"\x15\x7d\x0b\x00\x15\x92\x0b\x00\x15\xa7\x0b\x00\x15\xbc\x0b\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\xd1\x0b\x00\x15\xe6\x0b\x00\x15\xfb\x0b\x00\x15\x10\x0c\x00".
|
||||
"\x15\x25\x0c\x00\x15\x3a\x0c\x00\x15\x4f\x0c\x00\x15\x64\x0c\x00".
|
||||
"\x15\x79\x0c\x00\x15\x8e\x0c\x00\x15\xa3\x0c\x00\x15\xb8\x0c\x00".
|
||||
"\x15\xcd\x0c\x00\x15\xe2\x0c\x00\x15\xf7\x0c\x00\x15\x0c\x0d\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\x21\x0d\x00\x15\x36\x0d\x00\x15\x4b\x0d\x00\x15\x60\x0d\x00".
|
||||
"\x15\x75\x0d\x00\x15\x8a\x0d\x00\x15\x9f\x0d\x00\x15\xb4\x0d\x00".
|
||||
"\x15\xc9\x0d\x00\x15\xde\x0d\x00\x15\xf3\x0d\x00\x15\x08\x0e\x00".
|
||||
"\x15\x1d\x0e\x00\x15\x32\x0e\x00\x15\x47\x0e\x00\x15\x5c\x0e\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\x71\x0e\x00\x15\x86\x0e\x00\x15\x9b\x0e\x00\x15\xb0\x0e\x00".
|
||||
"\x15\xc5\x0e\x00\x15\xda\x0e\x00\x15\xef\x0e\x00\x15\x04\x0f\x00".
|
||||
"\x15\x19\x0f\x00\x15\x2e\x0f\x00\x15\x43\x0f\x00\x15\x58\x0f\x00".
|
||||
"\x15\x6d\x0f\x00\x15\x82\x0f\x00\x15\x97\x0f\x00\x15\xac\x0f\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\xc1\x0f\x00\x15\xd6\x0f\x00\x15\xeb\x0f\x00\x15\x00\x10\x00".
|
||||
"\x15\x15\x10\x00\x15\x2a\x10\x00\x15\x3f\x10\x00\x15\x54\x10\x00".
|
||||
"\x15\x69\x10\x00\x15\x7e\x10\x00\x15\x93\x10\x00\x15\xa8\x10\x00".
|
||||
"\x15\xbd\x10\x00\x15\xd2\x10\x00\x15\xe7\x10\x00\x15\xfc\x10\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\x11\x11\x00\x15\x26\x11\x00\x15\x3b\x11\x00\x15\x50\x11\x00".
|
||||
"\x15\x65\x11\x00\x15\x7a\x11\x00\x15\x8f\x11\x00\x15\xa4\x11\x00".
|
||||
"\x15\xb9\x11\x00\x15\xce\x11\x00\x15\xe3\x11\x00\x15\xf8\x11\x00".
|
||||
"\x15\x0d\x12\x00\x15\x22\x12\x00\x15\x37\x12\x00\x15\x4c\x12\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\x61\x12\x00\x15\x76\x12\x00\x15\x8b\x12\x00\x15\xa0\x12\x00".
|
||||
"\x15\xb5\x12\x00\x15\xca\x12\x00\x15\xdf\x12\x00\x15\xf4\x12\x00".
|
||||
"\x15\x09\x13\x00\x15\x1e\x13\x00\x15\x33\x13\x00\x15\x48\x13\x00".
|
||||
"\x15\x5d\x13\x00\x15\x72\x13\x00\x15\x87\x13\x00\x15\x9c\x13\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x15\xb1\x13\x00\x15\xc6\x13\x00\x15\xdb\x13\x00\x15\xf0\x13\x00".
|
||||
"\x15\x05\x14\x00\x15\x1a\x14\x00\x15\x2f\x14\x00\x15\x44\x14\x00".
|
||||
"\x15\x59\x14\x00\x15\x6e\x14\x00\x15\x83\x14\x00\x15\x98\x14\x00".
|
||||
"\x15\xad\x14\x00\x15\xc2\x14\x00\x15\xd7\x14\x00\x15\xec\x14\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
|
||||
"\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;
|
||||
}
|
||||
console("[DEBUG] Generating level ".ceil(($Z + 1)/0.16)."%", true, true, 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getChunk($X, $Z){
|
||||
$chunk = b"";
|
||||
$columns = array();
|
||||
$X *= 16;
|
||||
$Z *= 16;
|
||||
for($x = 0; $x < 16; ++$x){
|
||||
for($z = 0; $z < 16; ++$z){
|
||||
$columns[$x * 16 + $z] = $this->gen->getColumn($X + $x, $Z + $z);
|
||||
}
|
||||
}
|
||||
for($i = 0; $i < 4; ++$i){
|
||||
for($x = 0; $x < 16; ++$x){
|
||||
for($z = 0; $z < 16; ++$z){
|
||||
$chunk .= $columns[$x * 16 + $z][$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($columns);
|
||||
return $chunk;
|
||||
}
|
||||
|
||||
public function save($dir, $name){
|
||||
@mkdir($dir, 0777, true);
|
||||
file_put_contents($dir."chunks.dat", $this->raw);
|
||||
$s = $this->getSpawn();
|
||||
$array = array();
|
||||
file_put_contents($dir."entities.dat", serialize($array));
|
||||
file_put_contents($dir."tileEntities.dat", serialize($array));
|
||||
$level = array(
|
||||
"LevelName" => $name,
|
||||
"Time" => 0,
|
||||
"Gamemode" => 1,
|
||||
"RandomSeed" => $this->seed,
|
||||
"SpawnX" => $s[0],
|
||||
"SpawnY" => $s[1],
|
||||
"SpawnZ" => $s[2],
|
||||
);
|
||||
file_put_contents($dir."level.dat", serialize($level));
|
||||
}
|
||||
|
||||
}
|
@ -26,9 +26,9 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
|
||||
class Session{
|
||||
class Player{
|
||||
private $server, $timeout, $connected, $evid, $queue, $buffer;
|
||||
var $clientID, $ip, $port, $counter, $username, $eid, $data, $entity, $auth, $CID, $MTU, $spawned;
|
||||
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();
|
||||
@ -43,17 +43,18 @@ class Session{
|
||||
$this->port = $port;
|
||||
$this->timeout = microtime(true) + 25;
|
||||
$this->evid = array();
|
||||
$this->equipment = array(1, 0);
|
||||
$this->spawned = false;
|
||||
$this->evid[] = $this->server->event("onTick", array($this, "onTick"));
|
||||
$this->evid[] = $this->server->event("onClose", array($this, "close"));
|
||||
$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);
|
||||
$this->counter = array(0, 0, 0);
|
||||
}
|
||||
|
||||
public function onTick($time, $event){
|
||||
if($event !== "onTick"){
|
||||
if($event !== "server.tick"){
|
||||
return;
|
||||
}
|
||||
if($time > $this->timeout){
|
||||
@ -96,7 +97,7 @@ class Session{
|
||||
foreach($this->evid as $ev){
|
||||
$this->server->deleteEvent($ev);
|
||||
}
|
||||
$this->eventHandler("You have been kicked. Reason: ".$reason, "onChat");
|
||||
$this->eventHandler("You have been kicked. Reason: ".$reason, "server.chat");
|
||||
$this->dataPacket(MC_LOGIN_STATUS, array(
|
||||
"status" => 1,
|
||||
));
|
||||
@ -104,7 +105,7 @@ class Session{
|
||||
|
||||
$this->connected = false;
|
||||
if($msg === true){
|
||||
$this->server->trigger("onChat", $this->username." left the game");
|
||||
$this->server->trigger("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);
|
||||
@ -112,23 +113,16 @@ class Session{
|
||||
|
||||
public function eventHandler($data, $event){
|
||||
switch($event){
|
||||
case "onBlockUpdate":
|
||||
$this->dataPacket(MC_UPDATE_BLOCK, $data);
|
||||
break;
|
||||
case "onTeleport":
|
||||
if($data["eid"] !== $this->eid){
|
||||
case "player.equipment.change":
|
||||
if($data["eid"] === $this->eid){
|
||||
break;
|
||||
}
|
||||
$this->dataPacket(MC_MOVE_PLAYER, array(
|
||||
"eid" => $data["eid"],
|
||||
"x" => $data["x"],
|
||||
"y" => $data["y"],
|
||||
"z" => $data["z"],
|
||||
"yaw" => 0,
|
||||
"pitch" => 0,
|
||||
));
|
||||
$this->dataPacket(MC_PLAYER_EQUIPMENT, $data);
|
||||
break;
|
||||
case "onEntityMove":
|
||||
case "world.block.change":
|
||||
$this->dataPacket(MC_UPDATE_BLOCK, $data);
|
||||
break;
|
||||
case "entity.move":
|
||||
if($data === $this->eid){
|
||||
break;
|
||||
}
|
||||
@ -142,7 +136,7 @@ class Session{
|
||||
"pitch" => $entity->pitch,
|
||||
));
|
||||
break;
|
||||
case "onEntityRemove":
|
||||
case "entity.remove":
|
||||
if($data === $this->eid){
|
||||
break;
|
||||
}
|
||||
@ -150,12 +144,12 @@ class Session{
|
||||
"eid" => $data,
|
||||
));
|
||||
break;
|
||||
case "onTimeChange":
|
||||
case "server.time.change":
|
||||
$this->dataPacket(MC_SET_TIME, array(
|
||||
"time" => $data,
|
||||
));
|
||||
break;
|
||||
case "onAnimate":
|
||||
case "entity.animate":
|
||||
if($data["eid"] === $this->eid){
|
||||
break;
|
||||
}
|
||||
@ -164,10 +158,10 @@ class Session{
|
||||
"action" => $data["action"],
|
||||
));
|
||||
break;
|
||||
case "onChat":
|
||||
case "server.chat":
|
||||
$this->dataPacket(MC_CHAT, array(
|
||||
"message" => $data,
|
||||
));
|
||||
"message" => str_replace("@username", $this->username, $data),
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -187,8 +181,19 @@ class Session{
|
||||
}
|
||||
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;
|
||||
@ -234,6 +239,15 @@ class Session{
|
||||
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){
|
||||
@ -242,14 +256,11 @@ class Session{
|
||||
if($c !== false){
|
||||
$c->close("logged in from another location");
|
||||
}
|
||||
if($this->server->whitelist !== false and !in_array($this->username, $this->server->whitelist)){
|
||||
$this->close("\"".$this->username."\" not being on white-list", false);
|
||||
break;
|
||||
}
|
||||
$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,
|
||||
));
|
||||
@ -275,32 +286,37 @@ class Session{
|
||||
$this->entity->data["clientID"] = $this->clientID;
|
||||
$this->server->api->entity->spawnAll($this);
|
||||
$this->server->api->entity->spawnToAll($this->eid);
|
||||
$this->evid[] = $this->server->event("onTimeChange", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onChat", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onEntityRemove", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onEntityMove", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onAnimate", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onTeleport", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onBlockUpdate", array($this, "eventHandler"));
|
||||
$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("world.block.change", array($this, "eventHandler"));
|
||||
console("[DEBUG] Player with EID ".$this->eid." \"".$this->username."\" spawned!", true, true, 2);
|
||||
|
||||
$this->eventHandler($this->server->motd, "onChat");
|
||||
$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.", "onChat");
|
||||
$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->trigger("onEntityMove", $this->eid);
|
||||
$this->server->trigger("entity.move", $this->eid);
|
||||
}
|
||||
break;
|
||||
case MC_PLAYER_EQUIPMENT:
|
||||
console("[DEBUG] EID ".$this->eid." has now ".$data["block"].":".$data["meta"]." in their hands!", true, true, 2);
|
||||
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 = floor(($this->MTU - 16 - 255) / 192);
|
||||
$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(
|
||||
@ -313,47 +329,15 @@ class Session{
|
||||
console("[INTERNAL] Chunk X ".$data["x"]." Z ".$data["z"]." requested", true, true, 3);
|
||||
break;
|
||||
case MC_USE_ITEM:
|
||||
if($data["face"] >= 0 and $data["face"] <= 5 and $data["block"] !== 0){
|
||||
switch($data["face"]){
|
||||
case 0:
|
||||
--$data["y"];
|
||||
break;
|
||||
case 1:
|
||||
++$data["y"];
|
||||
break;
|
||||
case 2:
|
||||
--$data["z"];
|
||||
break;
|
||||
case 3:
|
||||
++$data["z"];
|
||||
break;
|
||||
case 4:
|
||||
--$data["x"];
|
||||
break;
|
||||
case 5:
|
||||
++$data["x"];
|
||||
break;
|
||||
}
|
||||
if($data["block"] === 65){
|
||||
$data["block"] = 63;
|
||||
}
|
||||
$data["eid"] = $this->eid;
|
||||
$this->server->handle("onBlockPlace", $data);
|
||||
if($data["block"] === 63){
|
||||
$data["line0"] = "WHOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
|
||||
$data["line1"] = "this is a test";
|
||||
$data["line2"] = "I'm ".$this->username;
|
||||
$data["line3"] = "TPS: ".$this->server->getTPS();
|
||||
$this->dataPacket(MC_SIGN_UPDATE, $data);
|
||||
}
|
||||
}
|
||||
$data["eid"] = $this->eid;
|
||||
$this->server->handle("player.block.action", $data);
|
||||
break;
|
||||
case MC_PLACE_BLOCK:
|
||||
var_dump($data);
|
||||
|
||||
break;
|
||||
case MC_REMOVE_BLOCK:
|
||||
$data["eid"] = $this->eid;
|
||||
$this->server->handle("onBlockBreak", $data);
|
||||
$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){
|
||||
@ -364,7 +348,7 @@ class Session{
|
||||
}
|
||||
break;
|
||||
case MC_ANIMATE:
|
||||
$this->server->trigger("onAnimate", array("eid" => $this->eid, "action" => $data["action"]));
|
||||
$this->server->trigger("entity.animate", array("eid" => $this->eid, "action" => $data["action"]));
|
||||
break;
|
||||
case MC_RESPAWN:
|
||||
$this->entity->setHealth(20, "respawn");
|
@ -25,14 +25,12 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
*/
|
||||
|
||||
require_once("classes/Session.class.php");
|
||||
|
||||
class PocketMinecraftServer extends stdClass{
|
||||
var $invisible, $tickMeasure, $preparedSQL, $seed, $protocol, $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, $protocol = CURRENT_PROTOCOL, $port = 19132, $serverID = false, $version = CURRENT_VERSION){
|
||||
$this->port = (int) $port; //19132 - 19135
|
||||
console("[INFO] PocketMine-MP by @shoghicp, LGPL License. http://bit.ly/TbrimG", true, true, 0);
|
||||
console("[INFO] PocketMine-MP ".MAJOR_VERSION." by @shoghicp, LGPL License. http://bit.ly/TbrimG", true, true, 0);
|
||||
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");
|
||||
@ -57,6 +55,8 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->handCnt = 0;
|
||||
$this->eidCnt = 1;
|
||||
$this->maxClients = 20;
|
||||
$this->schedule = array();
|
||||
$this->scheduleCnt = 0;
|
||||
$this->description = "";
|
||||
$this->whitelist = false;
|
||||
$this->bannedIPs = array();
|
||||
@ -86,11 +86,11 @@ class PocketMinecraftServer extends stdClass{
|
||||
}
|
||||
|
||||
public function loadEvents(){
|
||||
$this->event("onChat", "eventHandler", true);
|
||||
$this->event("onPlayerAdd", "eventHandler", true);
|
||||
$this->event("server.chat", array($this, "eventHandler"));
|
||||
$this->event("player.new", array($this, "eventHandler"));
|
||||
|
||||
$this->action(500000, '$this->time += (int) ($this->timePerSecond / 2);$this->trigger("onTimeChange", $this->time);');
|
||||
$this->action(5000000, 'if($this->difficulty < 2){$this->trigger("onHealthRegeneration", 1);}');
|
||||
$this->action(500000, '$this->time += (int) ($this->timePerSecond / 2);$this->trigger("server.time.change", $this->time);');
|
||||
$this->action(5000000, 'if($this->difficulty < 2){$this->trigger("server.regeneration", 1);}');
|
||||
$this->action(1000000 * 60, '$this->reloadConfig();');
|
||||
$this->action(1000000 * 60 * 10, '$this->custom = array();');
|
||||
if($this->api !== false){
|
||||
@ -153,11 +153,13 @@ class PocketMinecraftServer extends stdClass{
|
||||
}
|
||||
|
||||
public function close($reason = "stop"){
|
||||
$this->chat(false, "Stopping server...");
|
||||
$this->save();
|
||||
$this->stop = true;
|
||||
$this->trigger("onClose");
|
||||
$this->interface->close();
|
||||
if($this->stop !== true){
|
||||
$this->chat(false, "Stopping server...");
|
||||
$this->save();
|
||||
$this->stop = true;
|
||||
$this->trigger("server.close");
|
||||
$this->interface->close();
|
||||
}
|
||||
}
|
||||
|
||||
public function chat($owner, $text, $target = true){
|
||||
@ -166,7 +168,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
$message = "<".$owner."> ";
|
||||
}
|
||||
$message .= $text;
|
||||
$this->trigger("onChat", $message);
|
||||
$this->trigger("server.chat", $message);
|
||||
}
|
||||
|
||||
public function setType($type = "normal"){
|
||||
@ -192,28 +194,36 @@ class PocketMinecraftServer extends stdClass{
|
||||
return $this->handCnt++;
|
||||
}
|
||||
|
||||
public function handle($event, $data){
|
||||
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();
|
||||
if($handlers === false or $handlers === true){
|
||||
return $this->trigger($event, $data);
|
||||
}
|
||||
while(false !== ($hn = $handlers->fetchArray(SQLITE3_ASSOC))){
|
||||
$hnid = (int) $hn["ID"];
|
||||
call_user_func($this->handlers[$hnid], $data, $event);
|
||||
$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);
|
||||
}else{
|
||||
$result = $handler($data, $event);
|
||||
}
|
||||
}
|
||||
}
|
||||
$handlers->finalize();
|
||||
return true;
|
||||
if($result !== false){
|
||||
$this->trigger($event, $data);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function eventHandler($data, $event){
|
||||
switch($event){
|
||||
case "onPlayerAdd":
|
||||
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 "onChat":
|
||||
case "server.chat":
|
||||
console("[CHAT] $data");
|
||||
break;
|
||||
}
|
||||
@ -225,7 +235,15 @@ class PocketMinecraftServer extends stdClass{
|
||||
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"];
|
||||
}
|
||||
$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"));
|
||||
@ -299,6 +317,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
declare(ticks=15);
|
||||
register_tick_function(array($this, "tick"));
|
||||
register_shutdown_function(array($this, "close"));
|
||||
$this->trigger("server.start", microtime(true));
|
||||
console("[INFO] Server started!");
|
||||
$this->process();
|
||||
}
|
||||
@ -306,10 +325,10 @@ class PocketMinecraftServer extends stdClass{
|
||||
public function tick(){
|
||||
$time = microtime(true);
|
||||
if($this->lastTick <= ($time - 0.05)){
|
||||
$this->tickMeasure[] = $this->lastTick = $time;
|
||||
array_shift($this->tickMeasure);
|
||||
$this->tickMeasure[] = $this->lastTick = $time;
|
||||
$this->tickerFunction($time);
|
||||
$this->trigger("onTick", $time);
|
||||
$this->trigger("server.tick", $time);
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,7 +434,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
$port = $data[2];
|
||||
$MTU = $data[3];
|
||||
$clientID = $data[4];
|
||||
$this->clients[$CID] = new Session($this, $clientID, $packet["ip"], $packet["port"], $MTU);
|
||||
$this->clients[$CID] = new Player($this, $clientID, $packet["ip"], $packet["port"], $MTU);
|
||||
$this->clients[$CID]->handle(0x07, $data);
|
||||
break;
|
||||
}
|
||||
@ -446,8 +465,13 @@ class PocketMinecraftServer extends stdClass{
|
||||
return;
|
||||
}
|
||||
while(false !== ($evn = $events->fetchArray(SQLITE3_ASSOC))){
|
||||
$evid = (int) $evn["ID"];
|
||||
$this->responses[$evid] = call_user_func($this->events[$evid], $data, $event, $this);
|
||||
$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);
|
||||
}
|
||||
}
|
||||
$events->finalize();
|
||||
return true;
|
||||
@ -460,10 +484,23 @@ class PocketMinecraftServer extends stdClass{
|
||||
return $res;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function schedule($ticks, $callback, $data = array(), $repeat = false, $eventName = "server.schedule"){
|
||||
if(!is_callable($callback)){
|
||||
return false;
|
||||
}
|
||||
$add = "";
|
||||
if($repeat === false){
|
||||
$add = ' unset($this->schedule['.$this->scheduleCnt.']);';
|
||||
}
|
||||
$this->schedule[$this->scheduleCnt] = array($callback, $data, $eventName);
|
||||
$this->action(50000 * $ticks, '$schedule = $this->schedule['.$this->scheduleCnt.'];'.$add.' call_user_func($schedule[0], $schedule[1], $schedule[2]);', (bool) $repeat);
|
||||
return $this->scheduleCnt++;
|
||||
}
|
||||
|
||||
public function action($microseconds, $code, $repeat = true){
|
||||
$this->query("INSERT INTO actions (interval, last, code, repeat) VALUES(".($microseconds / 1000000).", ".microtime(true).", '".str_replace("'", "\\'", $code)."', ".($repeat === true ? 1:0).");");
|
||||
$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);
|
||||
}
|
||||
|
||||
@ -478,7 +515,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
return;
|
||||
}
|
||||
while(false !== ($action = $actions->fetchArray(SQLITE3_ASSOC))){
|
||||
eval($action["code"]);
|
||||
eval(base64_decode($action["code"]));
|
||||
if($action["repeat"] === 0){
|
||||
$this->query("DELETE FROM actions WHERE ID = ".$action["ID"].";");
|
||||
}
|
||||
@ -490,10 +527,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->preparedSQL->updateActions->execute();
|
||||
}
|
||||
|
||||
public function event($event, $func, $in = false){
|
||||
if($in === true){
|
||||
$func = array($this, $func);
|
||||
}
|
||||
public function event($event, $func){
|
||||
if(!is_callable($func)){
|
||||
return false;
|
||||
}
|
||||
|
1057
classes/Spyc.class.php
Normal file
1057
classes/Spyc.class.php
Normal file
File diff suppressed because it is too large
Load Diff
107
classes/SuperflatGenerator.class.php
Normal file
107
classes/SuperflatGenerator.class.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?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 SuperflatGenerator{
|
||||
private $config, $spawn, $structure;
|
||||
public function __construct($seed){
|
||||
$this->config = array(
|
||||
"preset" => "7;20x1;3x3;2",
|
||||
"spawn-surface" => 24,
|
||||
"spawn-radius" => 10,
|
||||
"torches" => 0,
|
||||
"seed" => (int) $seed,
|
||||
);
|
||||
$this->parsePreset();
|
||||
}
|
||||
|
||||
public function set($name, $value){
|
||||
$this->config[$name] = $value;
|
||||
if($name === "preset"){
|
||||
$this->parsePreset();
|
||||
}
|
||||
}
|
||||
|
||||
private function parsePreset(){
|
||||
$this->structure = array(
|
||||
0 => "",
|
||||
1 => "",
|
||||
2 => str_repeat("\x00", 64),
|
||||
3 => str_repeat("\x00", 64),
|
||||
);
|
||||
$preset = explode(";", trim($this->config["preset"]));
|
||||
foreach($preset as $i => $data){
|
||||
$num = 1;
|
||||
if(preg_match('#([a-zA-Z\-_]*)\((.*)\)#', $data, $matches) > 0){ //Property
|
||||
$this->config[$matches[1]] = $matches[2];
|
||||
continue;
|
||||
}elseif(preg_match('#([0-9]*)x([0-9:]*)#', $data, $matches) > 0){
|
||||
$num = (int) $matches[1];
|
||||
$d = explode(":", $matches[2]);
|
||||
}else{
|
||||
$d = explode(":", $data);
|
||||
}
|
||||
$block = (int) array_shift($d);
|
||||
$meta = (int) @array_shift($d);
|
||||
for($j = 0; $j < $num; ++$j){
|
||||
$this->structure[0] .= chr($block & 0xFF);
|
||||
$this->structure[1] .= substr(dechex($meta & 0x0F), -1);
|
||||
}
|
||||
}
|
||||
$this->structure[1] = pack("h*", str_pad($this->structure[1], (strlen($this->structure[1])&0xFE) + 2, "0", STR_PAD_RIGHT)); //invert nibbles
|
||||
$this->structure[0] = substr($this->structure[0], 0, 128);
|
||||
$this->structure[1] = substr($this->structure[1], 0, 64);
|
||||
$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;
|
||||
$column = $this->structure;
|
||||
if(floor(sqrt(pow($x - $this->spawn[0], 2) + pow($z - $this->spawn[2], 2))) <= $this->config["spawn-radius"]){
|
||||
$column[0]{strlen($column[0])-1} = chr($this->config["spawn-surface"]);
|
||||
}
|
||||
if(($x % 8) === 0 and ($z % 8) === 0 and $this->config["torches"] == "1"){
|
||||
$column[0] .= chr(50);
|
||||
}
|
||||
$column[0] .= str_repeat(chr(0), 128 - strlen($column[0]));
|
||||
$column[1] .= str_repeat(chr(0), 64 - strlen($column[1]));
|
||||
$column[2] .= str_repeat(chr(0), 64 - strlen($column[2]));
|
||||
$column[3] .= str_repeat(chr(0), 64 - strlen($column[3]));
|
||||
return $column;
|
||||
}
|
||||
|
||||
}
|
@ -35,7 +35,7 @@ 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));
|
||||
|
||||
class Utils{
|
||||
abstract class Utils{
|
||||
|
||||
public static function getOS(){
|
||||
$uname = strtoupper(php_uname("s"));
|
||||
|
@ -39,4 +39,5 @@ 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("TEST_MD5", "5ca8eced50a5801619f7ae86d631a4e7");
|
||||
define("MAJOR_VERSION", "Alpha_1.0.1");
|
@ -1,12 +1,12 @@
|
||||
#Pocket Minecraft PHP server properties
|
||||
server-name=PHP Server
|
||||
description= This is a Work in Progress custom server.
|
||||
motd=Welcome to PHP Server
|
||||
#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
|
||||
protocol=CURRENT
|
||||
memory-limit=256M
|
||||
memory-limit=512M
|
||||
last-update=false
|
||||
update-channel=stable
|
||||
white-list=false
|
||||
debug=2
|
||||
max-players=20
|
||||
@ -14,7 +14,7 @@ server-type=normal
|
||||
time-per-second=20
|
||||
gamemode=1
|
||||
difficulty=1
|
||||
seed=false
|
||||
generator=
|
||||
generator-settings=
|
||||
level-name=false
|
||||
server-id=false
|
||||
spawn=128.5;100;128.5
|
||||
server-id=false
|
@ -68,6 +68,12 @@ if($errors > 0){
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
|
||||
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");
|
||||
@ -79,5 +85,6 @@ 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("misc/");
|
||||
|
||||
?>
|
@ -26,6 +26,44 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
|
||||
function require_all($path, &$count = 0){
|
||||
$dir = dir($path."/");
|
||||
while(false !== ($file = $dir->read())){
|
||||
if($file !== "." and $file !== ".."){
|
||||
if(!is_dir($path.$file) and strtolower(substr($file, -3)) === "php"){
|
||||
require_once($path.$file);
|
||||
++$count;
|
||||
}elseif(is_dir($path.$file)){
|
||||
require_all($path.$file."/", $count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function hard_unset(&$var){
|
||||
if(is_object($var)){
|
||||
$unset = new ReflectionClass($var);
|
||||
foreach($unset->getProperties() as $prop){
|
||||
$prop->setAccessible(true);
|
||||
@hard_unset($prop->getValue($var));
|
||||
$prop->setValue($var, null);
|
||||
}
|
||||
$var = null;
|
||||
unset($var);
|
||||
}elseif(is_array($var)){
|
||||
foreach($var as $i => $v){
|
||||
hard_unset($var[$i]);
|
||||
}
|
||||
$var = null;
|
||||
unset($var);
|
||||
}else{
|
||||
$var = null;
|
||||
unset($var);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function parseNBTData($data){
|
||||
$x = array();
|
||||
if(isset($data["value"])){
|
||||
|
34
example/ExamplePlugin.php
Normal file
34
example/ExamplePlugin.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
__PocketMine Plugin__
|
||||
name=ExamplePlugin
|
||||
version=0.0.1
|
||||
author=shoghicp
|
||||
class=ExamplePlugin
|
||||
*/
|
||||
|
||||
|
||||
class ExamplePlugin implements Plugin{
|
||||
private $api;
|
||||
public function __construct(ServerAPI $api, $server = false){
|
||||
$this->api = $api;
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->api->console->register("example", "Example command", array($this, "handleCommand"));
|
||||
}
|
||||
|
||||
public function __destruct(){
|
||||
|
||||
}
|
||||
|
||||
public function handleCommand($cmd, $arg){
|
||||
switch($cmd){
|
||||
case "example":
|
||||
console("EXAMPLE!!!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
46
example/ReactorAsWater.php
Normal file
46
example/ReactorAsWater.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
__PocketMine Plugin__
|
||||
name=ReactorAsWater
|
||||
description=Replaces the Nether Reactor with Water
|
||||
version=0.0.2
|
||||
author=shoghicp
|
||||
class=ReactorAsWater
|
||||
*/
|
||||
|
||||
|
||||
class ReactorAsWater implements Plugin{
|
||||
private $api;
|
||||
public function __construct(ServerAPI $api, $server = false){
|
||||
$this->api = $api;
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->api->addHandler("player.block.action", array($this, "handle"), 15); //Priority higher that API
|
||||
$this->api->addHandler("player.equipment.change", array($this, "handle"), 15);
|
||||
}
|
||||
|
||||
public function __destruct(){
|
||||
|
||||
}
|
||||
|
||||
public function handle(&$data, $event){
|
||||
switch($event){
|
||||
case "player.equipment.change":
|
||||
if($data["block"] === 247){
|
||||
$this->api->player->getByEID($data["eid"])->eventHandler("[ReactorAsWater] Placing water", "server.chat");
|
||||
$data["block"] = 9;
|
||||
$data["meta"] = 0;
|
||||
}
|
||||
break;
|
||||
case "player.block.action":
|
||||
if($data["block"] === 247){ //nether reactor
|
||||
$data["block"] = 9; //water source
|
||||
$data["meta"] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
105
example/SpawnChanger.php
Normal file
105
example/SpawnChanger.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
__PocketMine Plugin__
|
||||
name=SpawnChanger
|
||||
description=Change the spawn coordinates, or make it default for all players!
|
||||
version=0.0.1
|
||||
author=shoghicp
|
||||
class=SpawnChanger
|
||||
*/
|
||||
|
||||
|
||||
class SpawnChanger implements Plugin{
|
||||
private $api, $config, $path;
|
||||
public function __construct(ServerAPI $api, $server = false){
|
||||
$this->api = $api;
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$spawn = $this->api->level->getSpawn();
|
||||
$this->path = $this->api->plugin->createConfig($this, array(
|
||||
"spawnX" => $spawn["x"],
|
||||
"spawnY" => $spawn["y"],
|
||||
"spawnZ" => $spawn["z"],
|
||||
"custom-spawn" => false,
|
||||
"force-spawn" => false,
|
||||
));
|
||||
$this->config = $this->api->plugin->readYAML($this->path."config.yml");
|
||||
if($this->config["custom-spawn"] === false){
|
||||
$this->config["spawnX"] = $spawn["x"];
|
||||
$this->config["spawnY"] = $spawn["y"];
|
||||
$this->config["spawnZ"] = $spawn["z"];
|
||||
$this->api->plugin->writeYAML($this->path."config.yml", $this->config);
|
||||
}
|
||||
$this->api->addHandler("api.player.offline.get", array($this, "handle"), 15);
|
||||
$this->api->console->register("spawnchanger", "SpawnChanger init point managing", array($this, "command"));
|
||||
$this->api->console->register("spawn", "Teleports to spawn", array($this, "command"));
|
||||
}
|
||||
|
||||
public function __destruct(){
|
||||
|
||||
}
|
||||
|
||||
public function command($cmd, $args){
|
||||
switch($cmd){
|
||||
case "spawnchanger":
|
||||
switch(strtolower(array_shift($args))){
|
||||
case "force":
|
||||
$l = array_shift($args);
|
||||
if($l != "0" and $l != "1"){
|
||||
console("[SpawnChanger] Usage: /spawnchanger force <1 | 0>");
|
||||
}else{
|
||||
$this->config["force-spawn"] = $l == "0" ? false:true;
|
||||
if($this->config["force-spawn"] === true){
|
||||
console("[SpawnChanger] Forced spawn point");
|
||||
}else{
|
||||
console("[SpawnChanger] Freed pawn point");
|
||||
}
|
||||
$this->api->plugin->writeYAML($this->path."config.yml", $this->config);
|
||||
}
|
||||
break;
|
||||
case "set":
|
||||
$z = array_pop($args);
|
||||
$y = array_pop($args);
|
||||
$x = array_pop($args);
|
||||
if($x === null or $y === null or $z === null){
|
||||
console("[SpawnChanger] Usage: /spawnchanger set <x> <y> <z>");
|
||||
}else{
|
||||
$this->config["custom-spawn"] = true;
|
||||
$this->config["spawnX"] = (float) $x;
|
||||
$this->config["spawnY"] = (float) $y;
|
||||
$this->config["spawnZ"] = (float) $z;
|
||||
console("[SpawnChanger] Spawn point set at X ".$this->config["spawnX"]." Y ".$this->config["spawnY"]." Z ".$this->config["spawnZ"]);
|
||||
$this->api->plugin->writeYAML($this->path."config.yml", $this->config);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console("[SpawnChanger] Always spawn player in spawn point: /spawnchanger force <1 | 0>");
|
||||
console("[SpawnChanger] Set the spawn point: /spawnchanger set <x> <y> <z>");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "spawn":
|
||||
if($this->api->player->tppos(implode(" ", $args), $this->config["spawnX"], $this->config["spawnY"], $this->config["spawnZ"]) !== false){
|
||||
console("[SpawnChanger] Teleported to spawn!");
|
||||
}else{
|
||||
console("[SpawnChanger] Usage: /spawn <player>");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function handle(&$data, $event){
|
||||
switch($event){
|
||||
case "api.player.offline.get":
|
||||
if($this->config["force-spawn"] === true){
|
||||
$data["spawn"]["x"] = $this->config["spawnX"];
|
||||
$data["spawn"]["y"] = $this->config["spawnY"];
|
||||
$data["spawn"]["z"] = $this->config["spawnZ"];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
38
misc/block/plant/Sapling.php
Normal file
38
misc/block/plant/Sapling.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?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 Sapling{
|
||||
const OAK = 0;
|
||||
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);
|
||||
}
|
||||
}
|
60
misc/world/generator/object/tree/SmallTreeObject.php
Normal file
60
misc/world/generator/object/tree/SmallTreeObject.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
require_once("misc/world/generator/object/tree/TreeObject.php");
|
||||
|
||||
class SmallTreeObject extends TreeObject{
|
||||
private $totalHeight = 6;
|
||||
private $leavesHeight = 3;
|
||||
protected $radiusIncrease = 0;
|
||||
private $addLeavesVines = false;
|
||||
private $addLogVines = false;
|
||||
private $addCocoaPlants = false;
|
||||
|
||||
public function placeObject(LevelAPI $level, $x, $y, $z, $type){
|
||||
$level->setBlock($x, $y - 1, $z, 3, 0);
|
||||
$this->totalHeight += mt_rand(-1, 3);
|
||||
$this->leavesHeight += mt_rand(0, 1);
|
||||
for($yy = ($this->totalHeight - $this->leavesHeight); $yy < ($this->totalHeight + 1); ++$yy){
|
||||
$yRadius = ($yy - $this->totalHeight);
|
||||
$xzRadius = (int) (($this->radiusIncrease + 1) - $yRadius / 2);
|
||||
for($xx = -$xzRadius; $xx < ($xzRadius + 1); ++$xx){
|
||||
for($zz = -$xzRadius; $zz < ($xzRadius + 1); ++$zz){
|
||||
if((abs($xx) != $xzRadius or abs($zz) != $xzRadius) and $yRadius != 0){
|
||||
$level->setBlock($x + $xx, $y + $yy, $z + $zz, 18, $type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for($yy = 0; $yy < ($this->totalHeight - 1); ++$yy){
|
||||
$level->setBlock($x, $y + $yy, $z, 17, $type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
40
misc/world/generator/object/tree/TreeObject.php
Normal file
40
misc/world/generator/object/tree/TreeObject.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?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 TreeObject{
|
||||
|
||||
public static function growTree(LevelAPI $level, $block, $type){
|
||||
switch($type){
|
||||
default:
|
||||
case Sapling::OAK:
|
||||
$tree = new SmallTreeObject();
|
||||
break;
|
||||
}
|
||||
$tree->placeObject($level, $block[2][0], $block[2][1], $block[2][2], $type);
|
||||
}
|
||||
}
|
10
server.php
10
server.php
@ -23,7 +23,17 @@ while(true){
|
||||
if($server->start() !== true){
|
||||
break;
|
||||
}else{
|
||||
console("[INFO] Cleaning up...");
|
||||
hard_unset($server);
|
||||
$excludeList = array("GLOBALS", "_FILES", "_COOKIE", "_POST", "_GET", "excludeList");
|
||||
foreach(get_defined_vars() as $key => $value){
|
||||
if(!in_array($key, $excludeList)){
|
||||
$$key = null;
|
||||
unset($$key);
|
||||
}
|
||||
}
|
||||
$server = null;
|
||||
unset($server);
|
||||
console("[NOTICE] The server is restarting... (".gc_collect_cycles()." cycles collected)", true, true, 0);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
@echo off
|
||||
TITLE Pocket-Minecraft-PHP Server - by @shoghicp
|
||||
TITLE PocketMine-MP Server - by @shoghicp
|
||||
COLOR F0
|
||||
mode con: cols=90
|
||||
|
||||
@ -7,8 +7,8 @@ echo.
|
||||
echo -
|
||||
echo / \
|
||||
echo / \
|
||||
echo / POCKET \
|
||||
echo / MINECRAFT PHP \
|
||||
echo / PocketMine \
|
||||
echo / MP \
|
||||
echo ^|\ @shoghicp /^|
|
||||
echo ^|. \ / .^|
|
||||
echo ^| .. \ / .. ^|
|
||||
|
Reference in New Issue
Block a user