From 806d88ec20f35d738d58baa8d4db319fbdea3bdc Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 19 Oct 2025 00:34:14 +0100 Subject: [PATCH 1/4] Player: fixed suspicious ground state check fixes #3552 and #3553 for non-spectator-gamemode situations this would've caused problems if setHasBlockCollision(false) was used in other game modes --- src/player/Player.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/player/Player.php b/src/player/Player.php index e44f4c97d..f649de801 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -1304,7 +1304,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer, Nev } protected function checkGroundState(float $wantedX, float $wantedY, float $wantedZ, float $dx, float $dy, float $dz) : void{ - if($this->gamemode === GameMode::SPECTATOR){ + if(!$this->blockCollision){ $this->onGround = false; }else{ $bb = clone $this->boundingBox; From c92674a28582ea0a243feca2b6b1299875ae4673 Mon Sep 17 00:00:00 2001 From: Remminiscent Date: Sun, 19 Oct 2025 19:36:45 +0300 Subject: [PATCH 2/4] Short grass and ferns: add bone meal growth into double variants (#6845) --- src/block/TallGrass.php | 39 +++++++++++++++++++++++++++++++++++++ src/block/VanillaBlocks.php | 4 ++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/block/TallGrass.php b/src/block/TallGrass.php index 459751c4e..b56169dc8 100644 --- a/src/block/TallGrass.php +++ b/src/block/TallGrass.php @@ -25,14 +25,53 @@ namespace pocketmine\block; use pocketmine\block\utils\StaticSupportTrait; use pocketmine\block\utils\TallGrassTrait; +use pocketmine\item\Fertilizer; +use pocketmine\item\Item; use pocketmine\math\Facing; +use pocketmine\math\Vector3; +use pocketmine\player\Player; class TallGrass extends Flowable{ use TallGrassTrait; use StaticSupportTrait; + /** @phpstan-var \Closure() : DoublePlant|null */ + private ?\Closure $doublePlantVariant; + + /** + * @phpstan-param \Closure() : DoublePlant|null $doublePlantVariant + */ + public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo, ?\Closure $doublePlantVariant = null){ + parent::__construct($idInfo, $name, $typeInfo); + $this->doublePlantVariant = $doublePlantVariant; + } + private function canBeSupportedAt(Block $block) : bool{ $supportBlock = $block->getSide(Facing::DOWN); return $supportBlock->hasTypeTag(BlockTypeTags::DIRT) || $supportBlock->hasTypeTag(BlockTypeTags::MUD); } + + public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{ + $world = $this->position->getWorld(); + $upPos = $this->position->getSide(Facing::UP); + if(!$world->isInWorld($upPos->getFloorX(), $upPos->getFloorY(), $upPos->getFloorZ()) || $this->getSide(Facing::UP)->getTypeId() !== BlockTypeIds::AIR){ + return false; + } + + if($item instanceof Fertilizer && ($doubleVariant = $this->getDoublePlantVariant()) !== null){ + $bottom = (clone $doubleVariant)->setTop(false); + $top = (clone $doubleVariant)->setTop(true); + $world->setBlock($this->position, $bottom); + $world->setBlock($this->position->getSide(Facing::UP), $top); + $item->pop(); + + return true; + } + + return false; + } + + private function getDoublePlantVariant() : ?DoublePlant{ + return $this->doublePlantVariant !== null ? ($this->doublePlantVariant)() : null; + } } diff --git a/src/block/VanillaBlocks.php b/src/block/VanillaBlocks.php index fe3bbc254..026729c5c 100644 --- a/src/block/VanillaBlocks.php +++ b/src/block/VanillaBlocks.php @@ -1230,8 +1230,8 @@ final class VanillaBlocks{ self::register("sugarcane", fn(BID $id) => new Sugarcane($id, "Sugarcane", new Info(BreakInfo::instant()))); self::register("sweet_berry_bush", fn(BID $id) => new SweetBerryBush($id, "Sweet Berry Bush", new Info(BreakInfo::instant()))); self::register("tnt", fn(BID $id) => new TNT($id, "TNT", new Info(BreakInfo::instant()))); - self::register("fern", fn(BID $id) => new TallGrass($id, "Fern", new Info(BreakInfo::instant(ToolType::SHEARS, 1), [Tags::POTTABLE_PLANTS]))); - self::register("tall_grass", fn(BID $id) => new TallGrass($id, "Tall Grass", new Info(BreakInfo::instant(ToolType::SHEARS, 1)))); + self::register("fern", fn(BID $id) => new TallGrass($id, "Fern", new Info(BreakInfo::instant(ToolType::SHEARS, 1), [Tags::POTTABLE_PLANTS]), fn() => VanillaBlocks::LARGE_FERN())); + self::register("tall_grass", fn(BID $id) => new TallGrass($id, "Tall Grass", new Info(BreakInfo::instant(ToolType::SHEARS, 1)), fn() => VanillaBlocks::DOUBLE_TALLGRASS())); self::register("blue_torch", fn(BID $id) => new Torch($id, "Blue Torch", new Info(BreakInfo::instant()))); self::register("copper_torch", fn(BID $id) => new Torch($id, "Copper Torch", new Info(BreakInfo::instant()))); From e9eeaf9c617de4ca80547dbc40ed6635d26ec775 Mon Sep 17 00:00:00 2001 From: "Dylan T." Date: Sun, 19 Oct 2025 18:35:30 +0100 Subject: [PATCH 3/4] Trigger RestrictedActions Crowdin using cron job same reason for this as why we trigger the branch sync from here - we need to make sure the cron doesn't get disabled RestrictedActions can do things this repo can't - the old workflow would've failed because GH Actions doesn't have pull_request write perms here (which we can't grant because it would also allow it to approve PRs) --- .../crowdin-download-cron-trigger.yml | 32 +++++++++ .github/workflows/download-translations.yml | 66 ------------------- 2 files changed, 32 insertions(+), 66 deletions(-) create mode 100644 .github/workflows/crowdin-download-cron-trigger.yml delete mode 100644 .github/workflows/download-translations.yml diff --git a/.github/workflows/crowdin-download-cron-trigger.yml b/.github/workflows/crowdin-download-cron-trigger.yml new file mode 100644 index 000000000..935313eba --- /dev/null +++ b/.github/workflows/crowdin-download-cron-trigger.yml @@ -0,0 +1,32 @@ +#Since GitHub automatically disables cron actions after 60 days of repo inactivity, we need the active repo (PM) +#to trigger the branch merge workflow explicitly. This avoids the need for TOS-violating actions which we previously +#used to keep the restricted action active, as the workflow depends on the activity of this repo anyway. + +name: Trigger Crowdin download + +on: + schedule: + - cron: "0 21 * * *" + workflow_dispatch: #for testing + +jobs: + trigger: + name: Trigger Crowdin download RestrictedActions workflow + runs-on: ubuntu-22.04 + + steps: + - name: Generate access token + id: generate-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ vars.RESTRICTED_ACTIONS_DISPATCH_ID }} + private-key: ${{ secrets.RESTRICTED_ACTIONS_DISPATCH_KEY }} + owner: ${{ github.repository_owner }} + repositories: RestrictedActions + + - name: Dispatch branch sync restricted action + uses: peter-evans/repository-dispatch@v3 + with: + token: ${{ steps.generate-token.outputs.token }} + repository: ${{ github.repository_owner }}/RestrictedActions + event-type: pocketmine_mp_crowdin_download diff --git a/.github/workflows/download-translations.yml b/.github/workflows/download-translations.yml deleted file mode 100644 index b0b054d1b..000000000 --- a/.github/workflows/download-translations.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: Download new translations from Crowdin - -on: - schedule: - - cron: 0 21 * * * #every day at 9pm - workflow_dispatch: - -jobs: - download: - name: Download translations - runs-on: ubuntu-latest - - strategy: - matrix: - branch: - - stable - - minor-next - - major-next - fail-fast: false - - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ matrix.branch }} - - - name: Download translations - uses: crowdin/github-action@v2 - with: - upload_sources: false - upload_translations: false - download_translations: true - create_pull_request: false - push_translations: false - export_only_approved: true #irrespective of project config, only accept approved translations here - crowdin_branch_name: ${{ matrix.branch }} - env: - CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} - CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} - - - name: Post-process placeholders back into PocketMine format - working-directory: resources/translations - run: | - sed -i -r 's/\{([A-Za-z0-9]+)\}/\{%\1\}/g' *.ini - git diff - git status - - - name: Delete translation files with no translations - working-directory: resources/translations - run: | - for file in *.ini; do - if grep -q -P '^[A-Za-z0-9_\-\.]+=' $file; then - echo "Not empty: $file" - else - echo "Deleting empty file: $file" - rm "$file" - fi - done - - - name: Create Pull Request - uses: peter-evans/create-pull-request@v7 - with: - add-paths: '*.ini' - commit-message: 'New translations from Crowdin (${{ matrix.branch }})' - branch: crowdin-auto-fetch/${{ matrix.branch }} - title: 'New translations from Crowdin' - base: ${{ matrix.branch }} From 85ddcd17eb0a09d1e2665a064cf3e6f76ae073ef Mon Sep 17 00:00:00 2001 From: "Dylan T." Date: Sun, 19 Oct 2025 19:14:17 +0100 Subject: [PATCH 4/4] Trigger Crowdin upload via RestrictedActions --- .github/workflows/crowdin-upload-trigger.yml | 34 ++++++++++++++++++ .github/workflows/upload-translations.yml | 38 -------------------- 2 files changed, 34 insertions(+), 38 deletions(-) create mode 100644 .github/workflows/crowdin-upload-trigger.yml delete mode 100644 .github/workflows/upload-translations.yml diff --git a/.github/workflows/crowdin-upload-trigger.yml b/.github/workflows/crowdin-upload-trigger.yml new file mode 100644 index 000000000..4f6e39fae --- /dev/null +++ b/.github/workflows/crowdin-upload-trigger.yml @@ -0,0 +1,34 @@ +name: Upload translations to Crowdin + +on: + push: + paths: + - resources/translations/eng.ini + branches: + - stable + - minor-next + - major-next + workflow_dispatch: + +jobs: + upload: + name: Upload translations + runs-on: ubuntu-latest + + steps: + - name: Generate access token + id: generate-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ vars.RESTRICTED_ACTIONS_DISPATCH_ID }} + private-key: ${{ secrets.RESTRICTED_ACTIONS_DISPATCH_KEY }} + owner: ${{ github.repository_owner }} + repositories: RestrictedActions + + - name: Dispatch restricted action + uses: peter-evans/repository-dispatch@v3 + with: + token: ${{ steps.generate-token.outputs.token }} + repository: ${{ github.repository_owner }}/RestrictedActions + event-type: pocketmine_mp_crowdin_upload + client-payload: '{"branch": "${{ github.ref_name }}"}' diff --git a/.github/workflows/upload-translations.yml b/.github/workflows/upload-translations.yml deleted file mode 100644 index 6c8a1a398..000000000 --- a/.github/workflows/upload-translations.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Upload translations to Crowdin - -on: - push: - paths: - - resources/translations/eng.ini - branches: - - stable - - minor-next - - major-next - workflow_dispatch: - -jobs: - upload: - name: Upload translations - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v5 - - - name: Preprocess eng.ini placeholders so Crowdin can understand them - working-directory: resources/translations - run: | - sed -i -r 's/\{%([A-Za-z0-9]+)\}/\{\1\}/g' eng.ini - cat eng.ini - - - name: Upload eng.ini to Crowdin - uses: crowdin/github-action@v2 - with: - upload_sources: true - upload_translations: false - download_translations: false - create_pull_request: false - crowdin_branch_name: ${{ github.ref_name }} - env: - GITHUB_TOKEN: ${{ github.token }} - CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} - CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}