PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/pocketmine/network/Network.php

https://gitlab.com/Skull3x/ClearSky
PHP | 343 lines | 252 code | 40 blank | 51 comment | 9 complexity | a30e7424980dc73184f862346c884022 MD5 | raw file
  1. <?php
  2. /**
  3. * Network-related classes
  4. */
  5. namespace pocketmine\network;
  6. use pocketmine\network\protocol\AddEntityPacket;
  7. use pocketmine\network\protocol\AddItemEntityPacket;
  8. use pocketmine\network\protocol\AddPaintingPacket;
  9. use pocketmine\network\protocol\AddPlayerPacket;
  10. use pocketmine\network\protocol\AdventureSettingsPacket;
  11. use pocketmine\network\protocol\AnimatePacket;
  12. use pocketmine\network\protocol\BatchPacket;
  13. use pocketmine\network\protocol\ContainerClosePacket;
  14. use pocketmine\network\protocol\ContainerOpenPacket;
  15. use pocketmine\network\protocol\ContainerSetContentPacket;
  16. use pocketmine\network\protocol\ContainerSetDataPacket;
  17. use pocketmine\network\protocol\ContainerSetSlotPacket;
  18. use pocketmine\network\protocol\CraftingDataPacket;
  19. use pocketmine\network\protocol\CraftingEventPacket;
  20. use pocketmine\network\protocol\ChangeDimensionPacket;
  21. use pocketmine\network\protocol\DataPacket;
  22. use pocketmine\network\protocol\DropItemPacket;
  23. use pocketmine\network\protocol\FullChunkDataPacket;
  24. use pocketmine\network\protocol\Info;
  25. use pocketmine\network\protocol\SetEntityLinkPacket;
  26. use pocketmine\network\protocol\BlockEntityDataPacket;
  27. use pocketmine\network\protocol\EntityEventPacket;
  28. use pocketmine\network\protocol\ExplodePacket;
  29. use pocketmine\network\protocol\HurtArmorPacket;
  30. use pocketmine\network\protocol\Info as ProtocolInfo;
  31. use pocketmine\network\protocol\InteractPacket;
  32. use pocketmine\network\protocol\LevelEventPacket;
  33. use pocketmine\network\protocol\DisconnectPacket;
  34. use pocketmine\network\protocol\LoginPacket;
  35. use pocketmine\network\protocol\PlayStatusPacket;
  36. use pocketmine\network\protocol\TextPacket;
  37. use pocketmine\network\protocol\MoveEntityPacket;
  38. use pocketmine\network\protocol\MovePlayerPacket;
  39. use pocketmine\network\protocol\PlayerActionPacket;
  40. use pocketmine\network\protocol\MobArmorEquipmentPacket;
  41. use pocketmine\network\protocol\MobEquipmentPacket;
  42. use pocketmine\network\protocol\RemoveBlockPacket;
  43. use pocketmine\network\protocol\RemoveEntityPacket;
  44. use pocketmine\network\protocol\RemovePlayerPacket;
  45. use pocketmine\network\protocol\RespawnPacket;
  46. use pocketmine\network\protocol\SetDifficultyPacket;
  47. use pocketmine\network\protocol\SetEntityDataPacket;
  48. use pocketmine\network\protocol\SetEntityMotionPacket;
  49. use pocketmine\network\protocol\SetHealthPacket;
  50. use pocketmine\network\protocol\SetPlayerGameTypePacket;
  51. use pocketmine\network\protocol\SetSpawnPositionPacket;
  52. use pocketmine\network\protocol\SetTimePacket;
  53. use pocketmine\network\protocol\StartGamePacket;
  54. use pocketmine\network\protocol\TakeItemEntityPacket;
  55. use pocketmine\network\protocol\BlockEventPacket;
  56. use pocketmine\network\protocol\UpdateBlockPacket;
  57. use pocketmine\network\protocol\UseItemPacket;
  58. use pocketmine\network\protocol\PlayerListPacket;
  59. use pocketmine\network\protocol\PlayerInputPacket;
  60. use pocketmine\Player;
  61. use pocketmine\Server;
  62. use pocketmine\utils\Binary;
  63. use pocketmine\utils\MainLogger;
  64. class Network{
  65. public static $BATCH_THRESHOLD = 512;
  66. /** @deprecated */
  67. const CHANNEL_NONE = 0;
  68. /** @deprecated */
  69. const CHANNEL_PRIORITY = 1; //Priority channel, only to be used when it matters
  70. /** @deprecated */
  71. const CHANNEL_WORLD_CHUNKS = 2; //Chunk sending
  72. /** @deprecated */
  73. const CHANNEL_MOVEMENT = 3; //Movement sending
  74. /** @deprecated */
  75. const CHANNEL_BLOCKS = 4; //Block updates or explosions
  76. /** @deprecated */
  77. const CHANNEL_WORLD_EVENTS = 5; //Entity, level or tile entity events
  78. /** @deprecated */
  79. const CHANNEL_ENTITY_SPAWNING = 6; //Entity spawn/despawn channel
  80. /** @deprecated */
  81. const CHANNEL_TEXT = 7; //Chat and other text stuff
  82. /** @deprecated */
  83. const CHANNEL_END = 31;
  84. /** @var \SplFixedArray */
  85. private $packetPool;
  86. /** @var Server */
  87. private $server;
  88. /** @var SourceInterface[] */
  89. private $interfaces = [];
  90. /** @var AdvancedSourceInterface[] */
  91. private $advancedInterfaces = [];
  92. private $upload = 0;
  93. private $download = 0;
  94. private $name;
  95. public function __construct(Server $server){
  96. $this->registerPackets();
  97. $this->server = $server;
  98. }
  99. public function addStatistics($upload, $download){
  100. $this->upload += $upload;
  101. $this->download += $download;
  102. }
  103. public function getUpload(){
  104. return $this->upload;
  105. }
  106. public function getDownload(){
  107. return $this->download;
  108. }
  109. public function resetStatistics(){
  110. $this->upload = 0;
  111. $this->download = 0;
  112. }
  113. /**
  114. * @return SourceInterface[]
  115. */
  116. public function getInterfaces(){
  117. return $this->interfaces;
  118. }
  119. public function processInterfaces(){
  120. foreach($this->interfaces as $interface){
  121. try {
  122. $interface->process();
  123. }catch(\Exception $e){
  124. $logger = $this->server->getLogger();
  125. if(\pocketmine\DEBUG > 1){
  126. if($logger instanceof MainLogger){
  127. $logger->logException($e);
  128. }
  129. }
  130. $interface->emergencyShutdown();
  131. $this->unregisterInterface($interface);
  132. $logger->critical($this->server->getLanguage()->translateString("pocketmine.server.networkError", [get_class($interface), $e->getMessage()]));
  133. }
  134. }
  135. }
  136. /**
  137. * @param SourceInterface $interface
  138. */
  139. public function registerInterface(SourceInterface $interface){
  140. $this->interfaces[$hash = spl_object_hash($interface)] = $interface;
  141. if($interface instanceof AdvancedSourceInterface){
  142. $this->advancedInterfaces[$hash] = $interface;
  143. $interface->setNetwork($this);
  144. }
  145. $interface->setName($this->name);
  146. }
  147. /**
  148. * @param SourceInterface $interface
  149. */
  150. public function unregisterInterface(SourceInterface $interface){
  151. unset($this->interfaces[$hash = spl_object_hash($interface)],
  152. $this->advancedInterfaces[$hash]);
  153. }
  154. /**
  155. * Sets the server name shown on each interface Query
  156. *
  157. * @param string $name
  158. */
  159. public function setName($name){
  160. $this->name = (string) $name;
  161. foreach($this->interfaces as $interface){
  162. $interface->setName($this->name);
  163. }
  164. }
  165. public function getName(){
  166. return $this->name;
  167. }
  168. public function updateName(){
  169. foreach($this->interfaces as $interface){
  170. $interface->setName($this->name);
  171. }
  172. }
  173. /**
  174. * @param int $id 0-255
  175. * @param DataPacket $class
  176. */
  177. public function registerPacket($id, $class){
  178. $this->packetPool[$id] = new $class;
  179. }
  180. public function getServer(){
  181. return $this->server;
  182. }
  183. public function processBatch(BatchPacket $packet, Player $p){
  184. $str = zlib_decode($packet->payload, 1024 * 1024 * 64); //Max 64MB
  185. $len = strlen($str);
  186. $offset = 0;
  187. try{
  188. while($offset < $len){
  189. $pkLen = Binary::readInt(substr($str, $offset, 4));
  190. $offset += 4;
  191. $buf = substr($str, $offset, $pkLen);
  192. $offset += $pkLen;
  193. if(($pk = $this->getPacket(ord($buf{0}))) !== null){
  194. if($pk::NETWORK_ID === Info::BATCH_PACKET){
  195. throw new \InvalidStateException("Invalid BatchPacket inside BatchPacket");
  196. }
  197. $pk->setBuffer($buf, 1);
  198. $pk->decode();
  199. $p->handleDataPacket($pk);
  200. if($pk->getOffset() <= 0){
  201. return;
  202. }
  203. }
  204. }
  205. }catch(\Exception $e){
  206. if(\pocketmine\DEBUG > 1){
  207. $logger = $this->server->getLogger();
  208. if($logger instanceof MainLogger){
  209. $logger->debug("BatchPacket " . " 0x" . bin2hex($packet->payload));
  210. $logger->logException($e);
  211. }
  212. }
  213. }
  214. }
  215. /**
  216. * @param $id
  217. *
  218. * @return DataPacket
  219. */
  220. public function getPacket($id){
  221. /** @var DataPacket $class */
  222. $class = $this->packetPool[$id];
  223. if($class !== null){
  224. return clone $class;
  225. }
  226. return null;
  227. }
  228. /**
  229. * @param string $address
  230. * @param int $port
  231. * @param string $payload
  232. */
  233. public function sendPacket($address, $port, $payload){
  234. foreach($this->advancedInterfaces as $interface){
  235. $interface->sendRawPacket($address, $port, $payload);
  236. }
  237. }
  238. /**
  239. * Blocks an IP address from the main interface. Setting timeout to -1 will block it forever
  240. *
  241. * @param string $address
  242. * @param int $timeout
  243. */
  244. public function blockAddress($address, $timeout = 300){
  245. foreach($this->advancedInterfaces as $interface){
  246. $interface->blockAddress($address, $timeout);
  247. }
  248. }
  249. private function registerPackets(){
  250. $this->packetPool = new \SplFixedArray(256);
  251. $this->registerPacket(ProtocolInfo::LOGIN_PACKET, LoginPacket::class);
  252. $this->registerPacket(ProtocolInfo::PLAY_STATUS_PACKET, PlayStatusPacket::class);
  253. $this->registerPacket(ProtocolInfo::DISCONNECT_PACKET, DisconnectPacket::class);
  254. $this->registerPacket(ProtocolInfo::BATCH_PACKET, BatchPacket::class);
  255. $this->registerPacket(ProtocolInfo::TEXT_PACKET, TextPacket::class);
  256. $this->registerPacket(ProtocolInfo::SET_TIME_PACKET, SetTimePacket::class);
  257. $this->registerPacket(ProtocolInfo::START_GAME_PACKET, StartGamePacket::class);
  258. $this->registerPacket(ProtocolInfo::ADD_PLAYER_PACKET, AddPlayerPacket::class);
  259. $this->registerPacket(ProtocolInfo::REMOVE_PLAYER_PACKET, RemovePlayerPacket::class);
  260. $this->registerPacket(ProtocolInfo::ADD_ENTITY_PACKET, AddEntityPacket::class);
  261. $this->registerPacket(ProtocolInfo::REMOVE_ENTITY_PACKET, RemoveEntityPacket::class);
  262. $this->registerPacket(ProtocolInfo::ADD_ITEM_ENTITY_PACKET, AddItemEntityPacket::class);
  263. $this->registerPacket(ProtocolInfo::TAKE_ITEM_ENTITY_PACKET, TakeItemEntityPacket::class);
  264. $this->registerPacket(ProtocolInfo::MOVE_ENTITY_PACKET, MoveEntityPacket::class);
  265. $this->registerPacket(ProtocolInfo::MOVE_PLAYER_PACKET, MovePlayerPacket::class);
  266. $this->registerPacket(ProtocolInfo::REMOVE_BLOCK_PACKET, RemoveBlockPacket::class);
  267. $this->registerPacket(ProtocolInfo::UPDATE_BLOCK_PACKET, UpdateBlockPacket::class);
  268. $this->registerPacket(ProtocolInfo::ADD_PAINTING_PACKET, AddPaintingPacket::class);
  269. $this->registerPacket(ProtocolInfo::EXPLODE_PACKET, ExplodePacket::class);
  270. $this->registerPacket(ProtocolInfo::LEVEL_EVENT_PACKET, LevelEventPacket::class);
  271. $this->registerPacket(ProtocolInfo::BLOCK_EVENT_PACKET, BlockEventPacket::class);
  272. $this->registerPacket(ProtocolInfo::ENTITY_EVENT_PACKET, EntityEventPacket::class);
  273. $this->registerPacket(ProtocolInfo::MOB_EQUIPMENT_PACKET, MobEquipmentPacket::class);
  274. $this->registerPacket(ProtocolInfo::MOB_ARMOR_EQUIPMENT_PACKET, MobArmorEquipmentPacket::class);
  275. $this->registerPacket(ProtocolInfo::INTERACT_PACKET, InteractPacket::class);
  276. $this->registerPacket(ProtocolInfo::USE_ITEM_PACKET, UseItemPacket::class);
  277. $this->registerPacket(ProtocolInfo::PLAYER_ACTION_PACKET, PlayerActionPacket::class);
  278. $this->registerPacket(ProtocolInfo::HURT_ARMOR_PACKET, HurtArmorPacket::class);
  279. $this->registerPacket(ProtocolInfo::SET_ENTITY_DATA_PACKET, SetEntityDataPacket::class);
  280. $this->registerPacket(ProtocolInfo::SET_ENTITY_MOTION_PACKET, SetEntityMotionPacket::class);
  281. $this->registerPacket(ProtocolInfo::SET_ENTITY_LINK_PACKET, SetEntityLinkPacket::class);
  282. $this->registerPacket(ProtocolInfo::SET_HEALTH_PACKET, SetHealthPacket::class);
  283. $this->registerPacket(ProtocolInfo::SET_SPAWN_POSITION_PACKET, SetSpawnPositionPacket::class);
  284. $this->registerPacket(ProtocolInfo::ANIMATE_PACKET, AnimatePacket::class);
  285. $this->registerPacket(ProtocolInfo::RESPAWN_PACKET, RespawnPacket::class);
  286. $this->registerPacket(ProtocolInfo::DROP_ITEM_PACKET, DropItemPacket::class);
  287. $this->registerPacket(ProtocolInfo::CONTAINER_OPEN_PACKET, ContainerOpenPacket::class);
  288. $this->registerPacket(ProtocolInfo::CONTAINER_CLOSE_PACKET, ContainerClosePacket::class);
  289. $this->registerPacket(ProtocolInfo::CONTAINER_SET_SLOT_PACKET, ContainerSetSlotPacket::class);
  290. $this->registerPacket(ProtocolInfo::CONTAINER_SET_DATA_PACKET, ContainerSetDataPacket::class);
  291. $this->registerPacket(ProtocolInfo::CONTAINER_SET_CONTENT_PACKET, ContainerSetContentPacket::class);
  292. $this->registerPacket(ProtocolInfo::CRAFTING_DATA_PACKET, CraftingDataPacket::class);
  293. $this->registerPacket(ProtocolInfo::CRAFTING_EVENT_PACKET, CraftingEventPacket::class);
  294. $this->registerPacket(ProtocolInfo::ADVENTURE_SETTINGS_PACKET, AdventureSettingsPacket::class);
  295. $this->registerPacket(ProtocolInfo::BLOCK_ENTITY_DATA_PACKET, BlockEntityDataPacket::class);
  296. $this->registerPacket(ProtocolInfo::FULL_CHUNK_DATA_PACKET, FullChunkDataPacket::class);
  297. $this->registerPacket(ProtocolInfo::SET_DIFFICULTY_PACKET, SetDifficultyPacket::class);
  298. $this->registerPacket(ProtocolInfo::PLAYER_LIST_PACKET, PlayerListPacket::class);
  299. $this->registerPacket(ProtocolInfo::PLAYER_INPUT_PACKET, PlayerInputPacket::class);
  300. $this->registerPacket(ProtocolInfo::SET_PLAYER_GAMETYPE_PACKET, SetPlayerGameTypePacket::class);
  301. $this->registerPacket(ProtocolInfo::CHANGE_DIMENSION_PACKET, ChangeDimensionPacket::class);
  302. }
  303. }