mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 00:33:59 +00:00
Fixed a wide range of bugs with floating-point coordinates getting incorrectly int-casted
This causes lots of bugs in negative coordinates. This fixes #1789 after world load & save.
This commit is contained in:
parent
4e9e285e37
commit
e7e4645c0b
@ -1017,8 +1017,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$newOrder = [];
|
||||
$unloadChunks = $this->usedChunks;
|
||||
|
||||
$centerX = $this->x >> 4;
|
||||
$centerZ = $this->z >> 4;
|
||||
$centerX = $this->getFloorX() >> 4;
|
||||
$centerZ = $this->getFloorZ() >> 4;
|
||||
|
||||
for($x = 0; $x < $radius; ++$x){
|
||||
for($z = 0; $z <= $x; ++$z){
|
||||
@ -1127,9 +1127,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
$this->spawnPosition = new WeakPosition($pos->x, $pos->y, $pos->z, $level);
|
||||
$pk = new SetSpawnPositionPacket();
|
||||
$pk->x = (int) $this->spawnPosition->x;
|
||||
$pk->y = (int) $this->spawnPosition->y;
|
||||
$pk->z = (int) $this->spawnPosition->z;
|
||||
$pk->x = $this->spawnPosition->getFloorX();
|
||||
$pk->y = $this->spawnPosition->getFloorY();
|
||||
$pk->z = $this->spawnPosition->getFloorZ();
|
||||
$pk->spawnType = SetSpawnPositionPacket::TYPE_PLAYER_SPAWN;
|
||||
$pk->spawnForced = false;
|
||||
$this->dataPacket($pk);
|
||||
@ -1476,7 +1476,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$revert = true;
|
||||
}else{
|
||||
if($this->chunk === null or !$this->chunk->isGenerated()){
|
||||
$chunk = $this->level->getChunk($newPos->x >> 4, $newPos->z >> 4, false);
|
||||
$chunk = $this->level->getChunk($newPos->getFloorX() >> 4, $newPos->getFloorZ() >> 4, false);
|
||||
if($chunk === null or !$chunk->isGenerated()){
|
||||
$revert = true;
|
||||
$this->nextChunkOrderRun = 0;
|
||||
@ -3349,9 +3349,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
if($this->hasValidSpawnPosition()){
|
||||
$this->namedtag->setString("SpawnLevel", $this->spawnPosition->getLevel()->getFolderName());
|
||||
$this->namedtag->setInt("SpawnX", (int) $this->spawnPosition->x);
|
||||
$this->namedtag->setInt("SpawnY", (int) $this->spawnPosition->y);
|
||||
$this->namedtag->setInt("SpawnZ", (int) $this->spawnPosition->z);
|
||||
$this->namedtag->setInt("SpawnX", $this->spawnPosition->getFloorX());
|
||||
$this->namedtag->setInt("SpawnY", $this->spawnPosition->getFloorY());
|
||||
$this->namedtag->setInt("SpawnZ", $this->spawnPosition->getFloorZ());
|
||||
|
||||
if(!$this->isAlive()){
|
||||
//hack for respawn after quit
|
||||
|
@ -775,9 +775,9 @@ class Server{
|
||||
], NBT::TAG_Double),
|
||||
new StringTag("Level", $this->getDefaultLevel()->getFolderName()),
|
||||
//new StringTag("SpawnLevel", $this->getDefaultLevel()->getFolderName()),
|
||||
//new IntTag("SpawnX", (int) $spawn->x),
|
||||
//new IntTag("SpawnY", (int) $spawn->y),
|
||||
//new IntTag("SpawnZ", (int) $spawn->z),
|
||||
//new IntTag("SpawnX", $spawn->getFloorX()),
|
||||
//new IntTag("SpawnY", $spawn->getFloorY()),
|
||||
//new IntTag("SpawnZ", $spawn->getFloorZ()),
|
||||
//new ByteTag("SpawnForced", 1), //TODO
|
||||
new ListTag("Inventory", [], NBT::TAG_Compound),
|
||||
new ListTag("EnderChestInventory", [], NBT::TAG_Compound),
|
||||
@ -1103,8 +1103,8 @@ class Server{
|
||||
$this->getLogger()->notice($this->getLanguage()->translateString("pocketmine.level.backgroundGeneration", [$name]));
|
||||
|
||||
$spawnLocation = $level->getSpawnLocation();
|
||||
$centerX = $spawnLocation->x >> 4;
|
||||
$centerZ = $spawnLocation->z >> 4;
|
||||
$centerX = $spawnLocation->getFloorX() >> 4;
|
||||
$centerZ = $spawnLocation->getFloorZ() >> 4;
|
||||
|
||||
$order = [];
|
||||
|
||||
|
@ -83,7 +83,7 @@ class SpawnpointCommand extends VanillaCommand{
|
||||
}
|
||||
}elseif(count($args) <= 1){
|
||||
if($sender instanceof Player){
|
||||
$pos = new Position((int) $sender->x, (int) $sender->y, (int) $sender->z, $sender->getLevel());
|
||||
$pos = new Position($sender->getFloorX(), $sender->getFloorY(), $sender->getFloorZ(), $sender->getLevel());
|
||||
$target->setSpawn($pos);
|
||||
|
||||
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.spawnpoint.success", [$target->getName(), round($pos->x, 2), round($pos->y, 2), round($pos->z, 2)]));
|
||||
|
@ -484,7 +484,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
/** @var float[] $pos */
|
||||
$pos = $this->namedtag->getListTag("Pos")->getAllValues();
|
||||
|
||||
$this->chunk = $level->getChunk(((int) $pos[0]) >> 4, ((int) $pos[2]) >> 4, true);
|
||||
$this->chunk = $level->getChunk(((int) floor($pos[0])) >> 4, ((int) floor($pos[2])) >> 4, true);
|
||||
if($this->chunk === null){
|
||||
throw new \InvalidStateException("Cannot create entities in unloaded chunks");
|
||||
}
|
||||
@ -1757,14 +1757,16 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
}
|
||||
|
||||
protected function checkChunks(){
|
||||
if($this->chunk === null or ($this->chunk->getX() !== ($this->x >> 4) or $this->chunk->getZ() !== ($this->z >> 4))){
|
||||
$chunkX = $this->getFloorX() >> 4;
|
||||
$chunkZ = $this->getFloorZ() >> 4;
|
||||
if($this->chunk === null or ($this->chunk->getX() !== $chunkX or $this->chunk->getZ() !== $chunkZ)){
|
||||
if($this->chunk !== null){
|
||||
$this->chunk->removeEntity($this);
|
||||
}
|
||||
$this->chunk = $this->level->getChunk($this->x >> 4, $this->z >> 4, true);
|
||||
$this->chunk = $this->level->getChunk($chunkX, $chunkZ, true);
|
||||
|
||||
if(!$this->justCreated){
|
||||
$newChunk = $this->level->getChunkPlayers($this->x >> 4, $this->z >> 4);
|
||||
$newChunk = $this->level->getChunkPlayers($chunkX, $chunkZ);
|
||||
foreach($this->hasSpawned as $player){
|
||||
if(!isset($newChunk[$player->getLoaderId()])){
|
||||
$this->despawnFrom($player);
|
||||
|
@ -233,7 +233,7 @@ class Explosion{
|
||||
$pk->position = $this->source->asVector3();
|
||||
$pk->radius = $this->size;
|
||||
$pk->records = $send;
|
||||
$this->level->addChunkPacket($source->x >> 4, $source->z >> 4, $pk);
|
||||
$this->level->addChunkPacket($source->getFloorX() >> 4, $source->getFloorZ() >> 4, $pk);
|
||||
|
||||
$this->level->addParticle(new HugeExplodeSeedParticle($source));
|
||||
$this->level->broadcastLevelSoundEvent($source, LevelSoundEventPacket::SOUND_EXPLODE);
|
||||
|
@ -478,7 +478,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
if($players === null){
|
||||
foreach($pk as $e){
|
||||
$this->addChunkPacket($sound->x >> 4, $sound->z >> 4, $e);
|
||||
$this->addChunkPacket($sound->getFloorX() >> 4, $sound->getFloorZ() >> 4, $e);
|
||||
}
|
||||
}else{
|
||||
$this->server->batchPackets($players, $pk, false);
|
||||
@ -493,7 +493,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
if($players === null){
|
||||
foreach($pk as $e){
|
||||
$this->addChunkPacket($particle->x >> 4, $particle->z >> 4, $e);
|
||||
$this->addChunkPacket($particle->getFloorX() >> 4, $particle->getFloorZ() >> 4, $e);
|
||||
}
|
||||
}else{
|
||||
$this->server->batchPackets($players, $pk, false);
|
||||
@ -513,7 +513,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
$pk->data = $data;
|
||||
if($pos !== null){
|
||||
$pk->position = $pos->asVector3();
|
||||
$this->addChunkPacket($pos->x >> 4, $pos->z >> 4, $pk);
|
||||
$this->addChunkPacket($pos->getFloorX() >> 4, $pos->getFloorZ() >> 4, $pk);
|
||||
}else{
|
||||
$pk->position = null;
|
||||
$this->addGlobalPacket($pk);
|
||||
@ -538,7 +538,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
$pk->unknownBool = $unknown;
|
||||
$pk->disableRelativeVolume = $disableRelativeVolume;
|
||||
$pk->position = $pos->asVector3();
|
||||
$this->addChunkPacket($pos->x >> 4, $pos->z >> 4, $pk);
|
||||
$this->addChunkPacket($pos->getFloorX() >> 4, $pos->getFloorZ() >> 4, $pk);
|
||||
}
|
||||
|
||||
public function getAutoSave() : bool{
|
||||
@ -987,8 +987,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
$randRange = (int) ($randRange > $this->chunkTickRadius ? $this->chunkTickRadius : $randRange);
|
||||
|
||||
foreach($this->loaders as $loader){
|
||||
$chunkX = $loader->getX() >> 4;
|
||||
$chunkZ = $loader->getZ() >> 4;
|
||||
$chunkX = (int) floor($loader->getX()) >> 4;
|
||||
$chunkZ = (int) floor($loader->getZ()) >> 4;
|
||||
|
||||
$index = Level::chunkHash($chunkX, $chunkZ);
|
||||
$existingLoaders = max(0, $this->chunkTickList[$index] ?? 0);
|
||||
|
@ -89,9 +89,9 @@ abstract class BaseLevelProvider implements LevelProvider{
|
||||
}
|
||||
|
||||
public function setSpawn(Vector3 $pos){
|
||||
$this->levelData->setInt("SpawnX", (int) $pos->x);
|
||||
$this->levelData->setInt("SpawnY", (int) $pos->y);
|
||||
$this->levelData->setInt("SpawnZ", (int) $pos->z);
|
||||
$this->levelData->setInt("SpawnX", $pos->getFloorX());
|
||||
$this->levelData->setInt("SpawnY", $pos->getFloorY());
|
||||
$this->levelData->setInt("SpawnZ", $pos->getFloorZ());
|
||||
}
|
||||
|
||||
public function doGarbageCollection(){
|
||||
|
Loading…
x
Reference in New Issue
Block a user