├── LICENSE ├── README ├── chat.bat ├── chat.php ├── chat_help.php ├── chunk.php ├── client.php ├── command.php ├── dynmap.php ├── forking.php ├── functions.php ├── materials.php ├── nbt.class.php ├── packets.php ├── packets └── 03Chat.php ├── pstruct.php └── pstruct_modifier.php /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This program is free software: you can redistribute it and/or modify 2 | it under the terms of the GNU Lesser General Public License as published by 3 | the Free Software Foundation, either version 3 of the License, or 4 | (at your option) any later version. 5 | 6 | This program is distributed in the hope that it will be useful, 7 | but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 | GNU Lesser General Public License for more details. 10 | 11 | You should have received a copy of the GNU Lesser General Public License 12 | along with this program. If not, see . 13 | 14 | 15 | / \ 16 | / \ 17 | / MINECRAFT \ 18 | / PHP \ 19 | |\ CLIENT /| 20 | |. \ / .| 21 | | ´. \ / .´ | 22 | | ´. | .´ | 23 | | ´. | .´ | 24 | \ | / 25 | \ | / 26 | \ | / 27 | \ | / 28 | 29 | by @shoghicp 30 | 31 | 32 | 33 | WARNONG: This program is superseded by Minecraft PHP Client 2 34 | 35 | 36 | Run client.php with PHP-CLI 37 | 38 | Example: 39 | 40 | php client.php --help 41 | -------------------------------------------------------------------------------- /chat.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | php chat.php 3 | exit -------------------------------------------------------------------------------- /chat.php: -------------------------------------------------------------------------------- 1 | $say"; 13 | file_put_contents("chat.input",$say,FILE_APPEND); 14 | } 15 | ?> -------------------------------------------------------------------------------- /chat_help.php: -------------------------------------------------------------------------------- 1 | Pregunta detectada de '.$sender); 7 | if(/*(stripos($value,'comando') or stripos($value,'era') or stripos($value,'puedo') or stripos($value,'hago') or stripos($value,'voy') or stripos($value,'podr') or stripos($value,'es')) and */(stripos($value,'cuando') or stripos($value,'cual') or stripos($value,'que') or stripos($value,'para') or stripos($value,'algu') or stripos($value,'como') or stripos($value,'quien') or (stripos($value,'donde') and (stripos($value,'pued') or stripos($value,'podr'))) or stripos($value,'pued')) and !stripos($value,'porque') and !stripos($value,'por que')){ 8 | if(!stripos($value,' tu ') and !stripos($value,'te ') and !stripos($value,' me ')){ 9 | if((stripos($value,'admin') or stripos($value,' mod') or stripos($value,' op') or stripos($value,'staff')) and (stripos($value,'quien') or stripos($value,'cual'))){ 10 | /* Admins */ 11 | privateMessage('los moderadores de este servidor son Duendek86, Zaden, Kreador, susoboiro, creik, LoscoJones, Xerri92, milodescorpio. Dirigete a ellos si tienes problemas.',$sender); 12 | } 13 | if(stripos($value,'mcmmo') or stripos($value,'stats') or stripos($value,'abil') or stripos($value,'skill') or stripos($value,'drill') or stripos($value,'berserk')){ 14 | /* McMMO */ 15 | privateMessage('McMMO sirve para dar habilidades especiales tipicas de juegos MMO a Minecraft. Mas info con "/mcc"',$sender); 16 | } 17 | if(stripos($value,'curar') or stripos($value,'sanar')){ 18 | /* curacion */ 19 | privateMessage('puedes curarte en una Residence que pueda curar o comiendo comida. Puedes poner en tu Residence "/res set healing true" para autocurarte',$sender); 20 | } 21 | if(stripos($value,'cartel') and stripos($value,'color')){ 22 | /* Colores de carteles */ 23 | privateMessage('puedes poner colores al texto poniendo "&" mas un caracter del 1 a F antes del texto',$sender); 24 | } 25 | if(stripos($value,'veteran') and (stripos($value,'como') or stripos($value,'cuando') or stripos($value,'cuanto'))){ 26 | /* Veterano */ 27 | $text = curl_get('http://mespduendedreams.com/test.php'); 28 | $vetearray = explode('',$text); 29 | foreach($vetearray as $text){ 30 | if(stripos($text,$sender)){ 31 | $days = str_replace(array($sender,' ','','','','',"\r","\n"),array('','','','','','','',''),$text); 32 | break; 33 | } 34 | } 35 | if($days>=30){ 36 | privateMessage('ya eres veterano. Actualmente has pasado '.$days.' dias en el servidor',$sender); 37 | }else{ 38 | privateMessage('seras veterano cuando hayas pasado 30 dias diferentes en el servidor. Actualmente has pasado '.$days.' dias en el servidor',$sender); 39 | } 40 | } 41 | if(stripos($value,'vip')){ 42 | /* Vips */ 43 | privateMessage('los VIPs tienen acceso a mas comandos, y una atencion mas personalizada. Puedes ser VIP donando al servidor. Mas info en el foro',$sender); 44 | } 45 | if(stripos($value,'comando')){ 46 | /* Comandos */ 47 | privateMessage('los comandos que puedes utilizar son (con una barra "/" delante): spawn, home, list, lwc, money, sell, buy, mail, msg, helpop, stats',$sender); 48 | } 49 | if(stripos($value,'materia')){ 50 | /* Materiales */ 51 | privateMessage('lo mejor que puedes hacer es ir a una zona algo alejada y talar arboles. Luego replantalos. Tambien puedes comprar.',$sender); 52 | } 53 | if(stripos($value,'/res') or stripos($value,'residen') or (stripos($value,'terren') or (stripos($value,'prote') and stripos($value,'casa')))){ 54 | /* Residence */ 55 | privateMessage('marca con el hacha de madera la zona. Luego pon "/res create nombre". Mas info con el comando "/res ?"',$sender); 56 | } 57 | if((stripos($value,'prote') or stripos($value,'bloque') or (stripos($value,'magical') and stripos($value,'spell')) or stripos($value,'lwc') or (stripos($value,' no ') and stripos($value,'rob'))) and !stripos($value,' bloque')){ 58 | /* LWC */ 59 | privateMessage('puedes proteger cofres, puertas, dispensadores, hornos y carteles con LWC. Pon primero "/cremove" y luego "/cprivate". Mas info con "/lwc"',$sender); 60 | } 61 | if(stripos($value,' ts') or stripos($value,'turnstile') or (stripos($value,'boton') and (stripos($value,'pag') or stripos($value,'cobr') or stripos($value,'cost') or stripos($value,'cueste')))){ 62 | /* TurnStile*/ 63 | privateMessage('apunta a una valla y pon "/ts make nombre". Luego apunta el boton y pon "/ts link nombre". Mas info con "/ts"',$sender); 64 | } 65 | if(stripos($value,'pay') and stripos($value,'day')){ 66 | /* PayDay */ 67 | privateMessage('el Pay Day te da dinero al inicio de cada hora que estes conectado. Puedes ver la cantidad de Mesps que te da con "/pd"',$sender); 68 | } 69 | if(stripos($value,'lobo') and (stripos($value,'hay') or stripos($value,'enc') or stripos($value,'sale'))){ 70 | /* Lobos */ 71 | privateMessage('los lobos se encuentran en la Taiga y los Bosques. Para mayor seguridad, ves a una zona con nieve.',$sender); 72 | } 73 | if(stripos($value,'diner') or (stripos($value,'mesp') and !stripos($value,'algu') and !stripos($value,'city') and !stripos($value,'3') and !stripos($value,'stack') and !stripos($value,'unidad') and !stripos($value,'ciud') and !stripos($value,'nuev')) or stripos($value,'credit') or stripos($value,'money')){ 74 | /* Dinero */ 75 | if(stripos($value,'gan') or stripos($value,'cons') or stripos($value,'rico') or stripos($value,'mas')){ 76 | privateMessage('puedes ganar dinero vendiendo bloques en tiendas, o con el Pay Day. Al inicio de cada hora te daran mesps',$sender); 77 | }else{ 78 | privateMessage('para saber cuantos Mesps tienes pon "/money". Mas info con "/money ?"',$sender); 79 | } 80 | } 81 | if(stripos($value,' spawn') or stripos($value,' inicio')){ 82 | /* Spawn */ 83 | privateMessage('para ir al Spawn pon el comando "/spawn" y espera 5 segundos sin moverte',$sender); 84 | } 85 | if(stripos($value,'pued') and (stripos($value,'constr') or stripos($value,'terreno') or stripos($value,'parce') or stripos($value,'casa'))){ 86 | /* Construir casa */ 87 | privateMessage('puedes construir donde no molestes a nadie. Tambien puedes alquilar una parcela en una ciudad',$sender); 88 | } 89 | if(((stripos($value,'hay') and stripos($value,'tienda')) or stripos($value,'compr')) and !stripos($value,'terren') and !stripos($value,'casa') and !stripos($value,'parcel') and !stripos($value,'compras')){ 90 | /* Tiendas */ 91 | privateMessage('puedes comprar en las tiendas. Para ver la lista, pon "bot tiendas"',$sender); 92 | } 93 | if(stripos($value,'casa') or stripos($value,'home')){ 94 | /* Home */ 95 | /*if(stripos($value,'invit') or stripos($value,'otr')){ 96 | //invitar 97 | privateMessage('para invitar a otra persona a tu casa, pon "/home invite nombre"',$sender); 98 | }else*/if(stripos($value,'poner') or stripos($value,'volver') or stripos($value,'voy') or stripos($value,'ir') or stripos($value,'vuelvo')){ 99 | /* poner la casa, volver */ 100 | privateMessage('puedes establecer tu casa donde estas con "/sethome". Luego puedes volver con "/home"',$sender); 101 | } 102 | } 103 | if(stripos($value,'lava') and stripos($value,'infin') and !stripos($value,'obsi')){ 104 | privateMessage('no se puede hacer lava infinita.',$sender); 105 | } 106 | if(stripos($value,'afk')){ 107 | privateMessage('AFK significa Away From Keyboard, es decir, lejos del teclado.',$sender); 108 | } 109 | if(stripos($value,'foro')){ 110 | privateMessage('el foro de este servidor es http://minecraft-esp.com/',$sender); 111 | } 112 | if((stripos($value,'podria') or stripos($value,'puedo')) and stripos($value,'robar')){ 113 | privateMessage('NO',$sender); 114 | } 115 | } 116 | if((stripos($value,'progra') or stripos($value,'cre') or stripos($value,'hizo'))){ 117 | privateMessage('me creo shoghicp. Estoy programado en PHP',$sender); 118 | } 119 | if((stripos($value,'llama') or stripos($value,'nombre') or stripos($value,'cread') or stripos($value,'eres'))){ 120 | privateMessage('me llamo Bot Ayuda, y estoy aqui para ayudarte en tu inicio.',$sender); 121 | } 122 | if((stripos($value,' dia') or stripos($value,'noche') or stripos($value,'hora') or stripos($value,'tiempo'))){ 123 | privateMessage('son las '.((intval($ginfo["time"]/1000+6) % 24)).':'.str_pad(intval(($ginfo["time"]/1000-floor($ginfo["time"]/1000))*60),2,"0",STR_PAD_LEFT).' y es de '.(($ginfo["time"] > 23100 or $ginfo["time"] < 12900) ? "dia":"noche"),$sender); 124 | } 125 | } 126 | } 127 | if(stripos($value,'gay')){ 128 | privateMessage('soy un robot. No se que opinaras tu sobre ti.',$sender); 129 | } 130 | 131 | ?> -------------------------------------------------------------------------------- /chunk.php: -------------------------------------------------------------------------------- 1 | array(), 10 | "meta" => array(), 11 | "blight" => array(), 12 | "slight" => array(), 13 | ); 14 | //Loop over 16x16x16 chunks in the 16x256x16 column 15 | $offset = 0; 16 | $read = 4096; 17 | for ($i=0;$i<16;$i++) { 18 | //If the bitmask indicates this chunk has been sent... 19 | if ($bitmask & 1 << $i) { 20 | //Read data... 21 | $cubic_chunk_data = substr($data, $offset, $read); //2048 for the other arrays, where you'll need to split the data 22 | $offset += $read; 23 | $read = 2048; 24 | $len = strlen($cubic_chunk_data); 25 | for($j=0; $j<$len; $j++) { 26 | //Retrieve x,y,z and data from each element in cubic_chunk_array 27 | 28 | //Byte arrays 29 | $x = $chunk_x*16 + $j & 0x0F; 30 | $y = $i*16 + $j >> 8; 31 | $z = $chunk_z*16 + ($j & 0xF0) >> 4; 32 | $data = $cubic_chunk_data[$j]; 33 | 34 | //Nibble arrays 35 | $data1 = $cubic_chunk_data[$j] & 0x0F; 36 | $data2 = $cubic_chunk_data[$j] >> 4; 37 | 38 | $k = 2*$j; 39 | $x1 = $chunk_x*16 + $k & 0x0F; 40 | $y1 = $i*16 + $k >> 8; 41 | $z1 = $chunk_z*16 + ($k & 0xF0) >> 4; 42 | 43 | $k++; 44 | $x2 = $chunk_x*16 + $k & 0x0F; 45 | $y2 = $i*16 + $k >> 8; 46 | $z2 = $chunk_z*16 + ($k & 0xF0) >> 4; 47 | } 48 | } 49 | } 50 | 51 | } 52 | 53 | function old_chunk_read($data, $X, $Z, $onlyBlocks = false){ 54 | $totalOffset = 0; 55 | $size = strlen($data); 56 | $chunkBlocks = 16 * 16 * 128; //32768 57 | $chunk = array( 58 | "block" => array(), 59 | "meta" => array(), 60 | "blight" => array(), 61 | "slight" => array(), 62 | ); 63 | $byte = ""; 64 | $half = false; 65 | foreach($chunk as $type => $arr){ 66 | if($onlyBlocks == true and $type != "block"){ 67 | break; 68 | } 69 | for($offset=0;$offset<$chunkBlocks;++$offset){ 70 | if($type=="block"){ 71 | /*$x = $X + ($offset >> 11); 72 | $y = $offset & 0x7F; 73 | $z = $Z + (($offset & 0x780) >> 7 );*/ 74 | $chunk[$type][] = read_byte($data{$totalOffset+$offset},false); 75 | }else{ 76 | /*$x = $X + (($offset/2) >> 11); 77 | $y = ($offset/2) & 0x7F; 78 | $z = $Z + ((($offset/2) & 0x780) >> 7 );*/ 79 | $byte = $data{$totalOffset+($offset/2)}; 80 | $chunk[$type][] = read_byte($byte & 0x0F,false); 81 | $chunk[$type][] = read_byte(($byte >> 4) & 0x0F,false); 82 | ++$offset; 83 | } 84 | } 85 | $totalOffset += $offset; 86 | } 87 | return $onlyBlocks == true ? $chunk["block"]:$chunk; 88 | } 89 | 90 | function chunk_add($data, $x, $z){ 91 | global $chunks; 92 | $x /= 16; 93 | $z /= 16; 94 | $chunks[$x."|".$z] = gzinflate(substr($data,2)); 95 | return true; 96 | } 97 | 98 | function chunk_clean($x, $z){ 99 | global $chunks; 100 | $x /= 16; 101 | $z /= 16; 102 | if(!isset($chunks[$X."|".$Z])){ 103 | return false; 104 | } 105 | $chunks[$x."|".$z] = substr($chunks[$x."|".$z],0,16 + 16 * 128); 106 | return true; 107 | } 108 | 109 | function chunk_load($x, $z){ 110 | global $chunks, $tchunk; 111 | if(!isset($tchunk[$x."|".$z]) and isset($chunks[$x."|".$z])){ 112 | 113 | $tchunk[$x."|".$z] = chunk_read($chunks[$x."|".$z],$x,$z,true); 114 | return true; 115 | }elseif(isset($tchunk[$x."|".$z])){ 116 | return true; 117 | }else{ 118 | return false; 119 | } 120 | } 121 | 122 | function chunk_get_radius($x,$y,$z,$r=4){ 123 | $r = abs($r); 124 | return chunk_get_zone($x-$r,$y-$r,$z-$r,$x+$r,$y+$r,$z+$r); 125 | } 126 | 127 | function chunk_get_zone($x1,$z1,$y1, $x2,$z2,$y2){ 128 | if($x1>$x2 or $y1>$y2 or $z1>$z2){ 129 | return false; 130 | } 131 | $blocks = array(); 132 | for($x=$x1;$x<=$x2;++$x){ 133 | for($y=$y1;$y<=$y2;++$y){ 134 | for($z=$z1;$z<=$z2;++$z){ 135 | $blocks[$x][$y][$z] = chunk_get_block($x,$y,$z); 136 | } 137 | } 138 | } 139 | return $blocks; 140 | } 141 | 142 | function chunk_get_block($x,$y,$z){ 143 | global $chunks, $protocol; 144 | if($protocol <= 23){ 145 | return old_chunk_get_block($x,$y,$z); 146 | } 147 | $x = intval($x); 148 | $y = intval($y); 149 | $z = intval($z); 150 | $X = intval($x / 16); 151 | $Z = intval($z / 16); 152 | 153 | $x %= 16; 154 | $y %= 128; 155 | $z %= 16; 156 | 157 | if(!isset($chunks[$X."|".$Z])){ 158 | return 0x00; //AIR 159 | } 160 | $index = $y + ($z * 128) + ($x * 128 * 16); 161 | return read_byte($chunks[$X."|".$Z]{$index},false); 162 | } 163 | 164 | function old_chunk_get_block($x,$y,$z){ 165 | global $chunks; 166 | $x = intval($x); 167 | $y = intval($y); 168 | $z = intval($z); 169 | $X = intval($x / 16); 170 | $Z = intval($z / 16); 171 | 172 | $x %= 16; 173 | $y %= 128; 174 | $z %= 16; 175 | 176 | if(!isset($chunks[$X."|".$Z])){ 177 | return 0x00; //AIR 178 | } 179 | $index = $y + ($z * 128) + ($x * 128 * 16); 180 | return read_byte($chunks[$X."|".$Z]{$index},false); 181 | } 182 | 183 | function chunk_edit_block($x,$y,$z,$value){ 184 | global $chunks; 185 | $x = intval($x); 186 | $y = intval($y); 187 | $z = intval($z); 188 | $X = intval($x / 16); 189 | $Z = intval($z / 16); 190 | $x %= 16; 191 | $y %= 128; 192 | $z %= 16; 193 | 194 | if(!isset($chunks[$X."|".$Z])){ 195 | return false; 196 | } 197 | $index = $y + ($z * 128) + ($x * 128 * 16); 198 | $chunks[$X."|".$Z]{$index} = write_byte($value,false); 199 | return true; 200 | } 201 | 202 | ?> 203 | -------------------------------------------------------------------------------- /client.php: -------------------------------------------------------------------------------- 1 | 29, 26 | "1.2.4" => 29, 27 | "1.2.3" => 28, 28 | "1.2.2" => 28, 29 | "1.2.1" => 28, 30 | "1.2.0" => 28, 31 | "1.1.0" => 23, 32 | "1.0.1" => 22, 33 | "1.0.0" => 22, 34 | "b1.8.1" => 17, 35 | "b1.8" => 17, 36 | "b1.7.3" => 14, 37 | "b1.7.2" => 14, 38 | "b1.7_01" => 14, 39 | "b1.7" => 14, 40 | "b1.6.6" => 12, 41 | "b1.6" => 12, 42 | ); 43 | 44 | $lastver = "1.2.5"; 45 | 46 | 47 | echo << Server to connect, default "127.0.0.1" 82 | \tport => Port to connect, default "25565" 83 | \tversion => Version of server, default "$lastver" 84 | \tprotocol 85 | \tusername => username to use in server and minecraft.net (if PREMIUM), default "Player" 86 | \tpassword => password to use in minecraft.net, if PREMIUM 87 | \tsecure => use HTTPS to connect to minecraft.net 88 | \tdump => dump map chunks (experimental! [no crash]) 89 | \tlog => write a log in packets.log, console.log and raw.log, or if you specify an option, only one 90 | \tping => ping (packet 0xFE) a server, and returns info 91 | \thide => hides elements here from console, separated by a comma (sign, chat, nspawn, state, position) 92 | \tcrazyness => moves around doing things (moves head) (values: mad, normal) 93 | \towner => set owner (follow, commands) 94 | \tonly-food => only accept food as inventory items (default false) 95 | \tdynmap => enables dynmap if a port is given (default false) 96 | \tthreading => enables threading, only on linux BETA (default false) 97 | 98 | Example: 99 | php {$argv[0]} --server=127.0.0.1 --username=Player --version=b1.8.1 --hide=sign,chat 100 | 101 | USAGE; 102 | die(); 103 | } 104 | $server = arg("server", "127.0.0.1"); 105 | $port = arg("port", "25565"); 106 | $username = arg("username", "Player"); 107 | $password = arg("password", ""); 108 | $secure = arg("secure", false); 109 | $version = arg("version", $lastver); 110 | $protocol = intval(arg("protocol", $versions[$lastver])); 111 | 112 | if(arg("log", false) != false){ 113 | if(arg("log", false) == "raw"){ 114 | file_put_contents($path."raw_recv.log", ""); 115 | file_put_contents($path."raw_sent.log", ""); 116 | } 117 | file_put_contents($path."packets.log", ""); 118 | file_put_contents($path."console.log", ""); 119 | } 120 | if($version != $lastver){ 121 | $protocol = $versions[$version]; 122 | } 123 | 124 | $colorchar = "\xa7"; 125 | 126 | } 127 | include("materials.php"); 128 | include("pstruct.php"); 129 | include("pstruct_modifier.php"); 130 | 131 | if(!defined("CLIENT_LOADED")){ 132 | 133 | $logged_in = false; 134 | $connected = true; 135 | 136 | $login = array("last_version" => "", "download_ticket" => "", "username" => $username, "session_id" => ""); 137 | 138 | } 139 | 140 | $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 141 | 142 | if(@socket_connect($sock, $server, $port) === false){ 143 | console("[-] Couldn't connect to server"); 144 | die(); 145 | } 146 | socket_set_block($sock); 147 | 148 | socket_set_option($sock, SOL_SOCKET, SO_KEEPALIVE, 1); 149 | socket_set_option($sock, SOL_TCP, TCP_NODELAY, 1); 150 | 151 | if(FORKING && arg("threading", false) != false){ 152 | console("[+] Threading enabled"); 153 | include_once("forking.php"); 154 | }else{ 155 | define("THREADED", false); 156 | } 157 | 158 | if(arg("ping", false) != false){ 159 | console("[+] Pinging ".$server.":".$port." ..."); 160 | write_packet("fe"); 161 | buffer(); 162 | $packet = parse_packet(); 163 | if($packet["pid"] == "ff"){ 164 | $info = explode($colorchar,$packet["message"]); 165 | console("[*] Name: ".$info[0]); 166 | console("[*] Online players: ".$info[1]); 167 | console("[*] Max players: ".$info[2]); 168 | } 169 | die(); 170 | } 171 | 172 | 173 | $hide = explode(",", arg("hide", "")); 174 | 175 | /* 176 | 177 | ------------------ AUTH START ----------------- 178 | 179 | */ 180 | 181 | console("[*] Sending Handshake"); 182 | write_packet("02", array( 183 | "username" => $username, 184 | "server" => $server.":".$port, 185 | )); 186 | 187 | buffer(); 188 | $packet = parse_packet(); //Wait for Server Handshake 189 | 190 | if($packet["server_id"] != "-" and $packet["server_id"] != "+"){ 191 | console("[*] Server is Premium (SID: ".$packet["server_id"].")"); 192 | if($packet["server_id"] == "" or strpos($packet["server_id"], "&") !== false){ 193 | console("[!] NAME SPOOF DETECTED"); 194 | } 195 | if(!defined("CLIENT_LOADED")){ 196 | if($secure !== false){ 197 | $proto = "https"; 198 | console("[+] Using secure HTTPS connection"); 199 | }else{ 200 | $proto = "http"; 201 | } 202 | 203 | $response = curl_get($proto."://login.minecraft.net/?user=".$username."&password=".$password."&version=12"); 204 | switch($response){ 205 | case 'Bad Login': 206 | console("[-] Bad login"); 207 | die(); 208 | break; 209 | case "Old Version": 210 | console("[-] Old Version"); 211 | die(); 212 | break; 213 | default: 214 | $content = explode(":",$response); 215 | if(!is_array($content)){ 216 | console("[-] Unknown Login Error: \"".$response."\""); 217 | die(); 218 | } 219 | $login["last_version"] = $content[0]; 220 | $login["download_ticket"] = $content[1]; 221 | $login["username"] = $content[2]; 222 | $username = $content[2]; 223 | $login["session_id"] = $content[3]; 224 | console("[+] Logged into minecraft.net"); 225 | break; 226 | } 227 | } 228 | $res = curl_get("http://session.minecraft.net/game/joinserver.jsp?user=".$username."&sessionId=".$login["session_id"]."&serverId=".$packet["server_id"]); //User check 229 | if($res != "OK"){ 230 | console("[-] Error in User Check: \"".$res."\""); 231 | die(); 232 | } 233 | }else{ 234 | console("[*] Server is not Premium"); 235 | } 236 | console("[*] Sending Login Request"); 237 | 238 | write_packet("01",array( 239 | "version" => $protocol, 240 | "username" => $username, 241 | )); 242 | 243 | socket_set_nonblock($sock); 244 | define('CLIENT_LOADED', true); 245 | /* 246 | ---------- AUTH FINALIZED -------------- 247 | */ 248 | 249 | $position_packet = false; 250 | $next = 0; 251 | $start = $next; 252 | $moving = 0; 253 | $chunks = array(); 254 | $tchunk = array(); 255 | $ginfo = array( 256 | "eid" => 0, 257 | "seed" => 0, 258 | "dimension" => 0, 259 | "difficulty" => 0, 260 | "level_type" => "DEFAULT", 261 | "mode" => 0, 262 | "height" => 128, 263 | "crouch" => 0, 264 | "jump" => 0, 265 | "health" => 20, 266 | "food" => 20, 267 | "timer" => array( 268 | "restart" => time() + RESTART_TIME, 269 | ), 270 | "state" => array(), 271 | "time" => 0, 272 | "follow" => 0, 273 | "fly" => false, 274 | "inventory" => array(), 275 | "attack" => false, 276 | "aura" => false, 277 | "owner" => array( 278 | "name" => arg("owner", "shoghicp"), 279 | ), 280 | ); 281 | $entities = array(); 282 | $players = array(); 283 | $permissions = array( 284 | $ginfo["owner"]["name"] => 3, 285 | /* 286 | If you want some mods for the bot, add usernames here 287 | */ 288 | $username => 3, 289 | "susoboiro" => 2, 290 | "LoscoJones" => 2, 291 | "milodescorpio" => 2, 292 | "Duendek86" => 2, 293 | "kopron" => 2, 294 | "creik" => 2, 295 | "Sir_Pinkata" => 2, 296 | ); 297 | $recorder = array("mode" => "", "name" => "", "positions" => ""); 298 | $restart = false; 299 | 300 | 301 | while($sock and $restart == false){ 302 | $time = microtime(true); 303 | if(strlen($buffer) > 0){ 304 | $packet = parse_packet(); 305 | switch($packet["pid"]){ 306 | case "00": 307 | write_packet("00",$packet); 308 | break; 309 | case "01": 310 | console("[+] Login Request accepted"); 311 | console("[*] EID: ".$packet["eid"]); 312 | console("[*] Seed: ".$packet["seed"]); 313 | $ginfo["eid"] = $packet["eid"]; 314 | $ginfo["seed"] = $packet["seed"]; 315 | $ginfo["level_type"] = $packet["level_type"]; 316 | $ginfo["dimension"] = $packet["dimension"]; 317 | $ginfo["difficulty"] = $packet["difficulty"]; 318 | $ginfo["mode"] = $packet["mode"]; 319 | $ginfo["height"] = $packet["height"]; 320 | if($protocol>=17){ 321 | console("[*] Gamemode: ".($packet["mode"]==0 ? "survival":"creative")); 322 | console("[*] Max players: ".$packet["max_players"]); 323 | } 324 | $logged_in = true; 325 | break; 326 | case "03": 327 | $res = Packet03Chat($packet); 328 | if(!in_array("chat",$hide) and $res != false){ 329 | console($res); 330 | } 331 | break; 332 | 333 | case "04": 334 | $packet['time'] %= 24000; 335 | $ginfo["time"] = $packet['time']; 336 | if(!in_array("time",$hide)){ 337 | console("[*] Time: ".((intval($packet['time']/1000+6) % 24)).':'.str_pad(intval(($packet['time']/1000-floor($packet['time']/1000))*60),2,"0",STR_PAD_LEFT).', '.(($packet['time'] > 23100 or $packet['time'] < 12900) ? "day":"night")." \r", false, false); 338 | } 339 | break; 340 | case "08": 341 | if($ginfo["health"] != $packet["health"] or $ginfo["food"] != $packet["food"]){ 342 | console("[*] Health: ".$packet["health"].", Food: ". $packet["food"]); 343 | } 344 | $ginfo["health"] = $packet["health"]; 345 | $ginfo["food"] = $protocol <= 14 ? $packet["health"]:$packet["food"]; 346 | if($ginfo["health"]<=0){ 347 | write_packet("09", $ginfo); 348 | $messages = array( 349 | "Nooo!!!", 350 | "Por que??", 351 | "Solo hice lo que me pedian!", 352 | "Noooouuu!", 353 | ); 354 | Message($messages[count($messages)-1]); 355 | console("[-] Death and respawn"); 356 | } 357 | break; 358 | case "0d": 359 | if(!in_array("position",$hide)){ 360 | console("[+] Got position: (".$packet["x"].",".$packet["y"].",".$packet["z"].")"); 361 | } 362 | /*if(!$position_packet and arg("spout", false) != false){ 363 | write_packet("12", array( 364 | "eid" => -42, 365 | "animation" => 1, 366 | )); 367 | }*/ 368 | if($moving == 0 or $moving >= 2){ 369 | write_packet("0d",$packet); 370 | $position_packet = $packet; 371 | $moving = 0; 372 | } 373 | 374 | 375 | break; 376 | case "14": 377 | if(!in_array("nspawn",$hide)){ 378 | console("[+] Player \"".$packet["name"]."\" (EID: ".$packet["eid"].") spawned at (".$packet["x"].",".$packet["y"].",".$packet["z"].")"); 379 | } 380 | if(isset($permissions[$packet["name"]]) and $permissions[$packet["name"]] > 1){ 381 | if($ginfo["owner"]["name"] == $packet["name"]){ 382 | $ginfo["owner"]["eid"] = $packet["eid"]; 383 | } 384 | privateMessage("Hola ".$packet["name"].". Eres ".($permissions[$packet["name"]] == 2 ? "moderador":"administrador")." de ".$username, $packet["name"]); 385 | } 386 | $players[$packet["name"]] = $packet["eid"]; 387 | case "17": 388 | case "18": 389 | $entities[$packet["eid"]]["type"] = $packet["type"]; 390 | $entities[$packet["eid"]]["x"] = $packet["x"]; 391 | $entities[$packet["eid"]]["y"] = $packet["y"]; 392 | $entities[$packet["eid"]]["z"] = $packet["z"]; 393 | break; 394 | case "1d": 395 | unset($entities[$packet["eid"]]); 396 | if(in_array($packet["eid"], $players)){ 397 | foreach($players as $name => $eid){ 398 | if($eid == $packet["eid"]){ 399 | unset($players[$name]); 400 | break; 401 | } 402 | } 403 | } 404 | break; 405 | case "1f": 406 | case "21": 407 | $entities[$packet["eid"]]["x"] += $packet["dX"]; 408 | $entities[$packet["eid"]]["y"] += $packet["dY"]; 409 | $entities[$packet["eid"]]["z"] += $packet["dZ"]; 410 | 411 | break; 412 | case "22": 413 | $entities[$packet["eid"]]["x"] = $packet["x"]; 414 | $entities[$packet["eid"]]["y"] = $packet["y"]; 415 | $entities[$packet["eid"]]["z"] = $packet["z"]; 416 | break; 417 | case "33": 418 | if($protocol <= 23){ 419 | if($packet["xS"] == 15 and $packet["yS"] == 127 and $packet["zS"] == 15){ 420 | if(THREADED){ 421 | fork_chunk($packet, 33); 422 | }else{ 423 | chunk_add($packet["chunk"], $packet["x"], $packet["z"]); 424 | chunk_clean($packet["x"], $packet["z"]); 425 | } 426 | } 427 | } 428 | break; 429 | case "35": 430 | if($protocol <= 23){ 431 | if(THREADED){ 432 | fork_chunk($packet, 35); 433 | }else{ 434 | chunk_edit_block($packet["x"],$packet["y"],$packet["z"],$packet["type"]); 435 | } 436 | } 437 | break; 438 | case "46"; 439 | if(!in_array("state",$hide)){ 440 | switch($packet["reason"]){ 441 | case 0: 442 | $m = "Invalid bed"; 443 | break; 444 | case 1: 445 | $m = "Started raining"; 446 | break; 447 | case 2: 448 | $m = "Ended raining"; 449 | break; 450 | case 3: 451 | $m = "Gamemode changed: ".($packet["mode"]==0 ? "survival":"creative"); 452 | break; 453 | case 4: 454 | $m = "Entered credits"; 455 | break; 456 | } 457 | console("[*] ".$m); 458 | } 459 | break; 460 | case "67": 461 | if($packet["wid"] == 0){ 462 | $ginfo["inventory"][$packet["slot"]] = $packet["sdata"][0]; 463 | } 464 | break; 465 | 466 | case "68": 467 | if($packet["wid"] == 0){ 468 | foreach($packet["sdata"] as $i => $slot){ 469 | $ginfo["inventory"][$i] = $slot; 470 | } 471 | } 472 | break; 473 | case "82": 474 | if(!in_array("sign",$hide)){ 475 | console("[*] Sign at (".$packet["x"].",".$packet["y"].",".$packet["z"].")".PHP_EOL.implode(PHP_EOL,$packet["text"])); 476 | } 477 | break; 478 | case "ff": 479 | console("[-] Kicked from server, \"".$packet["message"]."\""); 480 | socket_close($sock); 481 | die(); 482 | break; 483 | } 484 | }else{ 485 | buffer(); 486 | } 487 | 488 | $do = false; 489 | /*if($next <= $time and $position_packet !== false){ 490 | write_packet("0a", array( 491 | "ground" => true, 492 | )); 493 | $do = true; 494 | }*/ 495 | 496 | if($next <= $time and $time%32==0 and intval(arg("dynmap", false)) > 0){ 497 | foreach(DynMapCoords() as $player){ 498 | if(!isset($players[$player["name"]]) or $players[$player["name"]] == md5($player["name"])){ 499 | $players[$player["name"]] = md5($player["name"]); 500 | $entities[md5($player["name"])] = $player; 501 | } 502 | } 503 | } 504 | if($next <= $time){ 505 | $input = file_get_contents("chat.input");file_put_contents("chat.input", ""); 506 | foreach(explode("\n", $input) as $in){ 507 | $in = trim($in); 508 | if($in == ""){ 509 | continue; 510 | } 511 | Message($in); 512 | console("[+] INPUT: ".$in); 513 | } 514 | } 515 | if($ginfo["aura"] == true and $position_packet !== false){ 516 | $att = false; 517 | foreach($entities as $eid => $ent){ 518 | $xD = abs($position_packet["x"] - $ent["x"]); 519 | $yD = abs($position_packet["y"] - $ent["y"]); 520 | $zD = abs($position_packet["z"] - $ent["z"]); 521 | if(pow(pow($xD,2) + pow($yD,2) + pow($zD,2),1/3) <= 7){ 522 | write_packet("07", array( 523 | "eid" => $ginfo["eid"], 524 | "target" => $eid, 525 | "left" => true, 526 | )); 527 | $att = true; 528 | } 529 | } 530 | if($att == true){ 531 | write_packet("12", array( 532 | "eid" => $ginfo["eid"], 533 | "animation" => 1, 534 | )); 535 | } 536 | } 537 | 538 | if($next <= $time and $position_packet !== false){ 539 | if($recorder["mode"] == "record"){ 540 | $recorder["positions"][] = $entities[$ginfo["follow"]]; 541 | } 542 | if($recorder["mode"] == "play"){ 543 | if(isset($recorder["positions"][$recorder["name"]])){ 544 | $recorder["positions"][$recorder["name"]]["stance"] = $recorder["positions"][$recorder["name"]]["y"] + 1.6; 545 | $recorder["positions"][$recorder["name"]]["ground"] = true; 546 | write_packet("0b", $recorder["positions"][$recorder["name"]]); 547 | ++$recorder["name"]; 548 | }else{ 549 | $recorder["mode"] = ""; 550 | } 551 | }else{ 552 | if($ginfo["follow"] > 0){ 553 | $xD = abs($position_packet["x"] - $entities[$ginfo["follow"]]["x"]); 554 | $yD = abs($position_packet["y"] - $entities[$ginfo["follow"]]["y"]); 555 | $zD = abs($position_packet["z"] - $entities[$ginfo["follow"]]["z"]); 556 | if($ginfo["attack"] == true and pow(pow($xD,2) + pow($yD,2) + pow($zD,2),1/3) <= 7){ 557 | write_packet("07", array( 558 | "eid" => $ginfo["eid"], 559 | "target" => $ginfo["follow"], 560 | "left" => true, 561 | )); 562 | write_packet("12", array( 563 | "eid" => $ginfo["eid"], 564 | "animation" => 1, 565 | )); 566 | } 567 | if(sqrt(pow($xD,2) + pow($zD,2)) <= 32 and sqrt(pow($xD,2) + pow($zD,2)) >= 2 and $moving <= 2){ 568 | if($ginfo["jump"] > 0){ 569 | $ginfo["jump"] = -1; 570 | }else{ 571 | $ginfo["jump"] = 1; 572 | } 573 | $position_packet["x"] += ($position_packet["x"] - $entities[$ginfo["follow"]]["x"]>0 ? -0.25:0.25); 574 | if($ginfo["fly"] == false){ 575 | $position_packet["y"] = $position_packet["y"] + $ginfo["jump"]; 576 | }else{ 577 | $position_packet["y"] += ($position_packet["y"] - $entities[$ginfo["follow"]]["y"]>0 ? -0.25:0.25); 578 | } 579 | $position_packet["stance"] = $position_packet["y"] + 1.6; 580 | $position_packet["yaw"] = -rad2deg(atan(($position_packet["x"] - $entities[$ginfo["follow"]]["x"])/($position_packet["z"] - $entities[$ginfo["follow"]]["z"]))); 581 | $position_packet["pitch"] = mt_rand(-10,10); 582 | $position_packet["z"] += ($position_packet["z"] - $entities[$ginfo["follow"]]["z"]>0 ? -0.25:0.25); 583 | $position_packet["ground"] = ($ginfo["jump"] > 0 and $ginfo["fly"] == false) ? false:true; 584 | write_packet("0d", $position_packet); 585 | }else{ 586 | $moving = 0; 587 | } 588 | /*if(sqrt(pow($xD,2) + pow($zD,2)) <= 4){ 589 | write_packet("07", array( 590 | "eid" => $ginfo["eid"], 591 | "target" => $ginfo["owner"]["eid"], 592 | "left" => true, 593 | )); 594 | }*/ 595 | } 596 | if($moving == 0){ 597 | if(arg("crazyness","normal") == "mad"){ 598 | if(mt_rand(0,100)<=80){ 599 | if(mt_rand(0,100)<=40){ 600 | $position_packet["x"] += mt_rand(-30,30)/210; 601 | $position_packet["z"] += mt_rand(-30,30)/210; 602 | } 603 | $position_packet["yaw"] = mt_rand(-360,360); 604 | $position_packet["pitch"] = mt_rand(-360,360); 605 | write_packet("0d", $position_packet); 606 | write_packet("12", array( 607 | "eid" => $ginfo["eid"], 608 | "animation" => 1, 609 | )); 610 | }else{ 611 | write_packet("13", array( 612 | "eid" => $ginfo["eid"], 613 | "action" => ($crouch == false ? 1:2), 614 | )); 615 | $crouch = $crouch == true ? false:true; 616 | } 617 | }elseif(arg("crazyness","normal") == "exorcist"){ 618 | $position_packet["yaw"] = 0; 619 | $position_packet["pitch"] += 6; 620 | $position_packet["pitch"] %= 360; 621 | write_packet("0d", $position_packet); 622 | }else{ 623 | if(mt_rand(0,100)<=20){ 624 | $position_packet["x"] += mt_rand(-30,30)/210; 625 | $position_packet["z"] += mt_rand(-30,30)/210; 626 | } 627 | $position_packet["yaw"] += mt_rand(-25,25); 628 | $position_packet["yaw"] %= 360; 629 | $position_packet["pitch"] += mt_rand(-10,10); 630 | $position_packet["pitch"] %= 55; 631 | write_packet("0d", $position_packet); 632 | } 633 | } 634 | } 635 | $do = true; 636 | } 637 | /*if($start+120<=$time){ 638 | write_packet("ff", array("message" => "Bot auto-disconnect")); 639 | console("[-] Kicked from server, \"Bot auto-disconnect\""); 640 | socket_close($sock); 641 | die(); 642 | }*/ 643 | if($ginfo["timer"]["food"]<=$time and $position_packet !== false){ 644 | $ginfo["timer"]["food"] = $time+4; 645 | $eat = false; 646 | for($i=36;$i<=44;++$i){ 647 | $slot = $ginfo["inventory"][$i]; 648 | if(isset($food[$slot[0]]) == true and ($ginfo["food"] + $food[$slot[0]]) <= 20){ 649 | write_packet("10",array("slot" => $i-36)); 650 | write_packet("0f", array("x" => -1, "y" => -1, "z" => -1, "direction" => -1, "slot" => array(-1))); 651 | $ginfo["food"] = 20; 652 | $eat = true; 653 | break; 654 | }elseif(!isset($food[$slot[0]]) and arg("only-food", false) == true){ 655 | for($a=0;$a $i-36)); 657 | write_packet("0e", array("status" => 4, "x" => 0, "y" => 0, "z" => 0, "face" => 0)); 658 | } 659 | } 660 | } 661 | if($ginfo["timer"]["sayfood"]<=$time and $eat == false and $ginfo["food"] <= 12){ 662 | $ginfo["timer"]["sayfood"] = $time+60; 663 | $messages = array( 664 | "Necesito comida!", 665 | "Comida!!!", 666 | "Me muero de hambre!", 667 | "No tengo comida!", 668 | ); 669 | Message($messages[count($messages)-1]); 670 | } 671 | } 672 | if($do){ 673 | $next = $time+0.05; 674 | } 675 | usleep(10); 676 | } 677 | socket_close($sock); 678 | if($restart == true){ 679 | console("[+] Restarting..."); 680 | $buffer = ""; 681 | sleep(8); 682 | include("client.php"); 683 | } 684 | die(); 685 | ?> 686 | -------------------------------------------------------------------------------- /command.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shoghicp/Minecraft-PHP-Client/58641b0674480be1e2c086f0998c088ae31284ac/command.php -------------------------------------------------------------------------------- /dynmap.php: -------------------------------------------------------------------------------- 1 | 'up/world/{world}/', 'send' => 'up/sendmessage'); 5 | $worlds = array( 6 | "mesp", 7 | /*"Celestia", 8 | "Reach", 9 | "Raccon", 10 | "Splash", 11 | "mesp2_the_end", 12 | "Laisla", 13 | "nether",*/ 14 | ); 15 | $players = array(); 16 | foreach($worlds as $world){ 17 | $update = json_decode(curl_get("http://mespduendedreams.com:".intval(arg("dynmap", false))."/".str_replace('{world}',$world,$config['get']).time()),true); 18 | foreach($update['players'] as $player){ 19 | $players[$player['name']] = $player; 20 | } 21 | } 22 | return $players; 23 | } 24 | 25 | ?> 26 | -------------------------------------------------------------------------------- /forking.php: -------------------------------------------------------------------------------- 1 | 4096 ? 4096:strlen($buffer); 45 | socket_write($IOsock, urlencode(substr($buffer,0,$len))."\n"); 46 | $buffer = substr($buffer,$len); 47 | break; 48 | case "chunk": 49 | $last = time(); 50 | $packet = unserialize(urldecode(trim(socket_read($IOsock,4096*16,PHP_NORMAL_READ)))); 51 | chunk_add($packet["chunk"], $packet["x"], $packet["z"]); 52 | chunk_clean($packet["x"], $packet["z"]); 53 | socket_write($IOsock, urlencode(serialize($chunks))."\n"); 54 | break; 55 | case "chunk2": 56 | $last = time(); 57 | $packet = unserialize(urldecode(trim(socket_read($IOsock,4096*16,PHP_NORMAL_READ)))); 58 | chunk_edit_block($packet["x"],$packet["y"],$packet["z"],$packet["type"]); 59 | socket_write($IOsock, urlencode(serialize($chunks))."\n"); 60 | break; 61 | case "die": 62 | return; 63 | break; 64 | } 65 | } 66 | 67 | } 68 | 69 | function fork_chunk($packet, $pid){ 70 | global $parent_sock, $chunks; 71 | socket_write($parent_sock,"chunk".($pid == 33 ? "":"2")."\n".urlencode(serialize($packet))."\n"); 72 | $chunks = unserialize(urldecode(trim(socket_read($parent_sock,4096,PHP_NORMAL_READ)))); 73 | } 74 | 75 | function fork_buffer(){ 76 | global $parent_sock, $buffer, $connected; 77 | 78 | socket_write($parent_sock,"buffer\n"); 79 | if(strlen($buffer) < 128 and $connected){ 80 | socket_set_block($parent_sock); 81 | }else{ 82 | socket_set_nonblock($parent_sock); 83 | } 84 | return urldecode(trim(socket_read($parent_sock,4096,PHP_NORMAL_READ))); 85 | } 86 | 87 | ?> 88 | -------------------------------------------------------------------------------- /functions.php: -------------------------------------------------------------------------------- 1 | 127 ? -(256-$b+1):$b; 24 | } 25 | return $b; 26 | } 27 | function write_byte($value, $signed = true){ 28 | if($signed == true){ 29 | $value = ($value <= -1) ? (256+$value):$value; 30 | } 31 | return pack("c", $value); 32 | } 33 | 34 | function read_short($str){ 35 | list(,$unpacked) = unpack("n", substr($str, 0, 2)); 36 | if($unpacked >= pow(2, 15)) $unpacked -= pow(2, 16); // Convert unsigned short to signed short. 37 | return $unpacked; 38 | } 39 | function write_short($value){ 40 | if($value < 0){ 41 | $value += pow(2, 16); 42 | } 43 | return pack("n", $value); 44 | } 45 | 46 | function read_int($str){ 47 | list(,$unpacked) = unpack("N", substr($str, 0, 4)); 48 | if($unpacked >= pow(2, 31)) $unpacked -= pow(2, 32); // Convert unsigned int to signed int 49 | return $unpacked; 50 | } 51 | function write_int($value){ 52 | if($value < 0){ 53 | $value += pow(2, 32); 54 | } 55 | return pack("N", $value); 56 | } 57 | 58 | 59 | function read_float($str){ 60 | list(,$value) = (pack('d', 1) == "\77\360\0\0\0\0\0\0")?unpack('f', substr($str,0, 4)):unpack('f', strrev(substr($str,0, 4))); 61 | return $value; 62 | } 63 | function write_float($value){ 64 | return (pack('d', 1) == "\77\360\0\0\0\0\0\0")?pack('f', $value):strrev(pack('f', $value)); 65 | } 66 | 67 | function read_double($str, $signed = true){ 68 | list(,$value) = (pack('d', 1) == "\77\360\0\0\0\0\0\0")?unpack('d', substr($str,0, 8)):unpack('d', strrev(substr($str,0, 8))); 69 | return $value; 70 | } 71 | function write_double($value){ 72 | return (pack('d', 1) == "\77\360\0\0\0\0\0\0")?pack('d', $value):strrev(pack('d', $value)); 73 | } 74 | 75 | function read_long($str, $signed = true){ 76 | $n = ""; 77 | for($i=0;$i<8;++$i){ 78 | $n .= bin2hex($str{$i}); 79 | } 80 | $n = hexdec($n); 81 | if($signed == true){ 82 | $n = $n>9223372036854775807 ? -(18446744073709551614-$n+1):$n; 83 | } 84 | return sprintf("%.0F", $n); 85 | } 86 | function write_long($value){ 87 | return (pack('d', 1) == "\77\360\0\0\0\0\0\0")?pack('d', $value):strrev(pack('d', $value)); 88 | } 89 | 90 | function convert($format, $str){ 91 | $ret = unpack($format, $str); 92 | if(is_array($ret)){ 93 | $ret = implode($ret); 94 | } 95 | return $ret; 96 | } 97 | 98 | function arg($name, $default){ 99 | global $arguments, $argv; 100 | if(!isset($arguments)){ 101 | $arguments = arguments($argv); 102 | } 103 | 104 | if(isset($arguments["commands"][$name])){ 105 | return $arguments["commands"][$name]; 106 | }else{ 107 | return $default; 108 | } 109 | } 110 | 111 | function arguments ( $args ){ 112 | if(!is_array($args)){ 113 | $args = array(); 114 | } 115 | array_shift( $args ); 116 | $args = join( $args, ' ' ); 117 | 118 | preg_match_all('/ (--\w+ (?:[= ] [^-]+ [^\s-] )? ) | (-\w+) | (\w+) /x', $args, $match ); 119 | $args = array_shift( $match ); 120 | 121 | /* 122 | Array 123 | ( 124 | [0] => asdf 125 | [1] => asdf 126 | [2] => --help 127 | [3] => --dest=/var/ 128 | [4] => -asd 129 | [5] => -h 130 | [6] => --option mew arf moo 131 | [7] => -z 132 | ) 133 | */ 134 | 135 | $ret = array( 136 | 'input' => array(), 137 | 'commands' => array(), 138 | 'flags' => array() 139 | ); 140 | 141 | foreach ( $args as $arg ) { 142 | 143 | // Is it a command? (prefixed with --) 144 | if ( substr( $arg, 0, 2 ) === '--' ) { 145 | 146 | $value = preg_split( '/[= ]/', $arg, 2 ); 147 | $com = substr( array_shift($value), 2 ); 148 | $value = join($value); 149 | 150 | $ret['commands'][$com] = !empty($value) ? $value : true; 151 | continue; 152 | 153 | } 154 | 155 | // Is it a flag? (prefixed with -) 156 | if ( substr( $arg, 0, 1 ) === '-' ) { 157 | $ret['flags'][] = substr( $arg, 1 ); 158 | continue; 159 | } 160 | 161 | $ret['input'][] = $arg; 162 | continue; 163 | 164 | } 165 | 166 | return $ret; 167 | } 168 | 169 | function min_struct($array){ 170 | $offset = 0; 171 | foreach($array as $type){ 172 | switch($type){ 173 | case "float": 174 | case "int": 175 | $offset += 4; 176 | break; 177 | case "double": 178 | case "long": 179 | $offset += 8; 180 | break; 181 | case "bool": 182 | case "boolean": 183 | case "byte": 184 | $offset += 1; 185 | $offset += 1; 186 | break; 187 | case "short": 188 | $offset += 2; 189 | break; 190 | } 191 | } 192 | return $offset; 193 | } 194 | 195 | function wait_buffer($to){ 196 | global $buffer, $connected; 197 | while(!isset($buffer{$to}) and $connected){ 198 | buffer(); //FIXES SLOW-CONNECTION ERROR 199 | } 200 | } 201 | 202 | function parse_packet(){ 203 | global $buffer, $pstruct, $path, $connected; 204 | $pid = bin2hex($buffer{0}); 205 | $data = array(); 206 | $pdata = array(); 207 | $raw = array(); 208 | $offset = 1; 209 | 210 | if(!isset($pstruct[$pid])){ 211 | write_packet("ff", array("message" => "Bad packet id ".$pid)); 212 | if(arg("log", false) === true or (arg("log", false) != false and arg("log", false) == "packets")){ 213 | $p = "==".time()."==> ERROR Bad packet id $pid :".PHP_EOL; 214 | $p .= hexdump(substr($buffer,0,512), false, false, true); 215 | $p .= PHP_EOL . "--------------- (512 byte extract) ----------" .PHP_EOL .PHP_EOL; 216 | file_put_contents($path."packets.log", $p, FILE_APPEND); 217 | } 218 | return array("pid" => "ff", "message" => "Bad packet id ".$pid); 219 | } 220 | wait_buffer(min_struct($pstruct[$pid])); 221 | $field = 0; 222 | $continue = true; 223 | foreach($pstruct[$pid] as $type){ 224 | if($continue == false){ 225 | break; 226 | } 227 | switch($type){ 228 | case "int": 229 | $raw[] = $r = substr($buffer,$offset, 4); 230 | $pdata[] = read_int($r); 231 | if($field == 5 and $pid == "17" and $pdata[count($pdata)-1] == 0){ 232 | $continue = false; 233 | } 234 | $offset += 4; 235 | break; 236 | case "string": 237 | $len = read_short(substr($buffer,$offset,2)); 238 | $offset += 2; 239 | wait_buffer($offset+$len*2-1); 240 | $raw[] = $r = substr($buffer,$offset,$len * 2); 241 | $pdata[] = utf16_decode($r); 242 | $offset += $len * 2; 243 | break; 244 | case "long": 245 | $raw[] = $r = substr($buffer,$offset, 8); 246 | $pdata[] = read_long($r); 247 | $offset += 8; 248 | break; 249 | case "byte": 250 | $raw[] = $r = $buffer{$offset}; 251 | $pdata[] = read_byte($r); 252 | $offset += 1; 253 | break; 254 | case "ubyte": 255 | $raw[] = $r = $buffer{$offset}; 256 | $pdata[] = read_byte($r, false); 257 | $offset += 1; 258 | break; 259 | case "float": 260 | $raw[] = $r = substr($buffer,$offset, 4); 261 | $pdata[] = convert("f", $r); 262 | $offset += 4; 263 | break; 264 | case "double": 265 | $raw[] = $r = substr($buffer,$offset, 8); 266 | $pdata[] = read_double($r); 267 | $offset += 8; 268 | break; 269 | case "short": 270 | $raw[] = $r = substr($buffer,$offset,2); 271 | $pdata[] = read_short($r); 272 | $offset += 2; 273 | break; 274 | case "bool": 275 | case "boolean": 276 | $raw[] = $r = $buffer{$offset}; 277 | $pdata[] = read_byte($r, false) == 0 ? false:true; 278 | $offset += 1; 279 | break; 280 | case "explosionRecord": 281 | $r = array(); 282 | for($i=$pdata[4];$i>0;--$i){ 283 | $r[] = array(read_byte($buffer{$offset}),read_byte($buffer{$offset+1}),read_byte($buffer{$offset+2})); 284 | $offset += 3; 285 | } 286 | $pdata[] = $r; 287 | break; 288 | case "byteArray": 289 | $len = $pdata[count($pdata)-1]; 290 | $pdata[] = substr($buffer,$offset,$len); 291 | $offset += $len; 292 | break; 293 | case "chunkArray": 294 | $len = max(0,$pdata[6]); 295 | $first = false; 296 | $r = ""; 297 | while(strlen($r)<$len){ //Sometimes low-bandwidth servers made client a crash 298 | if($first == true){ 299 | buffer(); 300 | global $buffer; 301 | } 302 | $first = true; 303 | $r = substr($buffer, $offset, $len); 304 | } 305 | $pdata[] = $r; 306 | $offset += $len; 307 | break; 308 | case "multiblockArray": 309 | $count = $pdata[count($pdata)-1]; 310 | for($i=0;$i<$count;++$i){ 311 | //read_short(substr($buffer,$offset,2)); 312 | $offset += 2; 313 | } 314 | for($i=0;$i<$count;++$i){ 315 | //read_byte($buffer{$offset}); 316 | $offset += 1; 317 | } 318 | for($i=0;$i<$count;++$i){ 319 | //read_byte($buffer{$offset}); 320 | $offset += 1; 321 | } 322 | $pdata[] = ""; 323 | break; 324 | case "newChunkArray": 325 | $len = max(0,$pdata[5]); 326 | $first = false; 327 | $r = ""; 328 | while(strlen($r)<$len){ //Sometimes low-bandwidth servers made client a crash 329 | if($first == true){ 330 | buffer(); 331 | global $buffer; 332 | } 333 | $first = true; 334 | $r = substr($buffer, $offset, $len); 335 | } 336 | $pdata[] = $r; 337 | $offset += $len; 338 | break; 339 | case "newMultiblockArray": 340 | $count = $pdata[3]; 341 | $pdata[] = substr($buffer, $offset, $count); 342 | $offset += $count; 343 | break; 344 | case "slotArray": 345 | case "slotData": 346 | $scount = $type == "slotData" ? 1:$pdata[count($pdata)-1]; 347 | $d = array(); 348 | for($i=0;$i<$scount;++$i){ 349 | $id = read_short(substr($buffer,$offset,2)); 350 | $offset += 2; 351 | if($id != -1){ 352 | $count = read_byte($buffer{$offset}); 353 | $offset += 1; 354 | $meta = read_short(substr($buffer,$offset,2)); 355 | $offset += 2; 356 | $d[$i] = array($id,$count,$meta); 357 | $enchantable_items = array( 358 | 0x103, #Flint and steel 359 | 0x105, #Bow 360 | 0x15A, #Fishing rod 361 | 0x167, #Shears 362 | 363 | #TOOLS 364 | #sword, shovel, pickaxe, axe, hoe 365 | 0x10C, 0x10D, 0x10E, 0x10F, 0x122, #WOOD 366 | 0x110, 0x111, 0x112, 0x113, 0x123, #STONE 367 | 0x10B, 0x100, 0x101, 0x102, 0x124, #IRON 368 | 0x114, 0x115, 0x116, 0x117, 0x125, #DIAMOND 369 | 0x11B, 0x11C, 0x11D, 0x11E, 0x126, #GOLD 370 | 371 | #ARMOUR 372 | #helmet, chestplate, leggings, boots 373 | 0x12A, 0x12B, 0x12C, 0x12D, #LEATHER 374 | 0x12E, 0x12F, 0x130, 0x131, #CHAIN 375 | 0x132, 0x133, 0x134, 0x135, #IRON 376 | 0x136, 0x137, 0x138, 0x139, #DIAMOND 377 | 0x13A, 0x13B, 0x13C, 0x13D, #GOLD 378 | ); 379 | if(in_array($id, $enchantable_items)){ 380 | $len = read_short(substr($buffer,$offset,2)); 381 | $offset += 2; 382 | if($len > -1){ 383 | $arr = substr($buffer, $offset, $len); 384 | $offset += $len; 385 | } 386 | } 387 | } 388 | } 389 | $pdata[] = $d; 390 | break; 391 | case "entityMetadata": 392 | $m = array(); 393 | $b = read_byte($buffer{$offset}, false); 394 | while($b != 127){ 395 | $offset += 1; 396 | $bottom = $b & 0x1F; 397 | $type = $b >> 5; 398 | switch($type){ 399 | case 0: 400 | $r = read_byte($buffer{$offset}); 401 | $offset += 1; 402 | break; 403 | case 1: 404 | $r = read_short(substr($buffer,$offset,2)); 405 | $offset += 2; 406 | break; 407 | case 2: 408 | $r = read_int(substr($buffer,$offset, 4)); 409 | $offset += 4; 410 | break; 411 | case 3: 412 | $r = convert("f", substr($buffer,$offset, 4)); 413 | $offset += 4; 414 | break; 415 | case 4: 416 | $len = read_short(substr($buffer,$offset,2)); 417 | $offset += 2; 418 | $r = no_endian(substr($buffer,$offset,$len * 2)); 419 | $offset += $len * 2; 420 | break; 421 | case 5: 422 | $r = array("id" => read_short(substr($buffer,$offset,2)), "count" => read_byte($buffer{$offset+2}), "damage" => read_short($buffer{$offset+3}.$buffer{$offset+4})); 423 | $offset += 5; 424 | break; 425 | 426 | case 6: 427 | $r = array(); 428 | for($i=0;$i<3;++$i){ 429 | $r[] = convert("I", substr($buffer,$offset, 4)); 430 | $offset += 4; 431 | } 432 | break; 433 | 434 | } 435 | $m[] = $r; 436 | $b = read_byte($buffer{$offset}, false); 437 | } 438 | $offset += 1; 439 | $pdata[] = $m; 440 | break; 441 | 442 | 443 | } 444 | ++$field; 445 | } 446 | 447 | 448 | if(arg("log", false) === true or (arg("log", false) != false and arg("log", false) == "packets")){ 449 | $p = "==".time()."==> RECEIVED Packet $pid, lenght $offset :".PHP_EOL; 450 | $p .= hexdump(substr($buffer,0,$offset), false, false, true); 451 | $p .= PHP_EOL .PHP_EOL; 452 | file_put_contents($path."packets.log", $p, FILE_APPEND); 453 | }elseif(arg("log", false) != false and arg("log", false) == "raw"){ 454 | file_put_contents($path."raw_recv.log", substr($buffer,0,$offset), FILE_APPEND); 455 | } 456 | 457 | $buffer = substr($buffer, $offset); // Clear packet 458 | 459 | switch($pid){ 460 | case "00": 461 | $data["ka_id"] = $pdata[0]; 462 | break; 463 | case "01": //Login 464 | $data["eid"] = $pdata[0]; 465 | $data["seed"] = $pdata[2]; 466 | if($protocol >= 23){ 467 | $data["level_type"] = $pdata[3]; 468 | $data["mode"] = $pdata[4]; 469 | $data["dimension"] = $pdata[5]; 470 | $data["difficulty"] = $pdata[6]; 471 | $data["height"] = $pdata[7]; 472 | $data["max_players"] = $pdata[8]; 473 | }else{ 474 | $data["mode"] = $pdata[3]; 475 | $data["dimension"] = $pdata[4]; 476 | $data["difficulty"] = $pdata[5]; 477 | $data["height"] = $pdata[6]; 478 | $data["max_players"] = $pdata[7]; 479 | } 480 | break; 481 | case "02": //Handshake 482 | $data["server_id"] = $pdata[0]; 483 | break; 484 | case "03": //Chat 485 | $data["message"] = $pdata[0]; 486 | break; 487 | case "04": //Time update 488 | $data["time"] = $pdata[0];//unpack("L*",substr($buffer,0,8)); 489 | break; 490 | case "06": //Spawn pos 491 | $data["x"] = $pdata[0]; 492 | $data["y"] = $pdata[1]; 493 | $data["z"] = $pdata[2]; 494 | break; 495 | case "08": 496 | $data["health"] = $pdata[0]; 497 | $data["food"] = $pdata[1]; 498 | $data["saturation"] = $pdata[1]; 499 | break; 500 | case "0d": 501 | $data["x"] = $pdata[0]; 502 | $data["stance"] = $pdata[1]; 503 | $data["y"] = $pdata[2]; 504 | $data["z"] = $pdata[3]; 505 | $data["yaw"] = $pdata[4]; 506 | $data["pitch"] = $pdata[5]; 507 | $data["ground"] = $pdata[6]; 508 | break; 509 | case "14": //named entity spawn 510 | $data["eid"] = $pdata[0]; 511 | $data["name"] = $pdata[1]; 512 | $data["type"] = 100; 513 | $data["x"] = $pdata[2] / 32; 514 | $data["y"] = $pdata[3] / 32; 515 | $data["z"] = $pdata[4] / 32; 516 | break; 517 | case "17": 518 | $data["eid"] = $pdata[0]; 519 | $data["type"] = $pdata[1]; 520 | $data["x"] = $pdata[2] / 32; 521 | $data["y"] = $pdata[3] / 32; 522 | $data["z"] = $pdata[4] / 32; 523 | break; 524 | case "18": 525 | $data["eid"] = $pdata[0]; 526 | $data["type"] = $pdata[1]; 527 | $data["x"] = $pdata[2] / 32; 528 | $data["y"] = $pdata[3] / 32; 529 | $data["z"] = $pdata[4] / 32; 530 | break; 531 | case "1d": 532 | $data["eid"] = $pdata[0]; 533 | break; 534 | case "1f": 535 | $data["eid"] = $pdata[0]; 536 | $data["dX"] = $pdata[1] / 32; 537 | $data["dY"] = $pdata[2] / 32; 538 | $data["dZ"] = $pdata[3] / 32; 539 | break; 540 | case "20": 541 | $data["eid"] = $pdata[0]; 542 | $data["yaw"] = $pdata[1]; 543 | $data["pitch"] = $pdata[2]; 544 | break; 545 | case "21": 546 | $data["eid"] = $pdata[0]; 547 | $data["dX"] = $pdata[1] / 32; 548 | $data["dY"] = $pdata[2] / 32; 549 | $data["dZ"] = $pdata[3] / 32; 550 | $data["yaw"] = $pdata[4]; 551 | $data["pitch"] = $pdata[5]; 552 | break; 553 | case "22": 554 | $data["eid"] = $pdata[0]; 555 | $data["x"] = $pdata[1] / 32; 556 | $data["y"] = $pdata[2] / 32; 557 | $data["z"] = $pdata[3] / 32; 558 | $data["yaw"] = $pdata[4]; 559 | $data["pitch"] = $pdata[5]; 560 | break; 561 | case "33": 562 | if($protocol <= 23){ 563 | $data["x"] = $pdata[0]; 564 | $data["y"] = $pdata[1]; 565 | $data["z"] = $pdata[2]; 566 | $data["xS"] = $pdata[3]; 567 | $data["yS"] = $pdata[4]; 568 | $data["zS"] = $pdata[5]; 569 | $data["lenght"] = $pdata[6]; 570 | $data["chunk"] = $pdata[7]; 571 | }else{ 572 | $data["x"] = $pdata[0]; 573 | $data["z"] = $pdata[1]; 574 | $data["continuous"] = $pdata[2]; 575 | $data["pbm"] = $pdata[3]; 576 | $data["abm"] = $pdata[4]; 577 | $data["lenght"] = $pdata[5]; 578 | $data["chunk"] = $pdata[7]; 579 | } 580 | break; 581 | case "34": 582 | if($protocol <= 23){ 583 | $data["x"] = $pdata[0]; 584 | $data["z"] = $pdata[1]; 585 | $data["size"] = $pdata[2]; 586 | $data["carray"] = $pdata[3]; 587 | $data["tarray"] = $pdata[4]; 588 | $data["marray"] = $pdata[5]; 589 | }else{ 590 | $data["x"] = $pdata[0]; 591 | $data["z"] = $pdata[1]; 592 | $data["count"] = $pdata[2]; 593 | $data["size"] = $pdata[3]; 594 | /*$data["carray"] = $pdata[4]; 595 | $data["tarray"] = $pdata[5]; 596 | $data["marray"] = $pdata[6];*/ 597 | } 598 | break; 599 | case "35": 600 | $data["x"] = $pdata[0]; 601 | $data["y"] = $pdata[1]; 602 | $data["z"] = $pdata[2]; 603 | $data["type"] = $pdata[3]; 604 | $data["meta"] = $pdata[4]; 605 | break; 606 | case "46": 607 | $data["reason"] = $pdata[0]; 608 | if($protocol <= 14){ 609 | $data["mode"] = $pdata[1]; 610 | } 611 | break; 612 | case "67": 613 | $data["wid"] = $pdata[0]; 614 | $data["slot"] = $pdata[1]; 615 | $data["sdata"] = $pdata[2]; 616 | break; 617 | case "68": 618 | $data["wid"] = $pdata[0]; 619 | $data["count"] = $pdata[1]; 620 | $data["sdata"] = $pdata[2]; 621 | break; 622 | case "82": 623 | $data["x"] = $pdata[0]; 624 | $data["y"] = $pdata[1]; 625 | $data["z"] = $pdata[2]; 626 | $data["text"] = array($pdata[3], $pdata[4], $pdata[5], $pdata[6]); 627 | break; 628 | case "fa": 629 | $data["channel"] = $pdata[0]; 630 | $data["lenght"] = $pdata[1]; 631 | $data["data"] = $pdata[2]; 632 | break; 633 | case "ff": 634 | $data["message"] = $pdata[0]; 635 | break; 636 | } 637 | $data["pid"] = $pid; 638 | $data["raw"] = $raw; 639 | return $data; 640 | } 641 | 642 | function write_packet($pid,$data = array(), $raw = false){ 643 | global $sock, $path, $protocol, $connected; 644 | if($raw == false){ 645 | switch($pid){ 646 | case "00": 647 | $packet = "\x00". 648 | ($protocol <= 14 ? "":$data["raw"][0]); 649 | break; 650 | case "01": //Login 651 | $packet = "\x01". 652 | write_int($data["version"]). 653 | write_string($data["username"]); 654 | if($protocol<=23){ 655 | $packet .= write_long(0); 656 | } 657 | if($protocol >= 23){ 658 | $packet .= write_string(""); 659 | } 660 | if($protocol > 14){ 661 | $packet .= write_int(0); 662 | if($protocol >= 23){ 663 | $packet .= write_int(0); 664 | }else{ 665 | $packet .= write_byte(0); 666 | } 667 | $packet .= write_byte(0). 668 | write_byte(0); 669 | } 670 | $packet .= write_byte(0); 671 | break; 672 | 673 | case "02": //Handshake 674 | $packet = "\x02"; 675 | if($protocol > 23 ){ 676 | $packet .= write_string($data["username"].";".$data["server"]); 677 | }else{ 678 | $packet .= write_string($data["username"]); 679 | } 680 | break; 681 | case "03": 682 | $packet = "\x03". 683 | write_string($data["message"]); 684 | break; 685 | case "07": 686 | $packet = "\x07". 687 | write_int($data["eid"]). 688 | write_int($data["target"]). 689 | ($data["left"] == true ? "\x01":"\x00"); 690 | break; 691 | case "09": 692 | $packet = "\x09". 693 | write_byte($data["dimension"]). 694 | write_byte($data["difficulty"]). 695 | write_byte($data["mode"]). 696 | write_short($data["height"]). 697 | write_long($data["seed"]). 698 | ($protocol >= 23 ? write_string($data["level_type"]):""); 699 | break; 700 | case "0a": 701 | $packet = "\x0a". 702 | ($data["ground"] == true ? "\x01":"\x00"); 703 | break; 704 | case "0b": 705 | $packet = "\x0b". 706 | write_double($data["x"]). 707 | write_double($data["y"]). 708 | write_double($data["stance"]). 709 | write_double($data["z"]). 710 | ($data["ground"] == true ? "\x01":"\x00"); 711 | break; 712 | case "0c": 713 | $packet = "\x0c". 714 | write_float($data["yaw"]). 715 | write_float($data["pitch"]). 716 | ($data["ground"] == true ? "\x01":"\x00"); 717 | break; 718 | case "0d": 719 | $packet = "\x0d". 720 | write_double($data["x"]). 721 | write_double($data["y"]). 722 | write_double($data["stance"]). 723 | write_double($data["z"]). 724 | write_float($data["yaw"]). 725 | write_float($data["pitch"]). 726 | ($data["ground"] == true ? "\x01":"\x00"); 727 | break; 728 | case "0e": 729 | $packet = "\x0e". 730 | write_byte($data["status"]). 731 | write_int($data["x"]). 732 | write_byte($data["y"]). 733 | write_int($data["z"]). 734 | write_byte($data["face"]); 735 | break; 736 | case "0f": 737 | $packet = "\x0f". 738 | write_int($data["x"]). 739 | write_byte($data["y"]). 740 | write_int($data["z"]). 741 | write_byte($data["direction"]). 742 | 743 | write_short($data["slot"][0]); 744 | if($data["slot"][0]!=-1){ 745 | $packet .= write_byte($data["slot"][1]). 746 | write_short($data["slot"][2]); 747 | } 748 | break; 749 | case "10": 750 | $packet = "\x10". 751 | write_short($data["slot"]); 752 | break; 753 | case "12": 754 | $packet = "\x12". 755 | write_int($data["eid"]). 756 | write_byte($data["animation"]); 757 | break; 758 | case "13": 759 | $packet = "\x13". 760 | write_int($data["eid"]). 761 | write_byte($data["action"]); 762 | break; 763 | case "1b": 764 | /*$packet = "\x1b". 765 | write_float($data["x"]). 766 | write_float($data["y"]). 767 | write_float($data["stance"]). 768 | write_float($data["z"]). 769 | write_float($data["yaw"]). 770 | write_float($data["pitch"]). 771 | ($data["ground"] == true ? "\x01":"\x00"); */ 772 | break; 773 | case "27": 774 | $packet = "\x27". 775 | write_int($data["eid"]). 776 | write_int($data["vid"]); 777 | break; 778 | case "fe": 779 | $packet = "\xfe"; 780 | break; 781 | case "ff": 782 | $packet = "\xff". 783 | write_string($data["message"]); 784 | break; 785 | } 786 | }else{ 787 | $packet = pack("H*" , $pid); 788 | foreach($data["raw"] as $field){ 789 | $packet .= $field; 790 | } 791 | } 792 | if(!$connected){ 793 | return false; 794 | } 795 | 796 | if(arg("log", false) === true and (arg("log", false) != false and arg("log", false) == "packets")){ 797 | $len = strlen($packet); 798 | $p = "==".time()."==> SENT Packet $pid, lenght $len:".PHP_EOL; 799 | $p .= hexdump($packet, false, false, true); 800 | $p .= PHP_EOL .PHP_EOL; 801 | file_put_contents($path."packets.log", $p, FILE_APPEND); 802 | }elseif(arg("log", false) != false and arg("log", false) == "raw"){ 803 | file_put_contents($path."raw_sent.log", $packet, FILE_APPEND); 804 | } 805 | 806 | return @socket_write($sock, $packet); 807 | } 808 | 809 | function endian($str){ 810 | $new = ''; 811 | $len = strlen($str); 812 | for($i=0;$i<$len;++$i){ 813 | $new .= "\00".$str{$i}; 814 | } 815 | return $new; 816 | } 817 | function no_endian($str){ 818 | $len = strlen($str); 819 | $f=""; 820 | for($i=0;$i<$len;++$i){ 821 | if($i%2==1 and $i > 0){ 822 | $f .= $str{$i}; 823 | } 824 | } 825 | return $f; 826 | } 827 | 828 | function curl_get($page){ 829 | $ch = curl_init ($page); 830 | curl_setopt ($ch, CURLOPT_HTTPHEADER, array('User-Agent: Minecraft PHP Client')); 831 | curl_setopt ($ch, CURLOPT_AUTOREFERER, true); 832 | curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false); 833 | curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 2); 834 | curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true); 835 | curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); 836 | return curl_exec ($ch); 837 | } 838 | function curl_post($page, $args){ 839 | $ch = curl_init($page); 840 | curl_setopt ($ch, CURLOPT_POST, 1); 841 | curl_setopt ($ch, CURLOPT_POSTFIELDS, $args); 842 | curl_setopt ($ch, CURLOPT_AUTOREFERER, true); 843 | curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true); 844 | curl_setopt ($ch, CURLOPT_HTTPHEADER, array('User-Agent: Minecraft PHP Client')); 845 | curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); 846 | return curl_exec($ch); 847 | } 848 | 849 | function buffer(){ 850 | global $buffer, $sock, $connected; 851 | if(!isset($buffer)){ 852 | $buffer = ""; 853 | } 854 | $len = strlen($buffer); 855 | if(THREADED and !CHILD){ 856 | if($len < (MAX_BUFFER_BYTES / 8)){ 857 | $buffer .= fork_buffer(); 858 | } 859 | return; 860 | } 861 | 862 | if($len < (MAX_BUFFER_BYTES / 8)){ 863 | if(strlen($buffer) < 128 and $connected){ 864 | socket_set_block($sock); 865 | }else{ 866 | socket_set_nonblock($sock); 867 | } 868 | $read = @socket_read($sock,MAX_BUFFER_BYTES-$len, PHP_BINARY_READ); 869 | if($read != false and $read != ""){ 870 | $buffer .= $read; 871 | }elseif(socket_last_error($sock) == 104){ 872 | $connected = false; 873 | } 874 | } 875 | 876 | } 877 | 878 | 879 | /** 880 | * View any string as a hexdump. 881 | * 882 | * This is most commonly used to view binary data from streams 883 | * or sockets while debugging, but can be used to view any string 884 | * with non-viewable characters. 885 | * 886 | * @version 1.3.2 887 | * @author Aidan Lister 888 | * @author Peter Waller 889 | * @link http://aidanlister.com/2004/04/viewing-binary-data-as-a-hexdump-in-php/ 890 | * @param string $data The string to be dumped 891 | * @param bool $htmloutput Set to false for non-HTML output 892 | * @param bool $uppercase Set to true for uppercase hex 893 | * @param bool $return Set to true to return the dump 894 | */ 895 | function hexdump ($data, $htmloutput = true, $uppercase = false, $return = false) 896 | { 897 | // Init 898 | $hexi = ''; 899 | $ascii = ''; 900 | $dump = ($htmloutput === true) ? '
' : '';
901 |     $offset = 0;
902 |     $len    = strlen($data);
903 |  
904 |     // Upper or lower case hexadecimal
905 |     $x = ($uppercase === false) ? 'x' : 'X';
906 |  
907 |     // Iterate string
908 |     for ($i = $j = 0; $i < $len; $i++)
909 |     {
910 |         // Convert to hexidecimal
911 |         $hexi .= sprintf("%02$x ", ord($data[$i]));
912 |  
913 |         // Replace non-viewable bytes with '.'
914 |         if (ord($data[$i]) >= 32) {
915 |             $ascii .= ($htmloutput === true) ?
916 |                             htmlentities($data[$i]) :
917 |                             $data[$i];
918 |         } else {
919 |             $ascii .= '.';
920 |         }
921 |  
922 |         // Add extra column spacing
923 |         if ($j === 7) {
924 |             $hexi  .= ' ';
925 |             $ascii .= ' ';
926 |         }
927 |  
928 |         // Add row
929 |         if (++$j === 16 || $i === $len - 1) {
930 |             // Join the hexi / ascii output
931 |             $dump .= sprintf("%04$x  %-49s  %s", $offset, $hexi, $ascii);
932 |  
933 |             // Reset vars
934 |             $hexi   = $ascii = '';
935 |             $offset += 16;
936 |             $j      = 0;
937 |  
938 |             // Add newline
939 |             if ($i !== $len - 1) {
940 |                 $dump .= "\n";
941 |             }
942 |         }
943 |     }
944 |  
945 |     // Finish dump
946 |     $dump .= $htmloutput === true ?
947 |                 '
' : 948 | ''; 949 | $dump .= "\n"; 950 | 951 | $dump = preg_replace("/[^[:print:]\\r\\n]/", ".", $dump); 952 | 953 | // Output method 954 | if ($return === false) { 955 | echo $dump; 956 | } else { 957 | return $dump; 958 | } 959 | } 960 | 961 | function utf16_decode( $str ) { 962 | if( strlen($str) < 2 ) return $str; 963 | $bom_be = true; 964 | $c0 = ord($str{0}); 965 | $c1 = ord($str{1}); 966 | if( $c0 == 0xfe && $c1 == 0xff ) { $str = substr($str,2); } 967 | elseif( $c0 == 0xff && $c1 == 0xfe ) { $str = substr($str,2); $bom_be = false; } 968 | $len = strlen($str); 969 | $newstr = ''; 970 | for($i=0;$i<$len;$i+=2) { 971 | if( $bom_be ) { $val = ord($str{$i}) << 4; $val += ord($str{$i+1}); } 972 | else { $val = ord($str{$i+1}) << 4; $val += ord($str{$i}); } 973 | $newstr .= ($val == 0x228) ? "\n" : chr($val); 974 | } 975 | return $newstr; 976 | } 977 | ?> 978 | -------------------------------------------------------------------------------- /materials.php: -------------------------------------------------------------------------------- 1 | "Air", 5 | 1 => "Stone", 6 | 2 => "Grass", 7 | 3 => "Dirt", 8 | 4 => "Cobblestone", 9 | 5 => "Plank", 10 | 6 => "Sapling", 11 | 7 => "Bedrock", 12 | 8 => "Water", 13 | 9 => "Water", 14 | 10 => "Lava", 15 | 11 => "Lava", 16 | 12 => "Sand", 17 | 13 => "Gravel", 18 | 14 => "Gold Ore", 19 | 15 => "Iron Ore", 20 | 16 => "Coal Ore", 21 | 17 => "Wood", 22 | 18 => "Leave", 23 | 19 => "Sponge", 24 | 20 => "Glass", 25 | 21 => "Lapis Lazuli Ore", 26 | 22 => "Lapis Lazuli Block", 27 | 23 => "Dispenser", 28 | 24 => "Sandstone", 29 | 25 => "Note Block", 30 | 31 | 35 => "Wool", 32 | 33 | 43 => "Double Slab", 34 | 44 => "Slab", 35 | 45 => "Brick", 36 | 46 => "TNT", 37 | 38 | 49 => "Obsidian", 39 | 40 | 53 => "Wood Stair", 41 | 54 => "Chest", 42 | 43 | 61 => "Furnace", 44 | 45 | 67 => "Cobblestone Stair", 46 | 47 | 79 => "Ice", 48 | 49 | 89 => "Glowstone", 50 | 51 | ); 52 | 53 | $food = array( 54 | 282 => 8, //Stew 55 | 364 => 8, //Steak 56 | 320 => 8, //Porkchop 57 | 366 => 6, //Chicken 58 | 297 => 5, //Bread 59 | 350 => 5, //Fish 60 | 260 => 4, //R Apple 61 | 322 => 4, //G Apple 62 | 363 => 3, //Raw Beef 63 | 319 => 3, //Raw Porkchop 64 | 360 => 2, //Melon 65 | 349 => 2, //Raw fish 66 | 265 => 2, //Raw Chicken 67 | 357 => 1, //Cookie 68 | 367 => 4, //Flesh 69 | 375 => 2, //Spider eye, 70 | ); 71 | 72 | 73 | ?> -------------------------------------------------------------------------------- /nbt.class.php: -------------------------------------------------------------------------------- 1 | 6 | * @version 1.0 7 | * 8 | * Dependencies: 9 | * PHP 4.3+ (5.3+ recommended) 10 | * GMP Extension 11 | */ 12 | 13 | extension_loaded("gmp") or trigger_error ( 14 | "The NBT class requires the GMP extension for 64-bit number handling. ". 15 | "Excecution will continue, but will halt if a 64-bit number is handled.", E_USER_NOTICE 16 | ); 17 | 18 | class NBT { 19 | public $root = array(); 20 | 21 | public $verbose = false; 22 | 23 | const TAG_END = 0; 24 | const TAG_BYTE = 1; 25 | const TAG_SHORT = 2; 26 | const TAG_INT = 3; 27 | const TAG_LONG = 4; 28 | const TAG_FLOAT = 5; 29 | const TAG_DOUBLE = 6; 30 | const TAG_BYTE_ARRAY = 7; 31 | const TAG_STRING = 8; 32 | const TAG_LIST = 9; 33 | const TAG_COMPOUND = 10; 34 | 35 | public function loadFile($filename, $wrapper = "compress.zlib://") { 36 | if(is_string($wrapper) && is_file($filename)) { 37 | if($this->verbose) trigger_error("Loading file \"{$filename}\" with stream wrapper \"{$wrapper}\".", E_USER_NOTICE); 38 | $fp = fopen("{$wrapper}{$filename}", "rb"); 39 | } elseif(is_null($wrapper) && is_resource($filename)) { 40 | if($this->verbose) trigger_error("Loading file from existing resource.", E_USER_NOTICE); 41 | $fp = $filename; 42 | } else { 43 | trigger_error("First parameter must be a filename or a resource.", E_USER_WARNING); 44 | return false; 45 | } 46 | if($this->verbose) trigger_error("Traversing first tag in file.", E_USER_NOTICE); 47 | $this->traverseTag($fp, $this->root); 48 | if($this->verbose) trigger_error("Encountered end tag for first tag; finished.", E_USER_NOTICE); 49 | return end($this->root); 50 | } 51 | 52 | public function writeFile($filename, $wrapper = "compress.zlib://") { 53 | if(is_string($wrapper)) { 54 | if($this->verbose) trigger_error("Writing file \"{$filename}\" with stream wrapper \"{$wrapper}\".", E_USER_NOTICE); 55 | $fp = fopen("{$wrapper}{$filename}", "wb"); 56 | } elseif(is_null($wrapper) && is_resource($fp)) { 57 | if($this->verbose) trigger_error("Writing file to existing resource.", E_USER_NOTICE); 58 | $fp = $filename; 59 | } else { 60 | trigger_error("First parameter must be a filename or a resource.", E_USER_WARNING); 61 | return false; 62 | } 63 | if($this->verbose) trigger_error("Writing ".count($this->root)." root tag(s) to file/resource.", E_USER_NOTICE); 64 | foreach($this->root as $rootNum => $rootTag) if(!$this->writeTag($fp, $rootTag)) trigger_error("Failed to write root tag #{$rootNum} to file/resource.", E_USER_WARNING); 65 | return true; 66 | } 67 | 68 | public function purge() { 69 | if($this->verbose) trigger_error("Purging all loaded data", E_USER_ERROR); 70 | $this->root = array(); 71 | } 72 | 73 | public function traverseTag($fp, &$tree) { 74 | if(feof($fp)) { 75 | if($this->verbose) trigger_error("Reached end of file/resource.", E_USER_NOTICE); 76 | return false; 77 | } 78 | $tagType = $this->readType($fp, self::TAG_BYTE); // Read type byte. 79 | if($tagType == self::TAG_END) { 80 | return false; 81 | } else { 82 | if($this->verbose) $position = ftell($fp); 83 | $tagName = $this->readType($fp, self::TAG_STRING); 84 | if($this->verbose) trigger_error("Reading tag \"{$tagName}\" at offset {$position}.", E_USER_NOTICE); 85 | $tagData = $this->readType($fp, $tagType); 86 | $tree[] = array("type"=>$tagType, "name"=>$tagName, "value"=>$tagData); 87 | return true; 88 | } 89 | } 90 | 91 | public function writeTag($fp, $tag) { 92 | if($this->verbose) { 93 | $position = ftell($fp); 94 | trigger_error("Writing tag \"{$tag["name"]}\" of type {$tag["type"]} at offset {$position}.", E_USER_NOTICE); 95 | } 96 | return $this->writeType($fp, self::TAG_BYTE, $tag["type"]) && $this->writeType($fp, self::TAG_STRING, $tag["name"]) && $this->writeType($fp, $tag["type"], $tag["value"]); 97 | } 98 | 99 | public function readType($fp, $tagType) { 100 | switch($tagType) { 101 | case self::TAG_BYTE: // Signed byte (8 bit) 102 | list(,$unpacked) = unpack("c", fread($fp, 1)); 103 | return $unpacked; 104 | case self::TAG_SHORT: // Signed short (16 bit, big endian) 105 | list(,$unpacked) = unpack("n", fread($fp, 2)); 106 | if($unpacked >= pow(2, 15)) $unpacked -= pow(2, 16); // Convert unsigned short to signed short. 107 | return $unpacked; 108 | case self::TAG_INT: // Signed integer (32 bit, big endian) 109 | list(,$unpacked) = unpack("N", fread($fp, 4)); 110 | if($unpacked >= pow(2, 31)) $unpacked -= pow(2, 32); // Convert unsigned int to signed int 111 | return $unpacked; 112 | case self::TAG_LONG: // Signed long (64 bit, big endian) 113 | extension_loaded("gmp") or trigger_error ( 114 | "This file contains a 64-bit number and execution cannot continue. ". 115 | "Please install the GMP extension for 64-bit number handling.", E_USER_ERROR 116 | ); 117 | list(,$firstHalf) = unpack("N", fread($fp, 4)); 118 | list(,$secondHalf) = unpack("N", fread($fp, 4)); 119 | $value = gmp_add($secondHalf, gmp_mul($firstHalf, "4294967296")); 120 | if(gmp_cmp($value, gmp_pow(2, 63)) >= 0) $value = gmp_sub($value, gmp_pow(2, 64)); 121 | return gmp_strval($value); 122 | case self::TAG_FLOAT: // Floating point value (32 bit, big endian, IEEE 754-2008) 123 | list(,$value) = (pack('d', 1) == "\77\360\0\0\0\0\0\0")?unpack('f', fread($fp, 4)):unpack('f', strrev(fread($fp, 4))); 124 | return $value; 125 | case self::TAG_DOUBLE: // Double value (64 bit, big endian, IEEE 754-2008) 126 | list(,$value) = (pack('d', 1) == "\77\360\0\0\0\0\0\0")?unpack('d', fread($fp, 8)):unpack('d', strrev(fread($fp, 8))); 127 | return $value; 128 | case self::TAG_BYTE_ARRAY: // Byte array 129 | $arrayLength = $this->readType($fp, self::TAG_INT); 130 | $array = array(); 131 | for($i = 0; $i < $arrayLength; $i++) $array[] = $this->readType($fp, self::TAG_BYTE); 132 | return $array; 133 | case self::TAG_STRING: // String 134 | if(!$stringLength = $this->readType($fp, self::TAG_SHORT)) return ""; 135 | $string = utf8_decode(fread($fp, $stringLength)); // Read in number of bytes specified by string length, and decode from utf8. 136 | return $string; 137 | case self::TAG_LIST: // List 138 | $tagID = $this->readType($fp, self::TAG_BYTE); 139 | $listLength = $this->readType($fp, self::TAG_INT); 140 | if($this->verbose) trigger_error("Reading in list of {$listLength} tags of type {$tagID}.", E_USER_NOTICE); 141 | $list = array("type"=>$tagID, "value"=>array()); 142 | for($i = 0; $i < $listLength; $i++) { 143 | if(feof($fp)) break; 144 | $list["value"][] = $this->readType($fp, $tagID); 145 | } 146 | return $list; 147 | case self::TAG_COMPOUND: // Compound 148 | $tree = array(); 149 | while($this->traverseTag($fp, $tree)); 150 | return $tree; 151 | } 152 | } 153 | 154 | public function writeType($fp, $tagType, $value) { 155 | switch($tagType) { 156 | case self::TAG_BYTE: // Signed byte (8 bit) 157 | return is_int(fwrite($fp, pack("c", $value))); 158 | case self::TAG_SHORT: // Signed short (16 bit, big endian) 159 | if($value < 0) $value += pow(2, 16); // Convert signed short to unsigned short 160 | return is_int(fwrite($fp, pack("n", $value))); 161 | case self::TAG_INT: // Signed integer (32 bit, big endian) 162 | if($value < 0) $value += pow(2, 32); // Convert signed int to unsigned int 163 | return is_int(fwrite($fp, pack("N", $value))); 164 | case self::TAG_LONG: // Signed long (64 bit, big endian) 165 | extension_loaded("gmp") or trigger_error ( 166 | "This file contains a 64-bit number and execution cannot continue. ". 167 | "Please install the GMP extension for 64-bit number handling.", E_USER_ERROR 168 | ); 169 | $secondHalf = gmp_mod($value, 2147483647); 170 | $firstHalf = gmp_sub($value, $secondHalf); 171 | return is_int(fwrite($fp, pack("N", gmp_intval($firstHalf)))) && is_int(fwrite($fp, pack("N", gmp_intval($secondHalf)))); 172 | case self::TAG_FLOAT: // Floating point value (32 bit, big endian, IEEE 754-2008) 173 | return is_int(fwrite($fp, (pack('d', 1) == "\77\360\0\0\0\0\0\0")?pack('f', $value):strrev(pack('f', $value)))); 174 | case self::TAG_DOUBLE: // Double value (64 bit, big endian, IEEE 754-2008) 175 | return is_int(fwrite($fp, (pack('d', 1) == "\77\360\0\0\0\0\0\0")?pack('d', $value):strrev(pack('d', $value)))); 176 | case self::TAG_BYTE_ARRAY: // Byte array 177 | return $this->writeType($fp, self::TAG_INT, count($value)) && is_int(fwrite($fp, call_user_func_array("pack", array_merge(array("c".count($value)), $value)))); 178 | case self::TAG_STRING: // String 179 | $value = utf8_encode($value); 180 | return $this->writeType($fp, self::TAG_SHORT, strlen($value)) && is_int(fwrite($fp, $value)); 181 | case self::TAG_LIST: // List 182 | if($this->verbose) trigger_error("Writing list of ".count($value["value"])." tags of type {$value["type"]}.", E_USER_NOTICE); 183 | if(!($this->writeType($fp, self::TAG_BYTE, $value["type"]) && $this->writeType($fp, self::TAG_INT, count($value["value"])))) return false; 184 | foreach($value["value"] as $listItem) if(!$this->writeType($fp, $value["type"], $listItem)) return false; 185 | return true; 186 | case self::TAG_COMPOUND: // Compound 187 | foreach($value as $listItem) if(!$this->writeTag($fp, $listItem)) return false; 188 | if(!is_int(fwrite($fp, "\0"))) return false; 189 | return true; 190 | } 191 | } 192 | } 193 | ?> -------------------------------------------------------------------------------- /packets.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packets/03Chat.php: -------------------------------------------------------------------------------- 1 | "), $packet["message"]); 13 | $channel = ""; 14 | if(strpos($packet["message"], "]<") !== false){ 15 | $packet["message"] = explode("]<", substr($packet["message"],1)); 16 | $channel = $packet["message"][0]; 17 | $packet["message"] = "<".$packet["message"][1]; 18 | } 19 | $sender = false; 20 | $me = false; 21 | if($packet["message"]{0} == "["){ 22 | $sender = explode(".", substr($packet["message"],1,strpos($packet["message"], "->")-2)); 23 | $sender = isset($sender[1]) ? $sender[1]:$sender[0]; 24 | $packet["message"] = substr($packet["message"],strpos($packet["message"], "]")+2); 25 | if(strpos($packet["message"],": ")!==false){ 26 | $packet["message"] = explode("] ",$packet["message"]); 27 | $packet["message"] = trim($packet["message"][count($packet["message"])-1]); 28 | $sender = false; 29 | } 30 | }elseif(strpos($packet["message"], " whispers ") !== false){ 31 | $sender = substr($packet["message"],0,strpos($packet["message"], " ")); 32 | $packet["message"] = substr($packet["message"],strpos($packet["message"], " whispers ")+10); 33 | } 34 | if(stripos($packet["message"], "bot") !== false and $sender == false){ 35 | 36 | 37 | 38 | if($packet["message"]{0} == "<"){ 39 | $mess = substr($packet["message"],strpos($packet["message"], "> ")+2); 40 | $sender = explode(".", substr($packet["message"],1,strpos($packet["message"], "> ")-1)); 41 | }else{ 42 | $sender = explode(".", substr($packet["message"],0,strpos($packet["message"], ": "))); 43 | $mess = substr($packet["message"],strpos($packet["message"], ": ")+2); 44 | } 45 | $sender = isset($sender[1]) ? $sender[1]:$sender[0]; 46 | 47 | if(strtolower(substr($mess,0,3)) != "bot"){ 48 | $sender = false; 49 | }else{ 50 | $me = true; 51 | $packet["message"] = substr($mess, ($mess{4} == " " ? 5:4)); 52 | } 53 | } 54 | 55 | $mp = false; 56 | if(($sender !== false and $sender != "me" and $sender != "yo") or $me == true){ 57 | $mp = true; 58 | $value = explode(" ", $packet["message"]); 59 | $command = strtolower($value[0]); 60 | unset($value[0]); 61 | $value = implode(" ",$value); 62 | if(!command($command, $value, $sender)){ 63 | include("chat_help.php"); 64 | } 65 | return "[$sender --> me] ".$packet["message"]; 66 | }else{ 67 | if($packet["message"]{0} == "<"){ 68 | $sender = explode(".", substr($packet["message"],1,strpos($packet["message"], "> ")-1)); 69 | }else{ 70 | $sender = explode(".", substr($packet["message"],0,strpos($packet["message"], ": ")-1)); 71 | } 72 | $sender = isset($sender[1]) ? $sender[1]:$sender[0]; 73 | include("chat_help.php"); 74 | return $packet["message"]; 75 | } 76 | } 77 | 78 | function privateMessage($message, $target){ 79 | foreach(explode("\n", wordwrap($message,100-strlen("/tell $target "), "\n")) as $mess){ 80 | write_packet("03", array( 81 | "message" => "/tell $target $mess", 82 | )); 83 | } 84 | console("[me --> $target] ".$message); 85 | } 86 | 87 | function Message($message){ 88 | foreach(explode("\n", wordwrap($message,100, "\n")) as $mess){ 89 | write_packet("03", array( 90 | "message" => $mess, 91 | )); 92 | } 93 | } 94 | ?> -------------------------------------------------------------------------------- /pstruct.php: -------------------------------------------------------------------------------- 1 | array( 11 | "int", 12 | ), 13 | 14 | "01" => array( 15 | "int", 16 | "string", 17 | "string", 18 | "int", 19 | "int", 20 | "byte", 21 | "ubyte", 22 | "ubyte", 23 | ), 24 | 25 | "02" => array( 26 | "string", 27 | ), 28 | 29 | "03" => array( 30 | "string", 31 | ), 32 | 33 | "04" => array( 34 | "long", 35 | ), 36 | 37 | "05" => array( 38 | "int", 39 | "short", 40 | "short", 41 | "short", 42 | ), 43 | 44 | "06" => array( 45 | "int", 46 | "int", 47 | "int", 48 | ), 49 | 50 | "08" => array( 51 | "short", 52 | "short", 53 | "float", 54 | ), 55 | 56 | "09" => array( 57 | "int", 58 | "byte", 59 | "byte", 60 | "short", 61 | "string", 62 | ), 63 | 64 | "0d" => array( 65 | "double", 66 | "double", 67 | "double", 68 | "double", 69 | "float", 70 | "float", 71 | "bool", 72 | ), 73 | 74 | "10" => array( 75 | "short", 76 | ), 77 | 78 | "11" => array( 79 | "int", 80 | "byte", 81 | "int", 82 | "byte", 83 | "int", 84 | ), 85 | 86 | "12" => array( 87 | "int", 88 | "byte", 89 | ), 90 | 91 | "14" => array( 92 | "int", 93 | "string", 94 | "int", 95 | "int", 96 | "int", 97 | "byte", 98 | "byte", 99 | "short", 100 | ), 101 | 102 | "15" => array( 103 | "int", 104 | "short", 105 | "byte", 106 | "short", 107 | "int", 108 | "int", 109 | "int", 110 | "byte", 111 | "byte", 112 | "byte", 113 | ), 114 | 115 | "16" => array( 116 | "int", 117 | "int", 118 | ), 119 | 120 | "17" => array( 121 | "int", 122 | "byte", 123 | "int", 124 | "int", 125 | "int", 126 | "int", //if >0, fireball 127 | "short", 128 | "short", 129 | "short", 130 | ), 131 | 132 | "18" => array( 133 | "int", 134 | "byte", 135 | "int", 136 | "int", 137 | "int", 138 | "byte", 139 | "byte", 140 | "byte", 141 | "entityMetadata", 142 | ), 143 | 144 | "19" => array( 145 | "int", 146 | "string", 147 | "int", 148 | "int", 149 | "int", 150 | "int", 151 | ), 152 | 153 | "1a" => array( 154 | "int", 155 | "int", 156 | "int", 157 | "int", 158 | "short", 159 | ), 160 | 161 | "1b" => array( 162 | "float", 163 | "float", 164 | "float", 165 | "float", 166 | "bool", 167 | "bool", 168 | ), 169 | 170 | "1c" => array( 171 | "int", 172 | "short", 173 | "short", 174 | "short", 175 | ), 176 | 177 | "1d" => array( 178 | "int", 179 | ), 180 | 181 | "1e" => array( 182 | "int", 183 | ), 184 | 185 | "1f" => array( 186 | "int", 187 | "byte", 188 | "byte", 189 | "byte", 190 | ), 191 | 192 | "20" => array( 193 | "int", 194 | "byte", 195 | "byte", 196 | ), 197 | 198 | "21" => array( 199 | "int", 200 | "byte", 201 | "byte", 202 | "byte", 203 | "byte", 204 | "byte", 205 | ), 206 | 207 | "22" => array( 208 | "int", 209 | "int", 210 | "int", 211 | "int", 212 | "byte", 213 | "byte", 214 | ), 215 | 216 | "23" => array( 217 | "int", 218 | "byte", 219 | ), 220 | 221 | "26" => array( 222 | "int", 223 | "byte", 224 | ), 225 | 226 | "27" => array( 227 | "int", 228 | "int", 229 | ), 230 | 231 | "28" => array( 232 | "int", 233 | "entityMetadata", 234 | ), 235 | 236 | "29" => array( 237 | "int", 238 | "byte", 239 | "byte", 240 | "short", 241 | ), 242 | 243 | "2a" => array( 244 | "int", 245 | "byte", 246 | ), 247 | 248 | "2b" => array( 249 | "float", 250 | "short", 251 | "short", 252 | ), 253 | 254 | "32" => array( 255 | "int", 256 | "int", 257 | "bool", 258 | ), 259 | 260 | "33" => array( 261 | "int", 262 | "int", 263 | "bool", 264 | "short", 265 | "short", 266 | "int", 267 | "int", 268 | "newChunkArray", 269 | ), 270 | 271 | "34" => array( 272 | "int", 273 | "int", 274 | "short", 275 | "int", 276 | "newMultiblockArray", 277 | ), 278 | 279 | "35" => array( 280 | "int", 281 | "byte", 282 | "int", 283 | "byte", 284 | "byte", 285 | ), 286 | 287 | "36" => array( 288 | "int", 289 | "short", 290 | "int", 291 | "byte", 292 | "byte", 293 | ), 294 | 295 | "3c" => array( 296 | "double", 297 | "double", 298 | "double", 299 | "float", 300 | "int", 301 | "explosionRecord" 302 | ), 303 | 304 | "3d" => array( 305 | "int", 306 | "int", 307 | "byte", 308 | "int", 309 | "int", 310 | ), 311 | 312 | "46" => array( 313 | "byte", 314 | "byte", 315 | ), 316 | 317 | "47" => array( 318 | "int", 319 | "bool", 320 | "int", 321 | "int", 322 | "int", 323 | ), 324 | 325 | "64" => array( 326 | "byte", 327 | "byte", 328 | "string", 329 | "byte", 330 | ), 331 | 332 | "65" => array( 333 | "byte", 334 | ), 335 | 336 | "67" => array( 337 | "byte", 338 | "short", 339 | "slotData", 340 | ), 341 | 342 | "68" => array( 343 | "byte", 344 | "short", 345 | "slotArray", 346 | ), 347 | 348 | "69" => array( 349 | "byte", 350 | "short", 351 | "short", 352 | ), 353 | 354 | "6a" => array( 355 | "byte", 356 | "short", 357 | "bool", 358 | ), 359 | 360 | "6b" => array( 361 | "short", 362 | "slotData", 363 | ), 364 | 365 | "6c" => array( 366 | "byte", 367 | 368 | ), 369 | 370 | "82" => array( 371 | "int", 372 | "short", 373 | "int", 374 | "string", 375 | "string", 376 | "string", 377 | "string", 378 | ), 379 | 380 | "83" => array( 381 | "short", 382 | "short", 383 | "ubyte", 384 | "byteArray", 385 | ), 386 | 387 | "84" => array( 388 | "int", 389 | "short", 390 | "int", 391 | "byte", 392 | "int", 393 | "int", 394 | "int", 395 | ), 396 | 397 | "c8" => array( 398 | "int", 399 | "byte", 400 | ), 401 | 402 | "c9" => array( 403 | "string", 404 | "byte", 405 | "short", 406 | ), 407 | 408 | "ca" => array( 409 | "bool", 410 | "bool", 411 | "bool", 412 | "bool", 413 | ), 414 | 415 | "cb" => array( 416 | "string", 417 | ), 418 | 419 | "fa" => array( 420 | "string", 421 | "short", 422 | "byteArray", 423 | ), 424 | 425 | "fe" => array( 426 | "string", 427 | ), 428 | 429 | "ff" => array( 430 | "string", 431 | ), 432 | ); 433 | 434 | 435 | ?> 436 | -------------------------------------------------------------------------------- /pstruct_modifier.php: -------------------------------------------------------------------------------- 1 | = 23){ 7 | unset($pstruct["1b"]); 8 | } 9 | 10 | if($protocol <= 23){ 11 | $pstruct["01"] = array( 12 | "int", 13 | "string", 14 | "long", 15 | "string", 16 | "int", 17 | "byte", 18 | "byte", 19 | "ubyte", 20 | "ubyte", 21 | ); 22 | $pstruct["09"] = array( 23 | "byte", 24 | "byte", 25 | "byte", 26 | "short", 27 | "long", 28 | "string", 29 | ); 30 | $pstruct["18"] = array( 31 | "int", 32 | "byte", 33 | "int", 34 | "int", 35 | "int", 36 | "byte", 37 | "byte", 38 | "entityMetadata", 39 | ); 40 | $pstruct["33"] = array( 41 | "int", 42 | "short", 43 | "int", 44 | "byte", 45 | "byte", 46 | "byte", 47 | "int", 48 | "chunkArray", 49 | ); 50 | 51 | $pstruct["34"] = array( 52 | "int", 53 | "int", 54 | "short", 55 | "multiblockArray", 56 | ); 57 | } 58 | 59 | if($protocol <= 22){ 60 | $pstruct["09"] = array( 61 | "byte", 62 | "byte", 63 | "byte", 64 | "short", 65 | "long", 66 | ); 67 | $pstruct["01"] = array( 68 | "int", 69 | "string", 70 | "long", 71 | "int", 72 | "byte", 73 | "byte", 74 | "ubyte", 75 | "ubyte", 76 | ); 77 | } 78 | 79 | if($protocol <= 17){ 80 | $pstruct["2b"] = array( 81 | "byte", 82 | "byte", 83 | "short", 84 | ); 85 | } 86 | if($protocol <= 14){ 87 | $pstruct["00"] = array(); 88 | $pstruct["01"] = array( 89 | "int", 90 | "string", 91 | "long", 92 | "byte", 93 | ); 94 | $pstruct["46"] = array( 95 | "int", 96 | ); 97 | } 98 | 99 | ?> 100 | --------------------------------------------------------------------------------