mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-05 19:37:17 +00:00
Merge branch 'next-minor' into next-major
This commit is contained in:
commit
142ccc7e87
@ -95,6 +95,10 @@ Released 25th November 2022.
|
||||
- Improved performance of `ContainerTrait` dropping items on block destroy. ([link](https://github.com/pmmp/PocketMine-MP/commits/24e72ec109c1442b09558df89b6833cf2f2e0ec7))
|
||||
- Avoid repeated calls to `Position->getWorld()` (use local variables). ([link](https://github.com/pmmp/PocketMine-MP/commit/2940547026db40ce76deb46e992870de3ead79ad))
|
||||
- Revamped the way `InventoryManager` handles fake inventory slot mappings for stuff like crafting tables. ([link](https://github.com/pmmp/PocketMine-MP/commit/e90abecf38d9c57635fa0497514bba7e546a2469))
|
||||
- Inventories are now mapped on a per-slot basis. This means that more than one inventory can be mapped to the same window ID, which is necessary for correctly handling "UI" inventories like crafting tables.
|
||||
- `InventoryManager->getWindow(int $windowId) : ?Inventory` is replaced by `locateWindowAndSlot` (see below).
|
||||
- Added `InventoryManager->locateWindowAndSlot(int $windowId, int $netSlotId) : array{Inventory, int}` - accepts a window ID and absolute slot ID, and returns the associated inventory and the slot relative to the inventory's own start (for use with `getItem()` etc.).
|
||||
- Slot offset mapping for "UI" inventories is now handled in `InventoryManager->createComplexSlotMapping()` instead of in `TypeConverter`.
|
||||
- Console polling is now done on the main thread (no longer a performance concern). ([link](https://github.com/pmmp/PocketMine-MP/commit/b3f03d7ae645de67a54b7300c09b94eeca16298e))
|
||||
- Console reader subprocess should now automatically die if the server main process is killed, instead of persisting as a zombie. ([link](https://github.com/pmmp/PocketMine-MP/commit/2585160ca2c4df5758b8b980331307402ff9f0fb))
|
||||
- `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. ([link](https://github.com/pmmp/PocketMine-MP/commit/83e5b0adb6fa0dddec377182bb1c7945ac8f7820))
|
||||
|
@ -12,3 +12,9 @@ Released 30th November 2022.
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.50.
|
||||
- Removed support for older versions.
|
||||
|
||||
# 4.12.1
|
||||
Released 4th December 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed items glitching when dragging a stack of items across the crafting grid (desync issues).
|
||||
|
@ -73,6 +73,8 @@ final class EnchantmentIdMap{
|
||||
$this->register(EnchantmentIds::MENDING, VanillaEnchantments::MENDING());
|
||||
|
||||
$this->register(EnchantmentIds::VANISHING, VanillaEnchantments::VANISHING());
|
||||
|
||||
$this->register(EnchantmentIds::SWIFT_SNEAK, VanillaEnchantments::SWIFT_SNEAK());
|
||||
}
|
||||
|
||||
public function register(int $mcpeId, Enchantment $enchantment) : void{
|
||||
|
@ -66,4 +66,5 @@ final class EnchantmentIds{
|
||||
public const PIERCING = 34;
|
||||
public const QUICK_CHARGE = 35;
|
||||
public const SOUL_SPEED = 36;
|
||||
public const SWIFT_SNEAK = 37;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ final class StringToEnchantmentParser extends StringToTParser{
|
||||
$result->register("respiration", fn() => VanillaEnchantments::RESPIRATION());
|
||||
$result->register("sharpness", fn() => VanillaEnchantments::SHARPNESS());
|
||||
$result->register("silk_touch", fn() => VanillaEnchantments::SILK_TOUCH());
|
||||
$result->register("swift_sneak", fn() => VanillaEnchantments::SWIFT_SNEAK());
|
||||
$result->register("thorns", fn() => VanillaEnchantments::THORNS());
|
||||
$result->register("unbreaking", fn() => VanillaEnchantments::UNBREAKING());
|
||||
$result->register("vanishing", fn() => VanillaEnchantments::VANISHING());
|
||||
|
@ -49,6 +49,7 @@ use pocketmine\utils\RegistryTrait;
|
||||
* @method static Enchantment RESPIRATION()
|
||||
* @method static SharpnessEnchantment SHARPNESS()
|
||||
* @method static Enchantment SILK_TOUCH()
|
||||
* @method static Enchantment SWIFT_SNEAK()
|
||||
* @method static Enchantment THORNS()
|
||||
* @method static Enchantment UNBREAKING()
|
||||
* @method static Enchantment VANISHING()
|
||||
@ -95,6 +96,8 @@ final class VanillaEnchantments{
|
||||
self::register("MENDING", new Enchantment(KnownTranslationFactory::enchantment_mending(), Rarity::RARE, ItemFlags::NONE, ItemFlags::ALL, 1));
|
||||
|
||||
self::register("VANISHING", new Enchantment(KnownTranslationFactory::enchantment_curse_vanishing(), Rarity::MYTHIC, ItemFlags::NONE, ItemFlags::ALL, 1));
|
||||
|
||||
self::register("SWIFT_SNEAK", new Enchantment(KnownTranslationFactory::enchantment_swift_sneak(), Rarity::MYTHIC, ItemFlags::NONE, ItemFlags::LEGS, 3));
|
||||
}
|
||||
|
||||
protected static function register(string $name, Enchantment $member) : void{
|
||||
|
@ -193,8 +193,10 @@ class InventoryManager{
|
||||
*/
|
||||
public function addPredictedSlotChanges(array $networkInventoryActions) : void{
|
||||
foreach($networkInventoryActions as $action){
|
||||
if($action->sourceType === NetworkInventoryAction::SOURCE_CONTAINER && isset($this->windowMap[$action->windowId])){
|
||||
//this won't cover stuff like crafting grid due to too much magic
|
||||
if($action->sourceType === NetworkInventoryAction::SOURCE_CONTAINER && (
|
||||
isset($this->windowMap[$action->windowId]) ||
|
||||
($action->windowId === ContainerIds::UI && isset($this->complexSlotToWindowMap[$action->inventorySlot]))
|
||||
)){
|
||||
try{
|
||||
$item = TypeConverter::getInstance()->netItemStackToCore($action->newItem->getItemStack());
|
||||
}catch(TypeConversionException $e){
|
||||
|
@ -320,9 +320,7 @@ class InGamePacketHandler extends PacketHandler{
|
||||
$result = $this->handleReleaseItemTransaction($packet->trData);
|
||||
}
|
||||
|
||||
if(!$result){
|
||||
$this->inventoryManager->syncAll();
|
||||
}else{
|
||||
if($this->craftingTransaction === null){ //don't sync if we're waiting to complete a crafting transaction
|
||||
$this->inventoryManager->syncMismatchedPredictedSlotChanges();
|
||||
}
|
||||
return $result;
|
||||
@ -357,6 +355,7 @@ class InGamePacketHandler extends PacketHandler{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$this->inventoryManager->addPredictedSlotChanges($data->getActions());
|
||||
|
||||
if($isCraftingPart){
|
||||
if($this->craftingTransaction === null){
|
||||
@ -377,15 +376,9 @@ class InGamePacketHandler extends PacketHandler{
|
||||
}
|
||||
$this->player->setUsingItem(false);
|
||||
try{
|
||||
$this->inventoryManager->onTransactionStart($this->craftingTransaction);
|
||||
$this->craftingTransaction->execute();
|
||||
}catch(TransactionException $e){
|
||||
$this->session->getLogger()->debug("Failed to execute crafting transaction: " . $e->getMessage());
|
||||
|
||||
//TODO: only sync slots that the client tried to change
|
||||
foreach($this->craftingTransaction->getInventories() as $inventory){
|
||||
$this->inventoryManager->syncContents($inventory);
|
||||
}
|
||||
return false;
|
||||
}finally{
|
||||
$this->craftingTransaction = null;
|
||||
@ -405,18 +398,12 @@ class InGamePacketHandler extends PacketHandler{
|
||||
|
||||
$this->player->setUsingItem(false);
|
||||
$transaction = new InventoryTransaction($this->player, $actions);
|
||||
$this->inventoryManager->onTransactionStart($transaction);
|
||||
try{
|
||||
$transaction->execute();
|
||||
}catch(TransactionException $e){
|
||||
$logger = $this->session->getLogger();
|
||||
$logger->debug("Failed to execute inventory transaction: " . $e->getMessage());
|
||||
$logger->debug("Actions: " . json_encode($data->getActions()));
|
||||
|
||||
foreach($transaction->getInventories() as $inventory){
|
||||
$this->inventoryManager->syncContents($inventory);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -426,7 +413,6 @@ class InGamePacketHandler extends PacketHandler{
|
||||
|
||||
private function handleUseItemTransaction(UseItemTransactionData $data) : bool{
|
||||
$this->player->selectHotbarSlot($data->getHotbarSlot());
|
||||
$this->inventoryManager->addPredictedSlotChanges($data->getActions());
|
||||
|
||||
switch($data->getActionType()){
|
||||
case UseItemTransactionData::ACTION_CLICK_BLOCK:
|
||||
@ -512,9 +498,7 @@ class InGamePacketHandler extends PacketHandler{
|
||||
}
|
||||
|
||||
$this->player->selectHotbarSlot($data->getHotbarSlot());
|
||||
$this->inventoryManager->addPredictedSlotChanges($data->getActions());
|
||||
|
||||
//TODO: use transactiondata for rollbacks here
|
||||
switch($data->getActionType()){
|
||||
case UseItemOnEntityTransactionData::ACTION_INTERACT:
|
||||
$this->player->interactEntity($target, $data->getClickPosition());
|
||||
@ -529,14 +513,9 @@ class InGamePacketHandler extends PacketHandler{
|
||||
|
||||
private function handleReleaseItemTransaction(ReleaseItemTransactionData $data) : bool{
|
||||
$this->player->selectHotbarSlot($data->getHotbarSlot());
|
||||
$this->inventoryManager->addPredictedSlotChanges($data->getActions());
|
||||
|
||||
//TODO: use transactiondata for rollbacks here (resending entire inventory is very wasteful)
|
||||
switch($data->getActionType()){
|
||||
case ReleaseItemTransactionData::ACTION_RELEASE:
|
||||
if(!$this->player->releaseHeldItem()){
|
||||
$this->inventoryManager->syncContents($this->player->getInventory());
|
||||
}
|
||||
if($data->getActionType() == ReleaseItemTransactionData::ACTION_RELEASE){
|
||||
$this->player->releaseHeldItem();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\utils;
|
||||
|
||||
/**
|
||||
* This trait offers the same functionality as RegistryTrait, but also clones any returned objects to prevent outside
|
||||
* modification.
|
||||
*/
|
||||
trait CloningRegistryTrait{
|
||||
use RegistryTrait;
|
||||
|
||||
|
@ -23,6 +23,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\utils;
|
||||
|
||||
/**
|
||||
* This trait allows a class to simulate a Java-style enum. Members are exposed as static methods and handled via
|
||||
* __callStatic().
|
||||
*
|
||||
* Classes using this trait need to include \@method tags in their class docblock for every enum member.
|
||||
* Alternatively, just put \@generate-registry-docblock in the docblock and run tools/generate-registry-annotations.php
|
||||
*/
|
||||
trait EnumTrait{
|
||||
use RegistryTrait;
|
||||
use NotCloneable;
|
||||
|
@ -28,6 +28,13 @@ use function count;
|
||||
use function mb_strtoupper;
|
||||
use function preg_match;
|
||||
|
||||
/**
|
||||
* This trait allows a class to simulate object class constants, since PHP doesn't currently support this.
|
||||
* These faux constants are exposed in static class methods, which are handled using __callStatic().
|
||||
*
|
||||
* Classes using this trait need to include \@method tags in their class docblock for every faux constant.
|
||||
* Alternatively, just put \@generate-registry-docblock in the docblock and run tools/generate-registry-annotations.php
|
||||
*/
|
||||
trait RegistryTrait{
|
||||
/**
|
||||
* @var object[]
|
||||
|
87
tools/decode-crashdump.php
Normal file
87
tools/decode-crashdump.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\tools\decode_crashdump;
|
||||
|
||||
use function array_pop;
|
||||
use function array_slice;
|
||||
use function base64_decode;
|
||||
use function count;
|
||||
use function file;
|
||||
use function file_put_contents;
|
||||
use function fwrite;
|
||||
use function implode;
|
||||
use function json_decode;
|
||||
use function json_encode;
|
||||
use function realpath;
|
||||
use function trim;
|
||||
use function zlib_decode;
|
||||
use const FILE_IGNORE_NEW_LINES;
|
||||
use const PHP_EOL;
|
||||
use const STDERR;
|
||||
|
||||
if(count($argv) === 2){
|
||||
$input = $argv[1];
|
||||
$output = "decoded.json";
|
||||
}elseif(count($argv) === 3){
|
||||
[, $input, $output] = $argv;
|
||||
}else{
|
||||
fwrite(STDERR, "Required arguments: input file, output file" . PHP_EOL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$lines = file($input, FILE_IGNORE_NEW_LINES);
|
||||
if($lines === false){
|
||||
fwrite(STDERR, "Unable to read file $input" . PHP_EOL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$start = -1;
|
||||
foreach($lines as $num => $line){
|
||||
if(trim($line) === "===BEGIN CRASH DUMP==="){
|
||||
$start = $num + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if($start === -1){
|
||||
fwrite(STDERR, "Crashdump encoded data not found in target file" . PHP_EOL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$data = array_slice($lines, $start);
|
||||
array_pop($data);
|
||||
|
||||
$zlibData = base64_decode(implode("", $data), true);
|
||||
if($zlibData === false){
|
||||
fwrite(STDERR, "Invalid encoded data in crashdump" . PHP_EOL);
|
||||
exit(1);
|
||||
}
|
||||
$decoded = zlib_decode($zlibData);
|
||||
if($decoded === false){
|
||||
fwrite(STDERR, "Invalid compressed data in crashdump" . PHP_EOL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
file_put_contents($output, json_encode(json_decode($decoded), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
echo "Wrote decoded crashdump to " . realpath($output) . PHP_EOL;
|
Loading…
x
Reference in New Issue
Block a user