From adbf56d7545f9f24fc4eb5c963d2540214498602 Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Pueyo Date: Tue, 18 Dec 2012 17:05:28 +0100 Subject: [PATCH] Implemented Java String.hashCode() for level seed --- classes/API/ServerAPI.php | 10 +++ classes/Java.class.php | 126 ++++++++++++++++++++++++++++++++++++++ common/dependencies.php | 1 + 3 files changed, 137 insertions(+) create mode 100644 classes/Java.class.php diff --git a/classes/API/ServerAPI.php b/classes/API/ServerAPI.php index c5259f9b2..f6520ae49 100644 --- a/classes/API/ServerAPI.php +++ b/classes/API/ServerAPI.php @@ -241,6 +241,16 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run $v = (int) $v; break; case "seed": + $v = trim($v); + if($v == "false"){ + $v = false; + }elseif(preg_match("/[^0-9\-]/", $v) > 0){ + $str = new Java_String($v); + $v = $str->hashCode(); + }else{ + $v = (int) $v; + } + break; case "server-id": $v = trim($v); $v = $v == "false" ? false:(preg_match("/[^0-9\-]/", $v) > 0 ? Utils::readInt(substr(md5($v, true), 0, 4)):$v); diff --git a/classes/Java.class.php b/classes/Java.class.php new file mode 100644 index 000000000..b7c9564bf --- /dev/null +++ b/classes/Java.class.php @@ -0,0 +1,126 @@ +value = (string) $string; + $this->count = strlen($this->value); + } + } + + public function __toString(){ + return $this->value; + } + + public function lenght(){ + return $this->count; + } + + public function isEmpty(){ + return $this->count === 0; + } + + public function charAt($index){ + $index = (int) $index; + if($index < 0 or $index >= $this->count){ + trigger_error("Undefined offset $index", E_USER_WARNING); + return false; + } + return $this->value{$index}; + } + + public function hashCode(){ + $h = $this->hash; + if($h === 0 and $this->count > 0){ + for($i = 0; $i < $this->count; ++$i){ + $h = (($h << 5) - $h) + ord($this->charAt($i)); + $h = $h & $h; + $this->hash = $h; + } + $this->hash = $h; + } + return $h; + } +} + + +class Java_Random{ + private $haveNextNextGaussian, $nextNextGaussian, $seed, $n1, $n2, $n3, $zero; + + public function __construct($seed = false){ + $this->n1 = new Math_BigInteger(0x5DEECE66D); + $this->n2 = new Math_BigInteger(1); + $this->n2 = $this->n2->bitwise_leftShift(48)->subtract($this->n2); + $this->n3 = new Math_BigInteger(0xB); + $this->zero = new Math_BigInteger(0); + if($seed === false){ + $seed = microtime(true) * 1000000; + } + $this->setSeed($seed); + } + + public function setSeed($seed){ + $seed = new Math_BigInteger($seed); + $this->seed = $seed->bitwise_xor($this->n1)->bitwise_and($this->n2); + $this->haveNextNextGaussian = false; + } + + protected function next($bits){ + $bits = (int) $bits; + $this->seed = $this->seed->multiply($this->n1)->add($this->n3)->bitwise_and($this->n2); + return $this->_tripleRightShift($this->seed, (48 - $bits)); + } + + private function _tripleRightShift($number, $places){ + if($number->compare($this->zero) >= 0){ + return $number->bitwise_rightShift($places); + } + $n1 = new Math_BigInteger(2); + return $number->bitwise_rightShift($places)->add($n1->bitwise_leftShift(~$places)); + } + + public function nextBytes($bytes){ + $bytes = (int) $bytes; + $b = b""; + $max = $bytes & ~0x3; + for($i = 0; $i < $max; $i += 4){ + $b .= $this->next(32)->toBytes(); + } + if($max < $bytes){ + $random = $this->next(32)->toBytes(); + for($j = $max; $j < $bytes; ++$j){ + $b .= $random{$j-$max}; + } + } + return $b; + } + +} \ No newline at end of file diff --git a/common/dependencies.php b/common/dependencies.php index ab18b0826..4808204d6 100644 --- a/common/dependencies.php +++ b/common/dependencies.php @@ -74,6 +74,7 @@ require_once("classes/Packet.class.php"); require_once("classes/Entity.class.php"); require_once("classes/ChunkParser.class.php"); require_once("classes/NBT.class.php"); +require_once("classes/Java.class.php"); require_once("classes/SerializedPacketHandler.class.php"); require_once("classes/CustomPacketHandler.class.php"); require_once("classes/MinecraftInterface.class.php");