Compare commits

...

13 Commits

Author SHA1 Message Date
e5bc4deb12 Release 4.11.0-BETA2 2022-11-13 14:29:59 +00:00
2fcff13578 World: added getter and setter for simulation radius 2022-11-12 23:32:12 +00:00
b4b8ef1c6b World: Improve performance of ticked chunk selection when lots of loaders use the same chunk
since we use the same simulation distance for every loader, multiple loaders on the same chunk will produce the same set of ticked chunks.
2022-11-12 22:21:30 +00:00
a3502a711d Merge branch 'stable' into next-minor 2022-11-12 17:01:58 +00:00
83ddcce987 World: Considerably simplify ticked chunk selection
WARNING: This WILL have a performance impact on larger servers, but that's the price to pay for having crops actually grow.

The old overengineered method for doing this was causing glacially slow crop growth, vanilla parity issues and really just didn't make much sense. This method is probably incorrect too, but it will at least produce visible results.
2022-11-12 16:57:35 +00:00
732dac6fc1 Player: revert accidental change from ef100b248b 2022-11-12 14:43:22 +00:00
d5e3636908 Timezone: Apparently timezone_id returned by timezone_abbreviations_list() may be null... 2022-11-12 14:40:37 +00:00
ef100b248b Improved doc comment for Internet::getIP() (#5406) 2022-11-12 13:52:49 +00:00
d03bbb0426 Implemented darkness effect (#5402) 2022-11-10 12:57:14 +00:00
93e661aa4e Removed useless @inheritDoc (#5399) 2022-11-09 13:40:35 +00:00
50efcf7424 Bump ramsey/uuid from 4.5.1 to 4.6.0 (#5400)
Bumps [ramsey/uuid](https://github.com/ramsey/uuid) from 4.5.1 to 4.6.0.
- [Release notes](https://github.com/ramsey/uuid/releases)
- [Changelog](https://github.com/ramsey/uuid/blob/4.x/CHANGELOG.md)
- [Commits](https://github.com/ramsey/uuid/compare/4.5.1...4.6.0)

---
updated-dependencies:
- dependency-name: ramsey/uuid
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-09 13:40:09 +00:00
a7ac6070dc Correct damage calculation for non-arrow projectiles (#5394) 2022-11-07 20:05:53 +00:00
069062f122 4.11.0-BETA2 is next 2022-11-07 15:18:09 +00:00
14 changed files with 81 additions and 31 deletions

View File

@ -65,3 +65,28 @@ Released 7th November 2022.
- Console reader subprocess should now automatically die if the server main process is killed, instead of persisting as a zombie.
- `ConsoleCommandSender` is no longer responsible for relaying broadcast messages to `MainLogger`. A new `BroadcastLoggerForwarder` has been added, which is subscribed to the appropriate server broadcast channels in order to relay messages. This ensures that chat messages and command audit messages are logged.
- `DelegateInventory` now uses `WeakReference` to track its inventory listener. This allows the delegate to be reused.
# 4.11.0-BETA2
Released 13th November 2022.
## Configuration
- The `chunk-ticking.per-tick` setting is now deprecated, and will be removed in a future release.
- The functionality of this setting has been removed, since it caused more problems than it solved.
- Setting it to zero will still disable chunk ticking (for now), but this should now be done by setting `chunk-ticking.tick-radius` to `0` instead.
## Gameplay
- Improved chunk random ticking:
- Removed the limit on chunks ticked per tick, and its associated config option is no longer respected.
- This change significantly improves crop and plant growth with large numbers of players, but may cause higher CPU usage.
- This limit was causing a linear decrease in chunk ticking speed with larger numbers of players, leading to worsened gameplay experience.
- Every chunk within the configured tick radius of a player will be ticked. Previously, chunks were randomly selected from the radius.
- Implemented Darkness effect.
## API
### `pocketmine\world`
- The following new API methods have been added:
- `public World->getChunkTickRadius() : int` - returns the world's simulation radius
- `public World->setChunkTickRadius(int $radius) : void` - sets the world's simulation radius
## Internals
- Non-arrow projectile damage is now unscaled. Scaling according to velocity is only applied to arrows. This currently doesn't cause any observable change in behaviour, but is required for future additions.

14
composer.lock generated
View File

@ -930,21 +930,20 @@
},
{
"name": "ramsey/uuid",
"version": "4.5.1",
"version": "4.6.0",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
"reference": "a161a26d917604dc6d3aa25100fddf2556e9f35d"
"reference": "ad63bc700e7d021039e30ce464eba384c4a1d40f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/a161a26d917604dc6d3aa25100fddf2556e9f35d",
"reference": "a161a26d917604dc6d3aa25100fddf2556e9f35d",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/ad63bc700e7d021039e30ce464eba384c4a1d40f",
"reference": "ad63bc700e7d021039e30ce464eba384c4a1d40f",
"shasum": ""
},
"require": {
"brick/math": "^0.8.8 || ^0.9 || ^0.10",
"ext-ctype": "*",
"ext-json": "*",
"php": "^8.0",
"ramsey/collection": "^1.0"
@ -976,7 +975,6 @@
},
"suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
"ext-ctype": "Enables faster processing of character classification using ctype functions.",
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
@ -1008,7 +1006,7 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.5.1"
"source": "https://github.com/ramsey/uuid/tree/4.6.0"
},
"funding": [
{
@ -1020,7 +1018,7 @@
"type": "tidelift"
}
],
"time": "2022-09-16T03:22:46+00:00"
"time": "2022-11-05T23:03:38+00:00"
},
{
"name": "symfony/filesystem",

View File

@ -119,8 +119,6 @@ chunk-sending:
spawn-radius: 4
chunk-ticking:
#Max amount of chunks processed each tick
per-tick: 40
#Radius of chunks around a player to tick
tick-radius: 3
#Number of blocks inside ticking areas' subchunks that get ticked every tick. Higher values will accelerate events

View File

@ -31,7 +31,7 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "4.11.0-BETA1";
public const BASE_VERSION = "4.11.0-BETA2";
public const IS_DEVELOPMENT_BUILD = false;
public const BUILD_CHANNEL = "beta";

View File

@ -74,6 +74,7 @@ final class EffectIdMap{
//TODO: SLOW_FALLING
//TODO: BAD_OMEN
//TODO: VILLAGE_HERO
$this->register(EffectIds::DARKNESS, VanillaEffects::DARKNESS());
}
//TODO: not a big fan of the code duplication here :(

View File

@ -58,4 +58,5 @@ final class EffectIds{
public const SLOW_FALLING = 27;
public const BAD_OMEN = 28;
public const VILLAGE_HERO = 29;
public const DARKNESS = 30;
}

View File

@ -40,6 +40,7 @@ final class StringToEffectParser extends StringToTParser{
$result->register("absorption", fn() => VanillaEffects::ABSORPTION());
$result->register("blindness", fn() => VanillaEffects::BLINDNESS());
$result->register("conduit_power", fn() => VanillaEffects::CONDUIT_POWER());
$result->register("darkness", fn() => VanillaEffects::DARKNESS());
$result->register("fatal_poison", fn() => VanillaEffects::FATAL_POISON());
$result->register("fire_resistance", fn() => VanillaEffects::FIRE_RESISTANCE());
$result->register("haste", fn() => VanillaEffects::HASTE());

View File

@ -36,6 +36,7 @@ use pocketmine\utils\RegistryTrait;
* @method static AbsorptionEffect ABSORPTION()
* @method static Effect BLINDNESS()
* @method static Effect CONDUIT_POWER()
* @method static Effect DARKNESS()
* @method static PoisonEffect FATAL_POISON()
* @method static Effect FIRE_RESISTANCE()
* @method static Effect HASTE()
@ -68,6 +69,7 @@ final class VanillaEffects{
//TODO: bad_omen
self::register("blindness", new Effect(KnownTranslationFactory::potion_blindness(), new Color(0x1f, 0x1f, 0x23), true));
self::register("conduit_power", new Effect(KnownTranslationFactory::potion_conduitPower(), new Color(0x1d, 0xc2, 0xd1)));
self::register("darkness", new Effect(KnownTranslationFactory::effect_darkness(), new Color(0x29, 0x27, 0x21), true, 600, false));
self::register("fatal_poison", new PoisonEffect(KnownTranslationFactory::potion_poison(), new Color(0x4e, 0x93, 0x31), true, 600, true, true));
self::register("fire_resistance", new Effect(KnownTranslationFactory::potion_fireResistance(), new Color(0xe4, 0x9a, 0x3a)));
self::register("haste", new Effect(KnownTranslationFactory::potion_digSpeed(), new Color(0xd9, 0xc0, 0x43)));

View File

@ -38,6 +38,7 @@ use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
use pocketmine\player\Player;
use pocketmine\world\sound\ArrowHitSound;
use function ceil;
use function mt_rand;
use function sqrt;
@ -103,7 +104,7 @@ class Arrow extends Projectile{
}
public function getResultDamage() : int{
$base = parent::getResultDamage();
$base = (int) ceil($this->motion->length() * parent::getResultDamage());
if($this->isCritical()){
return ($base + mt_rand(0, (int) ($base / 2) + 1));
}else{

View File

@ -128,7 +128,7 @@ abstract class Projectile extends Entity{
* Returns the amount of damage this projectile will deal to the entity it hits.
*/
public function getResultDamage() : int{
return (int) ceil($this->motion->length() * $this->damage);
return (int) ceil($this->damage);
}
public function saveNBT() : CompoundTag{

View File

@ -2416,9 +2416,6 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$this->ySize = 0;
}
/**
* {@inheritdoc}
*/
public function teleport(Vector3 $pos, ?float $yaw = null, ?float $pitch = null) : bool{
if(parent::teleport($pos, $yaw, $pitch)){

View File

@ -70,7 +70,7 @@ class Internet{
public static $online = true;
/**
* Gets the External IP using an external service, it is cached
* Lazily gets the External IP using an external service and caches the result
*
* @param bool $force default false, force IP check even when cached
*

View File

@ -208,7 +208,7 @@ abstract class Timezone{
//That's been a bug in PHP since 2008!
foreach(timezone_abbreviations_list() as $zones){
foreach($zones as $timezone){
if($timezone['offset'] == $offset){
if($timezone['timezone_id'] !== null && $timezone['offset'] == $offset){
return $timezone['timezone_id'];
}
}

View File

@ -66,6 +66,7 @@ use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
use pocketmine\network\mcpe\protocol\ClientboundPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\player\ChunkSelector;
use pocketmine\player\Player;
use pocketmine\promise\Promise;
use pocketmine\promise\PromiseResolver;
@ -317,7 +318,6 @@ class World implements ChunkManager{
private int $sleepTicks = 0;
private int $chunkTickRadius;
private int $chunksPerTick;
private int $tickedBlocksPerSubchunkPerTick = self::DEFAULT_TICKED_BLOCKS_PER_SUBCHUNK_PER_TICK;
/**
* @var true[]
@ -493,7 +493,11 @@ class World implements ChunkManager{
$cfg = $this->server->getConfigGroup();
$this->chunkTickRadius = min($this->server->getViewDistance(), max(1, $cfg->getPropertyInt("chunk-ticking.tick-radius", 4)));
$this->chunksPerTick = $cfg->getPropertyInt("chunk-ticking.per-tick", 40);
if($cfg->getPropertyInt("chunk-ticking.per-tick", 40) <= 0){
//TODO: this needs l10n
$this->logger->warning("\"chunk-ticking.per-tick\" setting is deprecated, but you've used it to disable chunk ticking. Set \"chunk-ticking.tick-radius\" to 0 in \"pocketmine.yml\" instead.");
$this->chunkTickRadius = 0;
}
$this->tickedBlocksPerSubchunkPerTick = $cfg->getPropertyInt("chunk-ticking.blocks-per-subchunk-per-tick", self::DEFAULT_TICKED_BLOCKS_PER_SUBCHUNK_PER_TICK);
$this->maxConcurrentChunkPopulationTasks = $cfg->getPropertyInt("chunk-generation.population-queue-size", 2);
@ -1100,8 +1104,23 @@ class World implements ChunkManager{
unset($this->randomTickBlocks[$block->getFullId()]);
}
/**
* Returns the radius of chunks to be ticked around each ticking chunk loader (usually players). This is referred to
* as "simulation distance" in the Minecraft: Bedrock world options screen.
*/
public function getChunkTickRadius() : int{
return $this->chunkTickRadius;
}
/**
* Sets the radius of chunks ticked around each ticking chunk loader (usually players).
*/
public function setChunkTickRadius(int $radius) : void{
$this->chunkTickRadius = $radius;
}
private function tickChunks() : void{
if($this->chunksPerTick <= 0 || count($this->tickingLoaders) === 0){
if($this->chunkTickRadius <= 0 || count($this->tickingLoaders) === 0){
return;
}
@ -1110,19 +1129,26 @@ class World implements ChunkManager{
/** @var bool[] $chunkTickList chunkhash => dummy */
$chunkTickList = [];
$chunksPerLoader = min(200, max(1, (int) ((($this->chunksPerTick - count($this->tickingLoaders)) / count($this->tickingLoaders)) + 0.5)));
$randRange = 3 + $chunksPerLoader / 30;
$randRange = (int) ($randRange > $this->chunkTickRadius ? $this->chunkTickRadius : $randRange);
$centerChunks = [];
$selector = new ChunkSelector();
foreach($this->tickingLoaders as $loader){
$chunkX = (int) floor($loader->getX()) >> Chunk::COORD_BIT_SIZE;
$chunkZ = (int) floor($loader->getZ()) >> Chunk::COORD_BIT_SIZE;
$centerChunkX = (int) floor($loader->getX()) >> Chunk::COORD_BIT_SIZE;
$centerChunkZ = (int) floor($loader->getZ()) >> Chunk::COORD_BIT_SIZE;
$centerChunkPosHash = World::chunkHash($centerChunkX, $centerChunkZ);
if(isset($centerChunks[$centerChunkPosHash])){
//we already queued chunks in this radius because of a previous loader on the same chunk
continue;
}
$centerChunks[$centerChunkPosHash] = true;
for($chunk = 0; $chunk < $chunksPerLoader; ++$chunk){
$dx = mt_rand(-$randRange, $randRange);
$dz = mt_rand(-$randRange, $randRange);
$hash = World::chunkHash($dx + $chunkX, $dz + $chunkZ);
if(!isset($chunkTickList[$hash]) && isset($this->chunks[$hash]) && $this->isChunkTickable($dx + $chunkX, $dz + $chunkZ)){
foreach($selector->selectChunks(
$this->chunkTickRadius,
$centerChunkX,
$centerChunkZ
) as $hash){
World::getXZ($hash, $chunkX, $chunkZ);
if(!isset($chunkTickList[$hash]) && isset($this->chunks[$hash]) && $this->isChunkTickable($chunkX, $chunkZ)){
$chunkTickList[$hash] = true;
}
}