From 085e7f84140c3dbb916c120946f23ee946a75b86 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 29 Jul 2021 17:10:46 +0100 Subject: [PATCH 01/16] In case of fire ... --- chunkutils2.cpp | 2 + config.m4 | 2 +- config.w32 | 2 +- src/PhpLightArray.cpp | 14 +- src/PhpLightArray.h | 16 + src/PhpPalettedBlockArray.cpp | 28 +- src/PhpPalettedBlockArray.h | 2 - src/PhpPalettedBlockArrayObj.h | 4 + src/PhpSubChunk.cpp | 523 +++++++++++++++++++++++++++++++++ src/PhpSubChunk.h | 8 + src/PhpSubChunk_arginfo.h | 27 ++ src/ZendUtil.h | 13 + 12 files changed, 616 insertions(+), 25 deletions(-) create mode 100644 src/PhpSubChunk.cpp create mode 100644 src/PhpSubChunk.h create mode 100644 src/PhpSubChunk_arginfo.h diff --git a/chunkutils2.cpp b/chunkutils2.cpp index 68cd5cc..d081178 100644 --- a/chunkutils2.cpp +++ b/chunkutils2.cpp @@ -24,6 +24,7 @@ #include "src/PhpLightArray.h" #include "src/PhpPalettedBlockArray.h" +#include "src/PhpSubChunk.h" #include "src/PhpSubChunkConverter.h" extern "C" { @@ -38,6 +39,7 @@ PHP_MINIT_FUNCTION(chunkutils2) { register_light_array_class(); register_paletted_block_array_class(); + register_sub_chunk_class(); register_sub_chunk_converter_class(); return SUCCESS; } diff --git a/config.m4 b/config.m4 index da27f73..311fe24 100644 --- a/config.m4 +++ b/config.m4 @@ -8,7 +8,7 @@ if test "$PHP_CHUNKUTILS2" != "no"; then PHP_REQUIRE_CXX() dnl the 6th parameter here is required for C++ shared extensions - PHP_NEW_EXTENSION(chunkutils2, chunkutils2.cpp src/PhpLightArray.cpp src/PhpPalettedBlockArray.cpp src/PhpSubChunkConverter.cpp, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -std=c++14 -fno-strict-aliasing -DGSL_THROW_ON_CONTRACT_VIOLATION=1, yes) + PHP_NEW_EXTENSION(chunkutils2, chunkutils2.cpp src/PhpLightArray.cpp src/PhpPalettedBlockArray.cpp src/PhpSubChunk.cpp src/PhpSubChunkConverter.cpp, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -std=c++14 -fno-strict-aliasing -DGSL_THROW_ON_CONTRACT_VIOLATION=1, yes) PHP_SUBST(CHUNKUTILS2_SHARED_LIBADD) PHP_ADD_BUILD_DIR($ext_builddir/src, 1) PHP_ADD_BUILD_DIR($ext_builddir/lib, 1) diff --git a/config.w32 b/config.w32 index 504c360..46c6b76 100644 --- a/config.w32 +++ b/config.w32 @@ -8,7 +8,7 @@ if (PHP_CHUNKUTILS2 != "no") { ADD_FLAG("CFLAGS_CHUNKUTILS2", "/EHsc"); ADD_SOURCES( configure_module_dirname + "/src", - "PhpLightArray.cpp PhpPalettedBlockArray.cpp PhpSubChunkConverter.cpp", + "PhpLightArray.cpp PhpPalettedBlockArray.cpp PhpSubChunk.cpp PhpSubChunkConverter.cpp", "chunkutils2" ); } diff --git a/src/PhpLightArray.cpp b/src/PhpLightArray.cpp index 2b0ee02..dbb8346 100644 --- a/src/PhpLightArray.cpp +++ b/src/PhpLightArray.cpp @@ -14,11 +14,6 @@ extern "C" { zend_class_entry* light_array_entry; static zend_object_handlers light_array_handlers; -typedef struct { - LightArray lightArray; - zend_object std; -} light_array_obj; - /* internal object handlers */ static zend_object* light_array_new(zend_class_entry* class_type) { @@ -70,6 +65,10 @@ static int light_array_unserialize(zval* obj, zend_class_entry* ce, const unsign return SUCCESS; } +void light_array_fill(light_array_obj* object, zend_long level) { + new (&object->lightArray) LightArray(static_cast(level)); +} + ZEND_BEGIN_ARG_INFO_EX(arginfo_PhpLightArray___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, payload, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -110,8 +109,7 @@ PHP_METHOD(PhpLightArray, fill) { object_init_ex(return_value, light_array_entry); auto object = fetch_from_zend_object(Z_OBJ_P(return_value)); - - new (&object->lightArray) LightArray(static_cast(level)); + light_array_fill(object, level); } ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_PhpLightArray_get, 0, 3, IS_LONG, 0) @@ -213,7 +211,7 @@ void register_light_array_class() { light_array_handlers.clone_obj = light_array_clone; zend_class_entry ce; - INIT_CLASS_ENTRY(ce, "pocketmine\\world\\format\\LightArray", light_array_class_methods); + INIT_CLASS_ENTRY(ce, light_array_classname, light_array_class_methods); ce.create_object = light_array_new; ce.serialize = light_array_serialize; ce.unserialize = light_array_unserialize; diff --git a/src/PhpLightArray.h b/src/PhpLightArray.h index b1681a6..fa5bdf3 100644 --- a/src/PhpLightArray.h +++ b/src/PhpLightArray.h @@ -1,10 +1,17 @@ #ifndef HAVE_PHP_LIGHT_ARRAY_H #define HAVE_PHP_LIGHT_ARRAY_H +#include "lib/LightArray.h" + extern "C" { #include "php.h" } +typedef struct { + LightArray lightArray; + zend_object std; +} light_array_obj; + PHP_METHOD(PhpLightArray, __construct); PHP_METHOD(PhpLightArray, fill); PHP_METHOD(PhpLightArray, get); @@ -13,6 +20,15 @@ PHP_METHOD(PhpLightArray, getData); PHP_METHOD(PhpLightArray, collectGarbage); PHP_METHOD(PhpLightArray, isUniform); +extern zend_class_entry* light_array_entry; + +#define stringify_ex(macro) #macro +#define stringify(macro) stringify_ex(macro) + +#define light_array_classname "pocketmine\\world\\format\\LightArray" + +void light_array_fill(light_array_obj* object, zend_long level); + void register_light_array_class(); #endif diff --git a/src/PhpPalettedBlockArray.cpp b/src/PhpPalettedBlockArray.cpp index c427de7..94bac88 100644 --- a/src/PhpPalettedBlockArray.cpp +++ b/src/PhpPalettedBlockArray.cpp @@ -195,7 +195,18 @@ static int paletted_block_array_unserialize(zval *object, zend_class_entry *ce, return result; } - +bool paletted_block_array_fill(paletted_block_array_obj *intern, zend_long fillEntry) { + if (!checkPaletteEntrySize(fillEntry)) { + return false; + } + try { + new(&intern->container) NormalBlockArrayContainer((Block)fillEntry, 0); + } catch (std::exception& e) { + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "%s", e.what()); + return false; + } + return true; +} /* PHP-land PalettedBlockArray methods */ ZEND_BEGIN_ARG_INFO_EX(arginfo_PalettedBlockArray___construct, 0, 0, 1) @@ -209,20 +220,11 @@ PHP_METHOD(PhpPalettedBlockArray, __construct) { Z_PARAM_LONG(fillEntry) ZEND_PARSE_PARAMETERS_END(); - if (!checkPaletteEntrySize(fillEntry)) { - return; - } - paletted_block_array_obj *intern = fetch_from_zend_object(Z_OBJ_P(getThis())); - try { - new(&intern->container) NormalBlockArrayContainer((Block)fillEntry, 0); - } - catch (std::exception& e) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "%s", e.what()); - } + paletted_block_array_fill(intern, fillEntry); } -ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_PalettedBlockArray_fromData, 0, 3, pocketmine\\world\\format\\PalettedBlockArray, 0) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_PalettedBlockArray_fromData, 0, 3, paletted_block_array_classname, 0) ZEND_ARG_TYPE_INFO(0, bitsPerBlock, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, wordArray, IS_STRING, 0) ZEND_ARG_ARRAY_INFO(0, palette, 0) @@ -406,7 +408,7 @@ void register_paletted_block_array_class() { paletted_block_array_handlers.clone_obj = paletted_block_array_clone; zend_class_entry ce; - INIT_CLASS_ENTRY(ce, "pocketmine\\world\\format\\PalettedBlockArray", paletted_block_array_class_methods); + INIT_CLASS_ENTRY(ce, paletted_block_array_classname, paletted_block_array_class_methods); ce.create_object = paletted_block_array_new; ce.serialize = paletted_block_array_serialize; ce.unserialize = paletted_block_array_unserialize; diff --git a/src/PhpPalettedBlockArray.h b/src/PhpPalettedBlockArray.h index d361704..2b3337f 100644 --- a/src/PhpPalettedBlockArray.h +++ b/src/PhpPalettedBlockArray.h @@ -18,8 +18,6 @@ PHP_METHOD(PhpPalettedBlockArray, replace); PHP_METHOD(PhpPalettedBlockArray, replaceAll); PHP_METHOD(PhpPalettedBlockArray, getExpectedWordArraySize); -extern zend_class_entry *paletted_block_array_entry; - void register_paletted_block_array_class(); #endif diff --git a/src/PhpPalettedBlockArrayObj.h b/src/PhpPalettedBlockArrayObj.h index 4546c3e..f418d80 100644 --- a/src/PhpPalettedBlockArrayObj.h +++ b/src/PhpPalettedBlockArrayObj.h @@ -15,4 +15,8 @@ typedef struct { zend_object std; } paletted_block_array_obj; +extern zend_class_entry* paletted_block_array_entry; +#define paletted_block_array_classname "pocketmine\\world\\format\\PalettedBlockArray" + +bool paletted_block_array_fill(paletted_block_array_obj* intern, zend_long fillEntry); #endif diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp new file mode 100644 index 0000000..0ce28df --- /dev/null +++ b/src/PhpSubChunk.cpp @@ -0,0 +1,523 @@ +#include +#include + +#include "PhpPalettedBlockArray.h" +#include "PhpPalettedBlockArrayObj.h" +#include "PhpLightArray.h" +#include "PhpSubChunk.h" +#include "PhpSubChunk_arginfo.h" +#include "ZendUtil.h" + +extern "C" { +#include "php.h" +#include "ext/standard/php_var.h" +#include "Zend/zend_exceptions.h" +#include "Zend/zend_hash.h" +} + +typedef struct { + zend_long emptyBlockId; + std::vector blockLayers; + light_array_obj* blockLight; + light_array_obj* skyLight; + zend_object std; +} sub_chunk_obj; + +zend_class_entry* sub_chunk_entry; +static zend_object_handlers sub_chunk_handlers; + +static inline sub_chunk_obj* fetch_intern(zend_object* object) { + return fetch_from_zend_object(object); +} + +#define sub_chunk_this() fetch_intern(Z_OBJ_P(getThis())) + +static zend_object* sub_chunk_new(zend_class_entry* ce) { + sub_chunk_obj* result = alloc_custom_zend_object(ce, &sub_chunk_handlers); + + result->emptyBlockId = 0; + new(&result->blockLayers) std::vector(); + result->blockLight = nullptr; + result->skyLight = nullptr; + + return &result->std; +} + +static zend_object* sub_chunk_clone(chunkutils2_handler_context* object) { + sub_chunk_obj* const old_object = fetch_intern(Z_OBJ_FROM_HANDLER_CONTEXT(object)); + sub_chunk_obj* const new_object = fetch_intern(sub_chunk_new(Z_OBJ_FROM_HANDLER_CONTEXT(object)->ce)); + zval zv; + + new_object->emptyBlockId = old_object->emptyBlockId; + new(&new_object->blockLayers) std::vector(); + for (auto blockLayer : old_object->blockLayers) { + ZVAL_OBJ(&zv, &blockLayer->std); + auto clonedBlockLayer = fetch_from_zend_object(blockLayer->std.handlers->clone_obj(HANDLER_CONTEXT_FROM_ZVAL(&zv))); + new_object->blockLayers.push_back(clonedBlockLayer); + } + + auto blockLight = old_object->blockLight; + if (blockLight != nullptr) { + ZVAL_OBJ(&zv, &blockLight->std); + new_object->blockLight = fetch_from_zend_object(blockLight->std.handlers->clone_obj(HANDLER_CONTEXT_FROM_ZVAL(&zv))); + } + auto skyLight = old_object->skyLight; + if (skyLight != nullptr) { + ZVAL_OBJ(&zv, &skyLight->std); + new_object->skyLight = fetch_from_zend_object(skyLight->std.handlers->clone_obj(HANDLER_CONTEXT_FROM_ZVAL(&zv))); + } + + zend_objects_clone_members(&new_object->std, &old_object->std); //copy user-assigned properties + + return &new_object->std; +} + +static void sub_chunk_free(zend_object* std) { + auto object = fetch_intern(std); + + for (auto blockLayer : object->blockLayers) { + OBJ_RELEASE(&blockLayer->std); + } + object->blockLayers.~vector(); + + auto blockLight = object->blockLight; + if (blockLight != nullptr) { + OBJ_RELEASE(&blockLight->std); + } + + auto skyLight = object->skyLight; + if (skyLight != nullptr) { + OBJ_RELEASE(&skyLight->std); + } + + zend_object_std_dtor(std); +} + +static int sub_chunk_serialize(zval* obj, unsigned char** buffer, size_t* buf_len, zend_serialize_data* data) { + sub_chunk_obj* object = fetch_intern(Z_OBJ_P(obj)); + + smart_str buf = { 0 }; + php_serialize_data_t serialize_data = (php_serialize_data_t)data; + PHP_VAR_SERIALIZE_INIT(serialize_data); + + zval zv; + + ZVAL_LONG(&zv, object->emptyBlockId); + php_var_serialize(&buf, &zv, &serialize_data); + + array_init_size(&zv, object->blockLayers.size()); + for (auto i : object->blockLayers) { + zval zlayer; + ZVAL_OBJ_COPY(&zlayer, &i->std); + add_next_index_zval(&zv, &zlayer); + } + php_var_serialize(&buf, &zv, &serialize_data); + zval_dtor(&zv); + + { + auto blockLight = object->blockLight; + if (blockLight != nullptr) { + ZVAL_OBJ(&zv, &blockLight->std); + } else { + ZVAL_NULL(&zv); + } + php_var_serialize(&buf, &zv, &serialize_data); + } + { + auto skyLight = object->skyLight; + if (skyLight != nullptr) { + ZVAL_OBJ(&zv, &skyLight->std); + } else { + ZVAL_NULL(&zv); + } + php_var_serialize(&buf, &zv, &serialize_data); + } + + ZVAL_ARR(&zv, zend_std_get_properties(HANDLER_CONTEXT_FROM_ZVAL(obj))); + php_var_serialize(&buf, &zv, &serialize_data); + + PHP_VAR_SERIALIZE_DESTROY(serialize_data); + *buffer = (unsigned char*)estrndup(ZSTR_VAL(buf.s), ZSTR_LEN(buf.s)); + *buf_len = ZSTR_LEN(buf.s); + zend_string_release(buf.s); + + return SUCCESS; +} + +static int sub_chunk_unserialize(zval* object, zend_class_entry* ce, const unsigned char* buf, size_t buf_len, zend_unserialize_data* data) { + php_unserialize_data_t unserialize_data = (php_unserialize_data_t)data; + PHP_VAR_UNSERIALIZE_INIT(unserialize_data); + + int result = FAILURE; + + const unsigned char* start = buf; + const unsigned char* end = buf + buf_len; + + zval* emptyBlockId = var_tmp_var(&unserialize_data); + if (!php_var_unserialize(emptyBlockId, &start, end, &unserialize_data) || Z_TYPE_P(emptyBlockId) != IS_LONG) { + zend_throw_exception(NULL, "Failed to unserialize SubChunk::emptyBlockId", 0); + goto end; + } + + zval* blockLayers = var_tmp_var(&unserialize_data); + if (!php_var_unserialize(blockLayers, &start, end, &unserialize_data) || Z_TYPE_P(blockLayers) != IS_ARRAY) { + zend_throw_exception(NULL, "Failed to unserialize SubChunk::blockLayers", 0); + goto end; + } + zval* zvBlockLayer; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(blockLayers), zvBlockLayer) { + if (Z_TYPE_P(zvBlockLayer) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(zvBlockLayer), paletted_block_array_entry)) { + zend_throw_exception(NULL, "SubChunk::blockLayers expects only objects of type " paletted_block_array_classname, 0); + goto end; + } + } ZEND_HASH_FOREACH_END(); + + zval* blockLight = var_tmp_var(&unserialize_data); + if ( + !php_var_unserialize(blockLight, &start, end, &unserialize_data) || ( + Z_TYPE_P(blockLight) != IS_NULL && + (Z_TYPE_P(blockLight) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(blockLight), light_array_entry)) + ) + ) { + zend_throw_exception(NULL, "Failed to unserialize SubChunk::blockLight", 0); + goto end; + } + + zval* skyLight = var_tmp_var(&unserialize_data); + if ( + !php_var_unserialize(skyLight, &start, end, &unserialize_data) || ( + Z_TYPE_P(skyLight) != IS_NULL && + (Z_TYPE_P(skyLight) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(skyLight), light_array_entry)) + ) + ) { + zend_throw_exception(NULL, "Failed to unserialize SubChunk::skyLight", 0); + goto end; + } + + object_init_ex(object, sub_chunk_entry); + auto intern = fetch_intern(Z_OBJ_P(object)); + intern->emptyBlockId = Z_LVAL_P(emptyBlockId); + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(blockLayers), zvBlockLayer) { + auto blockLayerIntern = fetch_from_zend_object(Z_OBJ_P(zvBlockLayer)); + intern->blockLayers.push_back(blockLayerIntern); + Z_ADDREF_P(zvBlockLayer); + } ZEND_HASH_FOREACH_END(); + + if (Z_TYPE_P(blockLight) == IS_OBJECT) { + intern->blockLight = fetch_from_zend_object(Z_OBJ_P(blockLight)); + Z_ADDREF_P(blockLight); + } + if (Z_TYPE_P(skyLight) == IS_OBJECT) { + intern->skyLight = fetch_from_zend_object(Z_OBJ_P(skyLight)); + Z_ADDREF_P(skyLight); + } + + zval* properties = var_tmp_var(&unserialize_data); + if (!php_var_unserialize(properties, &start, end, &unserialize_data) || Z_TYPE_P(properties) != IS_ARRAY) { + zend_throw_exception(NULL, "Failed to unserialize SubChunk user properties", 0); + goto end; + } + if (zend_hash_num_elements(Z_ARRVAL_P(properties)) != 0) { + zend_hash_copy(zend_std_get_properties(HANDLER_CONTEXT_FROM_ZVAL(object)), Z_ARRVAL_P(properties), (copy_ctor_func_t)zval_add_ref); + } + result = SUCCESS; +end: + PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); + return result; +} + +static void sub_chunk_collect_garbage(sub_chunk_obj* object) { + std::vector cleanedLayers; + + for (auto layer : object->blockLayers) { + layer->container.collectGarbage(false, 0); + + bool keep = false; + for (auto p : layer->container.getPalette()) { + if (p != object->emptyBlockId) { + keep = true; + break; + } + } + if (keep) { + cleanedLayers.push_back(layer); + } else { + OBJ_RELEASE(&layer->std); + } + } + object->blockLayers = cleanedLayers; + + auto skyLight = object->skyLight; + if (skyLight != nullptr && skyLight->lightArray.isUniform(0)) { + OBJ_RELEASE(&skyLight->std); + object->skyLight = nullptr; + } + + auto blockLight = object->blockLight; + if (blockLight != nullptr && blockLight->lightArray.isUniform(0)) { + OBJ_RELEASE(&blockLight->std); + object->blockLight = nullptr; + } +} + +ZEND_BEGIN_ARG_INFO_EX(arginfo_SubChunk___construct, 0, 0, 2) + ZEND_ARG_TYPE_INFO(0, emptyBlockId, IS_LONG, 0) + ZEND_ARG_ARRAY_INFO(0, blocks, 0) + CUSTOM_ZEND_ARG_OBJ_INFO_STR(0, skyLight, light_array_classname, 1) + CUSTOM_ZEND_ARG_OBJ_INFO_STR(0, blockLight, light_array_classname, 1) +ZEND_END_ARG_INFO() + +PHP_METHOD(PhpSubChunk, __construct) { + zend_long emptyBlockId; + HashTable* htBlockLayers; + zval* skyLight = NULL; + zval* blockLight = NULL; + + ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 2, 4) + Z_PARAM_LONG(emptyBlockId) + Z_PARAM_ARRAY_HT(htBlockLayers) + Z_PARAM_OPTIONAL + Z_PARAM_OBJECT_OF_CLASS_EX(skyLight, light_array_entry, 1, 0) + Z_PARAM_OBJECT_OF_CLASS_EX(blockLight, light_array_entry, 1, 0) + ZEND_PARSE_PARAMETERS_END(); + + zval *layer; + ZEND_HASH_FOREACH_VAL(htBlockLayers, layer) { + if (Z_TYPE_P(layer) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(layer), paletted_block_array_entry)) { + zend_type_error("Layers array should contain only " paletted_block_array_classname " objects"); + return; + } + } ZEND_HASH_FOREACH_END(); + + auto intern = sub_chunk_this(); + intern->emptyBlockId = emptyBlockId; + + ZEND_HASH_FOREACH_VAL(htBlockLayers, layer) { + auto internLayer = fetch_from_zend_object(Z_OBJ_P(layer)); + intern->blockLayers.push_back(internLayer); + Z_ADDREF_P(layer); + } ZEND_HASH_FOREACH_END(); + + if (skyLight != NULL) { + intern->skyLight = fetch_from_zend_object(Z_OBJ_P(skyLight)); + Z_ADDREF_P(skyLight); + } + if (blockLight != NULL) { + intern->blockLight = fetch_from_zend_object(Z_OBJ_P(blockLight)); + Z_ADDREF_P(blockLight); + } +} + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_isEmptyAuthoritative, 0, 0, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +PHP_METHOD(PhpSubChunk, isEmptyAuthoritative) { + zend_parse_parameters_none_throw(); + + auto intern = sub_chunk_this(); + sub_chunk_collect_garbage(intern); + RETURN_BOOL(intern->blockLayers.empty()); +} + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_isEmptyFast, 0, 0, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +PHP_METHOD(PhpSubChunk, isEmptyFast) { + zend_parse_parameters_none_throw(); + RETURN_BOOL(sub_chunk_this()->blockLayers.empty()); +} + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_getEmptyBlockId, 0, 0, IS_LONG, 0) +ZEND_END_ARG_INFO() + +PHP_METHOD(PhpSubChunk, getEmptyBlockId) { + zend_parse_parameters_none_throw(); + RETURN_LONG(sub_chunk_this()->emptyBlockId); +} + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_getFullBlock, 0, 3, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, z, IS_LONG, 0) +ZEND_END_ARG_INFO() + +PHP_METHOD(PhpSubChunk, getFullBlock) { + zend_long x, y, z; + + ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 3, 3) + Z_PARAM_LONG(x) + Z_PARAM_LONG(y) + Z_PARAM_LONG(z) + ZEND_PARSE_PARAMETERS_END(); + + auto intern = sub_chunk_this(); + if (intern->blockLayers.empty()) { + RETURN_LONG(intern->emptyBlockId); + } else { + RETURN_LONG(intern->blockLayers[0]->container.get(x, y, z)); + } +} + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_setFullBlock, 0, 4, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, z, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, block, IS_LONG, 0) +ZEND_END_ARG_INFO() + +PHP_METHOD(PhpSubChunk, setFullBlock) { + zend_long x, y, z, block; + + ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4) + Z_PARAM_LONG(x) + Z_PARAM_LONG(y) + Z_PARAM_LONG(z) + Z_PARAM_LONG(block) + ZEND_PARSE_PARAMETERS_END(); + + auto intern = sub_chunk_this(); + paletted_block_array_obj* blockLayer; + if (intern->blockLayers.empty()) { + zval zvNewLayer; + //TODO: this isn't enough to initialize a PalettedBlockArray + object_init_ex(&zvNewLayer, paletted_block_array_entry); + blockLayer = fetch_from_zend_object(Z_OBJ(zvNewLayer)); + if (!paletted_block_array_fill(blockLayer, intern->emptyBlockId)) { + return; + } + intern->blockLayers.push_back(blockLayer); + } else { + blockLayer = intern->blockLayers[0]; + } + blockLayer->container.set(x, y, z, block); +} + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_getBlockLayers, 0, 0, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + +PHP_METHOD(PhpSubChunk, getBlockLayers) { + zend_parse_parameters_none_throw(); + + auto intern = sub_chunk_this(); + array_init_size(return_value, intern->blockLayers.size()); + for (auto layer : intern->blockLayers) { + zval zv; + ZVAL_OBJ_COPY(&zv, &layer->std); + add_next_index_zval(return_value, &zv); + } +} + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_getHighestBlockAt, 0, 2, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, z, IS_LONG, 0) +ZEND_END_ARG_INFO() + +PHP_METHOD(PhpSubChunk, getHighestBlockAt) { + zend_long x, z; + + ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 2, 2) + Z_PARAM_LONG(x) + Z_PARAM_LONG(z) + ZEND_PARSE_PARAMETERS_END(); + + auto intern = sub_chunk_this(); + if (intern->blockLayers.empty()) { + RETURN_LONG(-1); + } + + auto layerZero = intern->blockLayers[0]; + for (auto y = 15; y >= 0; y--) { + if (layerZero->container.get(x, y, z) != intern->emptyBlockId) { + RETURN_LONG(y); + } + } + RETURN_LONG(-1); +} + +static inline void ensure_light_array_initialized(light_array_obj** lightArray) { + if (*lightArray == nullptr) { + zval zv; + object_init_ex(&zv, light_array_entry); + auto lightArrayIntern = fetch_from_zend_object(Z_OBJ_P(&zv)); + light_array_fill(lightArrayIntern, 0); + *lightArray = lightArrayIntern; + } +} + +PHP_METHOD(PhpSubChunk, getBlockSkyLightArray) { + zend_parse_parameters_none_throw(); + + auto intern = sub_chunk_this(); + ensure_light_array_initialized(&intern->skyLight); + RETURN_OBJ_COPY(&intern->skyLight->std); +} + +PHP_METHOD(PhpSubChunk, getBlockLightArray) { + zend_parse_parameters_none_throw(); + + auto intern = sub_chunk_this(); + ensure_light_array_initialized(&intern->blockLight); + RETURN_OBJ_COPY(&intern->blockLight->std); +} + +PHP_METHOD(PhpSubChunk, setBlockSkyLightArray) { + parse_args_SubChunk_setLightArray(); + + auto intern = sub_chunk_this(); + if (intern->skyLight != nullptr) { + OBJ_RELEASE(&intern->skyLight->std); + } + intern->skyLight = fetch_from_zend_object(Z_OBJ_P(data)); + Z_ADDREF_P(data); +} + +PHP_METHOD(PhpSubChunk, setBlockLightArray) { + parse_args_SubChunk_setLightArray(); + + auto intern = sub_chunk_this(); + if (intern->blockLight != nullptr) { + OBJ_RELEASE(&intern->blockLight->std); + } + intern->blockLight = fetch_from_zend_object(Z_OBJ_P(data)); + Z_ADDREF_P(data); +} + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_collectGarbage, 0, 0, IS_VOID, 0) +ZEND_END_ARG_INFO(); + +PHP_METHOD(PhpSubChunk, collectGarbage) { + zend_parse_parameters_none_throw(); + + sub_chunk_collect_garbage(sub_chunk_this()); +} + +static zend_function_entry sub_chunk_class_methods[] = { + PHP_ME(PhpSubChunk, __construct, arginfo_SubChunk___construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(PhpSubChunk, isEmptyAuthoritative, arginfo_SubChunk_isEmptyAuthoritative, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, isEmptyFast, arginfo_SubChunk_isEmptyFast, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getFullBlock, arginfo_SubChunk_getFullBlock, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, setFullBlock, arginfo_SubChunk_setFullBlock, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getBlockLayers, arginfo_SubChunk_getBlockLayers, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getHighestBlockAt, arginfo_SubChunk_getHighestBlockAt, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getBlockSkyLightArray, arginfo_SubChunk_getLightArray, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, setBlockSkyLightArray, arginfo_SubChunk_setLightArray, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getBlockLightArray, arginfo_SubChunk_getLightArray, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, setBlockLightArray, arginfo_SubChunk_setLightArray, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, collectGarbage, arginfo_SubChunk_collectGarbage, ZEND_ACC_PUBLIC) + PHP_FE_END +}; + +void register_sub_chunk_class() { + memcpy(&sub_chunk_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + sub_chunk_handlers.offset = XtOffsetOf(sub_chunk_obj, std); + sub_chunk_handlers.free_obj = sub_chunk_free; + sub_chunk_handlers.clone_obj = sub_chunk_clone; + + zend_class_entry ce; + INIT_CLASS_ENTRY(ce, sub_chunk_classname, sub_chunk_class_methods); + ce.create_object = sub_chunk_new; + ce.serialize = sub_chunk_serialize; + ce.unserialize = sub_chunk_unserialize; + sub_chunk_entry = zend_register_internal_class(&ce); + sub_chunk_entry->ce_flags |= ZEND_ACC_FINAL; +} diff --git a/src/PhpSubChunk.h b/src/PhpSubChunk.h new file mode 100644 index 0000000..c87f063 --- /dev/null +++ b/src/PhpSubChunk.h @@ -0,0 +1,8 @@ +#ifndef HAVE_PHP_SUB_CHUNK_H +#define HAVE_PHP_SUB_CHUNK_H + +extern zend_class_entry* sub_chunk_entry; +#define sub_chunk_classname "pocketmine\\world\\format\\SubChunk" + +void register_sub_chunk_class(); +#endif diff --git a/src/PhpSubChunk_arginfo.h b/src/PhpSubChunk_arginfo.h new file mode 100644 index 0000000..5ab71e4 --- /dev/null +++ b/src/PhpSubChunk_arginfo.h @@ -0,0 +1,27 @@ +#ifndef HAVE_PHP_SUB_CHUNK_ARGINFO_H +#define HAVE_PHP_SUB_CHUNK_ARGINFO_H + +#include "ZendUtil.h" +#include "PhpLightArray.h" + +extern "C" { +#include "php.h" +} + + +CUSTOM_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX_STR(arginfo_SubChunk_getLightArray, 0, 0, light_array_classname, 0) +ZEND_END_ARG_INFO(); + + + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_setLightArray, 0, 1, IS_VOID, 0) + CUSTOM_ZEND_ARG_OBJ_INFO_STR(0, data, light_array_classname, 0) +ZEND_END_ARG_INFO() + +#define parse_args_SubChunk_setLightArray() \ + zval* data; \ + ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 1) \ + Z_PARAM_OBJECT_OF_CLASS(data, light_array_entry) \ + ZEND_PARSE_PARAMETERS_END(); + +#endif diff --git a/src/ZendUtil.h b/src/ZendUtil.h index 731030f..52d3941 100644 --- a/src/ZendUtil.h +++ b/src/ZendUtil.h @@ -32,5 +32,18 @@ typedef zval chunkutils2_handler_context; #define HANDLER_CONTEXT_FROM_ZVAL(zv) (zv) #endif +//custom version of ZEND_ARG_OBJ_INFO that accepts strings directly, instead of barewords - needed for macro usage +#if PHP_VERSION_ID < 80000 +#define CUSTOM_ZEND_ARG_OBJ_INFO_STR(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_ENCODE_CLASS_CONST(classname, allow_null), pass_by_ref, 0 }, +#else +#define CUSTOM_ZEND_ARG_OBJ_INFO_STR(pass_by_ref, name, classname, allow_null) \ + { #name, ZEND_TYPE_INIT_CLASS_CONST(classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL }, +#endif + +#define CUSTOM_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX_STR(name, return_reference, required_num_args, class_name, allow_null) \ + static const zend_internal_arg_info name[] = { \ + { (const char*)(zend_uintptr_t)(required_num_args), \ + ZEND_TYPE_INIT_CLASS_CONST(class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL }, + #endif From 6a4f8cc863cf68f7897c51a7ab096a051874f0d2 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 30 Jul 2021 21:23:18 +0100 Subject: [PATCH 02/16] remove junk --- src/PhpLightArray.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/PhpLightArray.h b/src/PhpLightArray.h index fa5bdf3..eb54b2e 100644 --- a/src/PhpLightArray.h +++ b/src/PhpLightArray.h @@ -22,9 +22,6 @@ PHP_METHOD(PhpLightArray, isUniform); extern zend_class_entry* light_array_entry; -#define stringify_ex(macro) #macro -#define stringify(macro) stringify_ex(macro) - #define light_array_classname "pocketmine\\world\\format\\LightArray" void light_array_fill(light_array_obj* object, zend_long level); From e368e694d538a07ec061833b04c503aab7c2c56e Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 30 Jul 2021 21:23:50 +0100 Subject: [PATCH 03/16] a sacrifice for the G++ gods --- src/PhpSubChunk.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index 0ce28df..b83c058 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -153,18 +153,19 @@ static int sub_chunk_unserialize(zval* object, zend_class_entry* ce, const unsig const unsigned char* start = buf; const unsigned char* end = buf + buf_len; - zval* emptyBlockId = var_tmp_var(&unserialize_data); + zval* emptyBlockId, * blockLayers, * zvBlockLayer, * blockLight, * skyLight, *properties; + emptyBlockId = var_tmp_var(&unserialize_data); if (!php_var_unserialize(emptyBlockId, &start, end, &unserialize_data) || Z_TYPE_P(emptyBlockId) != IS_LONG) { zend_throw_exception(NULL, "Failed to unserialize SubChunk::emptyBlockId", 0); goto end; } - zval* blockLayers = var_tmp_var(&unserialize_data); + blockLayers = var_tmp_var(&unserialize_data); if (!php_var_unserialize(blockLayers, &start, end, &unserialize_data) || Z_TYPE_P(blockLayers) != IS_ARRAY) { zend_throw_exception(NULL, "Failed to unserialize SubChunk::blockLayers", 0); goto end; } - zval* zvBlockLayer; + zvBlockLayer; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(blockLayers), zvBlockLayer) { if (Z_TYPE_P(zvBlockLayer) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(zvBlockLayer), paletted_block_array_entry)) { zend_throw_exception(NULL, "SubChunk::blockLayers expects only objects of type " paletted_block_array_classname, 0); @@ -172,7 +173,7 @@ static int sub_chunk_unserialize(zval* object, zend_class_entry* ce, const unsig } } ZEND_HASH_FOREACH_END(); - zval* blockLight = var_tmp_var(&unserialize_data); + blockLight = var_tmp_var(&unserialize_data); if ( !php_var_unserialize(blockLight, &start, end, &unserialize_data) || ( Z_TYPE_P(blockLight) != IS_NULL && @@ -183,7 +184,7 @@ static int sub_chunk_unserialize(zval* object, zend_class_entry* ce, const unsig goto end; } - zval* skyLight = var_tmp_var(&unserialize_data); + skyLight = var_tmp_var(&unserialize_data); if ( !php_var_unserialize(skyLight, &start, end, &unserialize_data) || ( Z_TYPE_P(skyLight) != IS_NULL && @@ -212,7 +213,7 @@ static int sub_chunk_unserialize(zval* object, zend_class_entry* ce, const unsig Z_ADDREF_P(skyLight); } - zval* properties = var_tmp_var(&unserialize_data); + properties = var_tmp_var(&unserialize_data); if (!php_var_unserialize(properties, &start, end, &unserialize_data) || Z_TYPE_P(properties) != IS_ARRAY) { zend_throw_exception(NULL, "Failed to unserialize SubChunk user properties", 0); goto end; From 48dc7fd9661a724631c9917cc534d25bd96e23ad Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 30 Jul 2021 21:25:44 +0100 Subject: [PATCH 04/16] ... --- src/PhpSubChunk.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index b83c058..58b5dc1 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -154,6 +154,7 @@ static int sub_chunk_unserialize(zval* object, zend_class_entry* ce, const unsig const unsigned char* end = buf + buf_len; zval* emptyBlockId, * blockLayers, * zvBlockLayer, * blockLight, * skyLight, *properties; + sub_chunk_obj* intern; emptyBlockId = var_tmp_var(&unserialize_data); if (!php_var_unserialize(emptyBlockId, &start, end, &unserialize_data) || Z_TYPE_P(emptyBlockId) != IS_LONG) { zend_throw_exception(NULL, "Failed to unserialize SubChunk::emptyBlockId", 0); @@ -196,7 +197,7 @@ static int sub_chunk_unserialize(zval* object, zend_class_entry* ce, const unsig } object_init_ex(object, sub_chunk_entry); - auto intern = fetch_intern(Z_OBJ_P(object)); + intern = fetch_intern(Z_OBJ_P(object)); intern->emptyBlockId = Z_LVAL_P(emptyBlockId); ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(blockLayers), zvBlockLayer) { auto blockLayerIntern = fetch_from_zend_object(Z_OBJ_P(zvBlockLayer)); From 968cbbdd1d6b573f69850fcb9e36057ca69c40a7 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 30 Jul 2021 21:28:18 +0100 Subject: [PATCH 05/16] PHP's internal API makes me want to kill myself --- src/PhpPalettedBlockArray.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpPalettedBlockArray.cpp b/src/PhpPalettedBlockArray.cpp index 94bac88..161ecc7 100644 --- a/src/PhpPalettedBlockArray.cpp +++ b/src/PhpPalettedBlockArray.cpp @@ -224,7 +224,7 @@ PHP_METHOD(PhpPalettedBlockArray, __construct) { paletted_block_array_fill(intern, fillEntry); } -ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_PalettedBlockArray_fromData, 0, 3, paletted_block_array_classname, 0) +CUSTOM_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX_STR(arginfo_PalettedBlockArray_fromData, 0, 3, paletted_block_array_classname, 0) ZEND_ARG_TYPE_INFO(0, bitsPerBlock, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, wordArray, IS_STRING, 0) ZEND_ARG_ARRAY_INFO(0, palette, 0) From 384571026ca0ec58272abdf8c2880da8f776edc1 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 30 Jul 2021 21:49:32 +0100 Subject: [PATCH 06/16] Remove mess that doesn't compile on 7.x --- src/PhpLightArray.cpp | 2 +- src/PhpLightArray.h | 2 -- src/PhpPalettedBlockArray.cpp | 6 +++--- src/PhpPalettedBlockArrayObj.h | 1 - src/PhpSubChunk.cpp | 10 +++++----- src/PhpSubChunk.h | 1 - src/PhpSubChunk_arginfo.h | 4 ++-- src/ZendUtil.h | 14 -------------- 8 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/PhpLightArray.cpp b/src/PhpLightArray.cpp index dbb8346..0048d31 100644 --- a/src/PhpLightArray.cpp +++ b/src/PhpLightArray.cpp @@ -211,7 +211,7 @@ void register_light_array_class() { light_array_handlers.clone_obj = light_array_clone; zend_class_entry ce; - INIT_CLASS_ENTRY(ce, light_array_classname, light_array_class_methods); + INIT_CLASS_ENTRY(ce, "pocketmine\\world\\format\\LightArray", light_array_class_methods); ce.create_object = light_array_new; ce.serialize = light_array_serialize; ce.unserialize = light_array_unserialize; diff --git a/src/PhpLightArray.h b/src/PhpLightArray.h index eb54b2e..7a74987 100644 --- a/src/PhpLightArray.h +++ b/src/PhpLightArray.h @@ -22,8 +22,6 @@ PHP_METHOD(PhpLightArray, isUniform); extern zend_class_entry* light_array_entry; -#define light_array_classname "pocketmine\\world\\format\\LightArray" - void light_array_fill(light_array_obj* object, zend_long level); void register_light_array_class(); diff --git a/src/PhpPalettedBlockArray.cpp b/src/PhpPalettedBlockArray.cpp index 161ecc7..323040e 100644 --- a/src/PhpPalettedBlockArray.cpp +++ b/src/PhpPalettedBlockArray.cpp @@ -224,7 +224,7 @@ PHP_METHOD(PhpPalettedBlockArray, __construct) { paletted_block_array_fill(intern, fillEntry); } -CUSTOM_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX_STR(arginfo_PalettedBlockArray_fromData, 0, 3, paletted_block_array_classname, 0) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_PalettedBlockArray_fromData, 0, 3, pocketmine\\world\\format\\PalettedBlockArray, 0) ZEND_ARG_TYPE_INFO(0, bitsPerBlock, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, wordArray, IS_STRING, 0) ZEND_ARG_ARRAY_INFO(0, palette, 0) @@ -408,10 +408,10 @@ void register_paletted_block_array_class() { paletted_block_array_handlers.clone_obj = paletted_block_array_clone; zend_class_entry ce; - INIT_CLASS_ENTRY(ce, paletted_block_array_classname, paletted_block_array_class_methods); + INIT_CLASS_ENTRY(ce, "pocketmine\\world\\format\\PalettedBlockArray", paletted_block_array_class_methods); ce.create_object = paletted_block_array_new; ce.serialize = paletted_block_array_serialize; ce.unserialize = paletted_block_array_unserialize; paletted_block_array_entry = zend_register_internal_class(&ce); paletted_block_array_entry->ce_flags |= ZEND_ACC_FINAL; -} \ No newline at end of file +} diff --git a/src/PhpPalettedBlockArrayObj.h b/src/PhpPalettedBlockArrayObj.h index f418d80..0a47d68 100644 --- a/src/PhpPalettedBlockArrayObj.h +++ b/src/PhpPalettedBlockArrayObj.h @@ -16,7 +16,6 @@ typedef struct { } paletted_block_array_obj; extern zend_class_entry* paletted_block_array_entry; -#define paletted_block_array_classname "pocketmine\\world\\format\\PalettedBlockArray" bool paletted_block_array_fill(paletted_block_array_obj* intern, zend_long fillEntry); #endif diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index 58b5dc1..26f9368 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -169,7 +169,7 @@ static int sub_chunk_unserialize(zval* object, zend_class_entry* ce, const unsig zvBlockLayer; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(blockLayers), zvBlockLayer) { if (Z_TYPE_P(zvBlockLayer) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(zvBlockLayer), paletted_block_array_entry)) { - zend_throw_exception(NULL, "SubChunk::blockLayers expects only objects of type " paletted_block_array_classname, 0); + zend_throw_exception_ex(NULL, 0, "SubChunk::blockLayers expects only objects of type %s", ZSTR_VAL(paletted_block_array_entry->name)); goto end; } } ZEND_HASH_FOREACH_END(); @@ -265,8 +265,8 @@ static void sub_chunk_collect_garbage(sub_chunk_obj* object) { ZEND_BEGIN_ARG_INFO_EX(arginfo_SubChunk___construct, 0, 0, 2) ZEND_ARG_TYPE_INFO(0, emptyBlockId, IS_LONG, 0) ZEND_ARG_ARRAY_INFO(0, blocks, 0) - CUSTOM_ZEND_ARG_OBJ_INFO_STR(0, skyLight, light_array_classname, 1) - CUSTOM_ZEND_ARG_OBJ_INFO_STR(0, blockLight, light_array_classname, 1) + ZEND_ARG_OBJ_INFO(0, skyLight, pocketmine\\world\\format\\LightArray, 1) + ZEND_ARG_OBJ_INFO(0, blockLight, pocketmine\\world\\format\\LightArray, 1) ZEND_END_ARG_INFO() PHP_METHOD(PhpSubChunk, __construct) { @@ -286,7 +286,7 @@ PHP_METHOD(PhpSubChunk, __construct) { zval *layer; ZEND_HASH_FOREACH_VAL(htBlockLayers, layer) { if (Z_TYPE_P(layer) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(layer), paletted_block_array_entry)) { - zend_type_error("Layers array should contain only " paletted_block_array_classname " objects"); + zend_type_error("Layers array should contain only %s objects", ZSTR_VAL(paletted_block_array_entry->name)); return; } } ZEND_HASH_FOREACH_END(); @@ -516,7 +516,7 @@ void register_sub_chunk_class() { sub_chunk_handlers.clone_obj = sub_chunk_clone; zend_class_entry ce; - INIT_CLASS_ENTRY(ce, sub_chunk_classname, sub_chunk_class_methods); + INIT_CLASS_ENTRY(ce, "pocketmine\\world\\format\\SubChunk", sub_chunk_class_methods); ce.create_object = sub_chunk_new; ce.serialize = sub_chunk_serialize; ce.unserialize = sub_chunk_unserialize; diff --git a/src/PhpSubChunk.h b/src/PhpSubChunk.h index c87f063..f469d02 100644 --- a/src/PhpSubChunk.h +++ b/src/PhpSubChunk.h @@ -2,7 +2,6 @@ #define HAVE_PHP_SUB_CHUNK_H extern zend_class_entry* sub_chunk_entry; -#define sub_chunk_classname "pocketmine\\world\\format\\SubChunk" void register_sub_chunk_class(); #endif diff --git a/src/PhpSubChunk_arginfo.h b/src/PhpSubChunk_arginfo.h index 5ab71e4..f872b25 100644 --- a/src/PhpSubChunk_arginfo.h +++ b/src/PhpSubChunk_arginfo.h @@ -9,13 +9,13 @@ extern "C" { } -CUSTOM_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX_STR(arginfo_SubChunk_getLightArray, 0, 0, light_array_classname, 0) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_SubChunk_getLightArray, 0, 0, pocketmine\\world\\format\\LightArray, 0) ZEND_END_ARG_INFO(); ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_setLightArray, 0, 1, IS_VOID, 0) - CUSTOM_ZEND_ARG_OBJ_INFO_STR(0, data, light_array_classname, 0) + ZEND_ARG_OBJ_INFO(0, data, pocketmine\\world\\format\\LightArray, 0) ZEND_END_ARG_INFO() #define parse_args_SubChunk_setLightArray() \ diff --git a/src/ZendUtil.h b/src/ZendUtil.h index 52d3941..9e84e63 100644 --- a/src/ZendUtil.h +++ b/src/ZendUtil.h @@ -32,18 +32,4 @@ typedef zval chunkutils2_handler_context; #define HANDLER_CONTEXT_FROM_ZVAL(zv) (zv) #endif -//custom version of ZEND_ARG_OBJ_INFO that accepts strings directly, instead of barewords - needed for macro usage -#if PHP_VERSION_ID < 80000 -#define CUSTOM_ZEND_ARG_OBJ_INFO_STR(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_ENCODE_CLASS_CONST(classname, allow_null), pass_by_ref, 0 }, -#else -#define CUSTOM_ZEND_ARG_OBJ_INFO_STR(pass_by_ref, name, classname, allow_null) \ - { #name, ZEND_TYPE_INIT_CLASS_CONST(classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL }, #endif - -#define CUSTOM_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX_STR(name, return_reference, required_num_args, class_name, allow_null) \ - static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), \ - ZEND_TYPE_INIT_CLASS_CONST(class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL }, - -#endif - From 41094b2d9c280f1e8f0e083cb96ab93bd61a2da1 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 30 Jul 2021 22:02:46 +0100 Subject: [PATCH 07/16] fix some broken things on 7.x --- src/PhpSubChunk.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index 26f9368..5f0c2aa 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -108,7 +108,8 @@ static int sub_chunk_serialize(zval* obj, unsigned char** buffer, size_t* buf_le array_init_size(&zv, object->blockLayers.size()); for (auto i : object->blockLayers) { zval zlayer; - ZVAL_OBJ_COPY(&zlayer, &i->std); + GC_ADDREF(&i->std); + ZVAL_OBJ(&zlayer, &i->std); add_next_index_zval(&zv, &zlayer); } php_var_serialize(&buf, &zv, &serialize_data); @@ -404,7 +405,8 @@ PHP_METHOD(PhpSubChunk, getBlockLayers) { array_init_size(return_value, intern->blockLayers.size()); for (auto layer : intern->blockLayers) { zval zv; - ZVAL_OBJ_COPY(&zv, &layer->std); + GC_ADDREF(&layer->std); + ZVAL_OBJ(&zv, &layer->std); add_next_index_zval(return_value, &zv); } } @@ -451,7 +453,8 @@ PHP_METHOD(PhpSubChunk, getBlockSkyLightArray) { auto intern = sub_chunk_this(); ensure_light_array_initialized(&intern->skyLight); - RETURN_OBJ_COPY(&intern->skyLight->std); + GC_ADDREF(&intern->skyLight->std); + RETURN_OBJ(&intern->skyLight->std); } PHP_METHOD(PhpSubChunk, getBlockLightArray) { @@ -459,7 +462,8 @@ PHP_METHOD(PhpSubChunk, getBlockLightArray) { auto intern = sub_chunk_this(); ensure_light_array_initialized(&intern->blockLight); - RETURN_OBJ_COPY(&intern->blockLight->std); + GC_ADDREF(&intern->blockLight->std); + RETURN_OBJ(&intern->blockLight->std); } PHP_METHOD(PhpSubChunk, setBlockSkyLightArray) { From 56f3f7f1aeb40f172598ba1c31c6ee38168061e6 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 30 Jul 2021 22:05:35 +0100 Subject: [PATCH 08/16] I think it's timeto drop 7.2, at least ... --- src/PhpSubChunk.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index 5f0c2aa..1bb90ee 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -108,8 +108,8 @@ static int sub_chunk_serialize(zval* obj, unsigned char** buffer, size_t* buf_le array_init_size(&zv, object->blockLayers.size()); for (auto i : object->blockLayers) { zval zlayer; - GC_ADDREF(&i->std); ZVAL_OBJ(&zlayer, &i->std); + Z_ADDREF(zlayer); add_next_index_zval(&zv, &zlayer); } php_var_serialize(&buf, &zv, &serialize_data); @@ -405,8 +405,8 @@ PHP_METHOD(PhpSubChunk, getBlockLayers) { array_init_size(return_value, intern->blockLayers.size()); for (auto layer : intern->blockLayers) { zval zv; - GC_ADDREF(&layer->std); ZVAL_OBJ(&zv, &layer->std); + Z_ADDREF(zv); add_next_index_zval(return_value, &zv); } } @@ -453,8 +453,8 @@ PHP_METHOD(PhpSubChunk, getBlockSkyLightArray) { auto intern = sub_chunk_this(); ensure_light_array_initialized(&intern->skyLight); - GC_ADDREF(&intern->skyLight->std); - RETURN_OBJ(&intern->skyLight->std); + RETVAL_OBJ(&intern->skyLight->std); + Z_ADDREF_P(return_value); } PHP_METHOD(PhpSubChunk, getBlockLightArray) { @@ -462,8 +462,8 @@ PHP_METHOD(PhpSubChunk, getBlockLightArray) { auto intern = sub_chunk_this(); ensure_light_array_initialized(&intern->blockLight); - GC_ADDREF(&intern->blockLight->std); - RETURN_OBJ(&intern->blockLight->std); + RETVAL_OBJ(&intern->blockLight->std); + Z_ADDREF_P(return_value); } PHP_METHOD(PhpSubChunk, setBlockSkyLightArray) { From 3bba1ac608e44d5f2311ee53fbe15a5c59f453fe Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 30 Jul 2021 22:19:46 +0100 Subject: [PATCH 09/16] Remove useless code --- src/PhpSubChunk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index 1bb90ee..8a3a99d 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -167,7 +167,7 @@ static int sub_chunk_unserialize(zval* object, zend_class_entry* ce, const unsig zend_throw_exception(NULL, "Failed to unserialize SubChunk::blockLayers", 0); goto end; } - zvBlockLayer; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(blockLayers), zvBlockLayer) { if (Z_TYPE_P(zvBlockLayer) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(zvBlockLayer), paletted_block_array_entry)) { zend_throw_exception_ex(NULL, 0, "SubChunk::blockLayers expects only objects of type %s", ZSTR_VAL(paletted_block_array_entry->name)); From 635181db22b85048f918f0f77209a1f487f0f4de Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 30 Jul 2021 22:23:10 +0100 Subject: [PATCH 10/16] dead TODO comment --- src/PhpSubChunk.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index 8a3a99d..3627955 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -382,7 +382,6 @@ PHP_METHOD(PhpSubChunk, setFullBlock) { paletted_block_array_obj* blockLayer; if (intern->blockLayers.empty()) { zval zvNewLayer; - //TODO: this isn't enough to initialize a PalettedBlockArray object_init_ex(&zvNewLayer, paletted_block_array_entry); blockLayer = fetch_from_zend_object(Z_OBJ(zvNewLayer)); if (!paletted_block_array_fill(blockLayer, intern->emptyBlockId)) { From 4cf1411dfb9060210eca2aa13e95baf2b055e5c8 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 30 Jul 2021 23:02:13 +0100 Subject: [PATCH 11/16] Fixed missing API method --- src/PhpSubChunk.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index 3627955..f097c72 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -500,6 +500,7 @@ static zend_function_entry sub_chunk_class_methods[] = { PHP_ME(PhpSubChunk, __construct, arginfo_SubChunk___construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) PHP_ME(PhpSubChunk, isEmptyAuthoritative, arginfo_SubChunk_isEmptyAuthoritative, ZEND_ACC_PUBLIC) PHP_ME(PhpSubChunk, isEmptyFast, arginfo_SubChunk_isEmptyFast, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getEmptyBlockId, arginfo_SubChunk_getEmptyBlockId, ZEND_ACC_PUBLIC) PHP_ME(PhpSubChunk, getFullBlock, arginfo_SubChunk_getFullBlock, ZEND_ACC_PUBLIC) PHP_ME(PhpSubChunk, setFullBlock, arginfo_SubChunk_setFullBlock, ZEND_ACC_PUBLIC) PHP_ME(PhpSubChunk, getBlockLayers, arginfo_SubChunk_getBlockLayers, ZEND_ACC_PUBLIC) From fe6123cb0df9a97a102e0f660b9a227db5661bf2 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 31 Jul 2021 15:25:12 +0100 Subject: [PATCH 12/16] fix build --- src/PhpSubChunk.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index f097c72..5f21922 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -43,28 +43,24 @@ static zend_object* sub_chunk_new(zend_class_entry* ce) { return &result->std; } -static zend_object* sub_chunk_clone(chunkutils2_handler_context* object) { - sub_chunk_obj* const old_object = fetch_intern(Z_OBJ_FROM_HANDLER_CONTEXT(object)); - sub_chunk_obj* const new_object = fetch_intern(sub_chunk_new(Z_OBJ_FROM_HANDLER_CONTEXT(object)->ce)); - zval zv; +static zend_object* sub_chunk_clone(zend_object* object) { + sub_chunk_obj* const old_object = fetch_intern(object); + sub_chunk_obj* const new_object = fetch_intern(sub_chunk_new(object->ce)); new_object->emptyBlockId = old_object->emptyBlockId; new(&new_object->blockLayers) std::vector(); for (auto blockLayer : old_object->blockLayers) { - ZVAL_OBJ(&zv, &blockLayer->std); - auto clonedBlockLayer = fetch_from_zend_object(blockLayer->std.handlers->clone_obj(HANDLER_CONTEXT_FROM_ZVAL(&zv))); + auto clonedBlockLayer = fetch_from_zend_object(blockLayer->std.handlers->clone_obj(&blockLayer->std)); new_object->blockLayers.push_back(clonedBlockLayer); } auto blockLight = old_object->blockLight; if (blockLight != nullptr) { - ZVAL_OBJ(&zv, &blockLight->std); - new_object->blockLight = fetch_from_zend_object(blockLight->std.handlers->clone_obj(HANDLER_CONTEXT_FROM_ZVAL(&zv))); + new_object->blockLight = fetch_from_zend_object(blockLight->std.handlers->clone_obj(&blockLight->std)); } auto skyLight = old_object->skyLight; if (skyLight != nullptr) { - ZVAL_OBJ(&zv, &skyLight->std); - new_object->skyLight = fetch_from_zend_object(skyLight->std.handlers->clone_obj(HANDLER_CONTEXT_FROM_ZVAL(&zv))); + new_object->skyLight = fetch_from_zend_object(skyLight->std.handlers->clone_obj(&skyLight->std)); } zend_objects_clone_members(&new_object->std, &old_object->std); //copy user-assigned properties @@ -134,7 +130,7 @@ static int sub_chunk_serialize(zval* obj, unsigned char** buffer, size_t* buf_le php_var_serialize(&buf, &zv, &serialize_data); } - ZVAL_ARR(&zv, zend_std_get_properties(HANDLER_CONTEXT_FROM_ZVAL(obj))); + ZVAL_ARR(&zv, zend_std_get_properties(Z_OBJ_P(obj))); php_var_serialize(&buf, &zv, &serialize_data); PHP_VAR_SERIALIZE_DESTROY(serialize_data); @@ -221,7 +217,7 @@ static int sub_chunk_unserialize(zval* object, zend_class_entry* ce, const unsig goto end; } if (zend_hash_num_elements(Z_ARRVAL_P(properties)) != 0) { - zend_hash_copy(zend_std_get_properties(HANDLER_CONTEXT_FROM_ZVAL(object)), Z_ARRVAL_P(properties), (copy_ctor_func_t)zval_add_ref); + zend_hash_copy(zend_std_get_properties(Z_OBJ_P(object)), Z_ARRVAL_P(properties), (copy_ctor_func_t)zval_add_ref); } result = SUCCESS; end: From 01a6c3872c3b245a02088323c0e170482c4ac772 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 31 Jul 2021 15:38:20 +0100 Subject: [PATCH 13/16] Use PHP 8 generated arginfos --- src/PhpSubChunk.cpp | 98 ++++++------------- src/PhpSubChunk_arginfo.h | 27 ----- .../pocketmine/world/format/SubChunk.stub.php | 71 ++++++++++++++ .../world/format/SubChunk_arginfo.h | 52 ++++++++++ 4 files changed, 151 insertions(+), 97 deletions(-) delete mode 100644 src/PhpSubChunk_arginfo.h create mode 100644 stubs/pocketmine/world/format/SubChunk.stub.php create mode 100644 stubs/pocketmine/world/format/SubChunk_arginfo.h diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index 5f21922..82bf8ba 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -5,8 +5,8 @@ #include "PhpPalettedBlockArrayObj.h" #include "PhpLightArray.h" #include "PhpSubChunk.h" -#include "PhpSubChunk_arginfo.h" #include "ZendUtil.h" +#include "stubs/pocketmine/world/format/SubChunk_arginfo.h" extern "C" { #include "php.h" @@ -259,13 +259,6 @@ static void sub_chunk_collect_garbage(sub_chunk_obj* object) { } } -ZEND_BEGIN_ARG_INFO_EX(arginfo_SubChunk___construct, 0, 0, 2) - ZEND_ARG_TYPE_INFO(0, emptyBlockId, IS_LONG, 0) - ZEND_ARG_ARRAY_INFO(0, blocks, 0) - ZEND_ARG_OBJ_INFO(0, skyLight, pocketmine\\world\\format\\LightArray, 1) - ZEND_ARG_OBJ_INFO(0, blockLight, pocketmine\\world\\format\\LightArray, 1) -ZEND_END_ARG_INFO() - PHP_METHOD(PhpSubChunk, __construct) { zend_long emptyBlockId; HashTable* htBlockLayers; @@ -307,9 +300,6 @@ PHP_METHOD(PhpSubChunk, __construct) { } } -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_isEmptyAuthoritative, 0, 0, _IS_BOOL, 0) -ZEND_END_ARG_INFO() - PHP_METHOD(PhpSubChunk, isEmptyAuthoritative) { zend_parse_parameters_none_throw(); @@ -318,28 +308,16 @@ PHP_METHOD(PhpSubChunk, isEmptyAuthoritative) { RETURN_BOOL(intern->blockLayers.empty()); } -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_isEmptyFast, 0, 0, _IS_BOOL, 0) -ZEND_END_ARG_INFO() - PHP_METHOD(PhpSubChunk, isEmptyFast) { zend_parse_parameters_none_throw(); RETURN_BOOL(sub_chunk_this()->blockLayers.empty()); } -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_getEmptyBlockId, 0, 0, IS_LONG, 0) -ZEND_END_ARG_INFO() - PHP_METHOD(PhpSubChunk, getEmptyBlockId) { zend_parse_parameters_none_throw(); RETURN_LONG(sub_chunk_this()->emptyBlockId); } -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_getFullBlock, 0, 3, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, z, IS_LONG, 0) -ZEND_END_ARG_INFO() - PHP_METHOD(PhpSubChunk, getFullBlock) { zend_long x, y, z; @@ -357,13 +335,6 @@ PHP_METHOD(PhpSubChunk, getFullBlock) { } } -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_setFullBlock, 0, 4, IS_VOID, 0) - ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, z, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, block, IS_LONG, 0) -ZEND_END_ARG_INFO() - PHP_METHOD(PhpSubChunk, setFullBlock) { zend_long x, y, z, block; @@ -390,9 +361,6 @@ PHP_METHOD(PhpSubChunk, setFullBlock) { blockLayer->container.set(x, y, z, block); } -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_getBlockLayers, 0, 0, IS_ARRAY, 0) -ZEND_END_ARG_INFO() - PHP_METHOD(PhpSubChunk, getBlockLayers) { zend_parse_parameters_none_throw(); @@ -406,11 +374,6 @@ PHP_METHOD(PhpSubChunk, getBlockLayers) { } } -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_getHighestBlockAt, 0, 2, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, z, IS_LONG, 0) -ZEND_END_ARG_INFO() - PHP_METHOD(PhpSubChunk, getHighestBlockAt) { zend_long x, z; @@ -461,31 +424,26 @@ PHP_METHOD(PhpSubChunk, getBlockLightArray) { Z_ADDREF_P(return_value); } -PHP_METHOD(PhpSubChunk, setBlockSkyLightArray) { - parse_args_SubChunk_setLightArray(); - - auto intern = sub_chunk_this(); - if (intern->skyLight != nullptr) { - OBJ_RELEASE(&intern->skyLight->std); - } - intern->skyLight = fetch_from_zend_object(Z_OBJ_P(data)); +#define macro_SubChunk_setLightArray(lightArrayFieldName) \ + zval* data; \ + ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 1) \ + Z_PARAM_OBJECT_OF_CLASS(data, light_array_entry) \ + ZEND_PARSE_PARAMETERS_END(); \ + auto intern = sub_chunk_this(); \ + if (intern->lightArrayFieldName != nullptr) { \ + OBJ_RELEASE(&intern->lightArrayFieldName->std); \ + } \ + intern->lightArrayFieldName = fetch_from_zend_object(Z_OBJ_P(data)); \ Z_ADDREF_P(data); + +PHP_METHOD(PhpSubChunk, setBlockSkyLightArray) { + macro_SubChunk_setLightArray(skyLight); } PHP_METHOD(PhpSubChunk, setBlockLightArray) { - parse_args_SubChunk_setLightArray(); - - auto intern = sub_chunk_this(); - if (intern->blockLight != nullptr) { - OBJ_RELEASE(&intern->blockLight->std); - } - intern->blockLight = fetch_from_zend_object(Z_OBJ_P(data)); - Z_ADDREF_P(data); + macro_SubChunk_setLightArray(blockLight); } -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_collectGarbage, 0, 0, IS_VOID, 0) -ZEND_END_ARG_INFO(); - PHP_METHOD(PhpSubChunk, collectGarbage) { zend_parse_parameters_none_throw(); @@ -493,19 +451,19 @@ PHP_METHOD(PhpSubChunk, collectGarbage) { } static zend_function_entry sub_chunk_class_methods[] = { - PHP_ME(PhpSubChunk, __construct, arginfo_SubChunk___construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(PhpSubChunk, isEmptyAuthoritative, arginfo_SubChunk_isEmptyAuthoritative, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, isEmptyFast, arginfo_SubChunk_isEmptyFast, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getEmptyBlockId, arginfo_SubChunk_getEmptyBlockId, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getFullBlock, arginfo_SubChunk_getFullBlock, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, setFullBlock, arginfo_SubChunk_setFullBlock, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getBlockLayers, arginfo_SubChunk_getBlockLayers, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getHighestBlockAt, arginfo_SubChunk_getHighestBlockAt, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getBlockSkyLightArray, arginfo_SubChunk_getLightArray, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, setBlockSkyLightArray, arginfo_SubChunk_setLightArray, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getBlockLightArray, arginfo_SubChunk_getLightArray, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, setBlockLightArray, arginfo_SubChunk_setLightArray, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, collectGarbage, arginfo_SubChunk_collectGarbage, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, __construct, arginfo_class_pocketmine_world_format_SubChunk___construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(PhpSubChunk, isEmptyAuthoritative, arginfo_class_pocketmine_world_format_SubChunk_isEmptyAuthoritative, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, isEmptyFast, arginfo_class_pocketmine_world_format_SubChunk_isEmptyFast, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getEmptyBlockId, arginfo_class_pocketmine_world_format_SubChunk_getEmptyBlockId, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getFullBlock, arginfo_class_pocketmine_world_format_SubChunk_getFullBlock, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, setFullBlock, arginfo_class_pocketmine_world_format_SubChunk_setFullBlock, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getBlockLayers, arginfo_class_pocketmine_world_format_SubChunk_getBlockLayers, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getHighestBlockAt, arginfo_class_pocketmine_world_format_SubChunk_getHighestBlockAt, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getBlockSkyLightArray, arginfo_class_pocketmine_world_format_SubChunk_getBlockSkyLightArray, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, setBlockSkyLightArray, arginfo_class_pocketmine_world_format_SubChunk_setBlockSkyLightArray, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, getBlockLightArray, arginfo_class_pocketmine_world_format_SubChunk_getBlockLightArray, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, setBlockLightArray, arginfo_class_pocketmine_world_format_SubChunk_setBlockLightArray, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, collectGarbage, arginfo_collect, ZEND_ACC_PUBLIC) PHP_FE_END }; diff --git a/src/PhpSubChunk_arginfo.h b/src/PhpSubChunk_arginfo.h deleted file mode 100644 index f872b25..0000000 --- a/src/PhpSubChunk_arginfo.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef HAVE_PHP_SUB_CHUNK_ARGINFO_H -#define HAVE_PHP_SUB_CHUNK_ARGINFO_H - -#include "ZendUtil.h" -#include "PhpLightArray.h" - -extern "C" { -#include "php.h" -} - - -ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_SubChunk_getLightArray, 0, 0, pocketmine\\world\\format\\LightArray, 0) -ZEND_END_ARG_INFO(); - - - -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_SubChunk_setLightArray, 0, 1, IS_VOID, 0) - ZEND_ARG_OBJ_INFO(0, data, pocketmine\\world\\format\\LightArray, 0) -ZEND_END_ARG_INFO() - -#define parse_args_SubChunk_setLightArray() \ - zval* data; \ - ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 1) \ - Z_PARAM_OBJECT_OF_CLASS(data, light_array_entry) \ - ZEND_PARSE_PARAMETERS_END(); - -#endif diff --git a/stubs/pocketmine/world/format/SubChunk.stub.php b/stubs/pocketmine/world/format/SubChunk.stub.php new file mode 100644 index 0000000..5754d4a --- /dev/null +++ b/stubs/pocketmine/world/format/SubChunk.stub.php @@ -0,0 +1,71 @@ + Date: Sat, 31 Jul 2021 15:39:22 +0100 Subject: [PATCH 14/16] vs sucks --- src/PhpSubChunk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index 82bf8ba..f9d918f 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -463,7 +463,7 @@ static zend_function_entry sub_chunk_class_methods[] = { PHP_ME(PhpSubChunk, setBlockSkyLightArray, arginfo_class_pocketmine_world_format_SubChunk_setBlockSkyLightArray, ZEND_ACC_PUBLIC) PHP_ME(PhpSubChunk, getBlockLightArray, arginfo_class_pocketmine_world_format_SubChunk_getBlockLightArray, ZEND_ACC_PUBLIC) PHP_ME(PhpSubChunk, setBlockLightArray, arginfo_class_pocketmine_world_format_SubChunk_setBlockLightArray, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, collectGarbage, arginfo_collect, ZEND_ACC_PUBLIC) + PHP_ME(PhpSubChunk, collectGarbage, arginfo_class_pocketmine_world_format_SubChunk_collectGarbage, ZEND_ACC_PUBLIC) PHP_FE_END }; From 1e35730113b381db9822ccba2de4634e08608749 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 31 Jul 2021 15:41:10 +0100 Subject: [PATCH 15/16] Remove unrelated formatting change --- src/ZendUtil.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ZendUtil.h b/src/ZendUtil.h index 73d52ed..5a8a23c 100644 --- a/src/ZendUtil.h +++ b/src/ZendUtil.h @@ -23,3 +23,4 @@ static class_name* alloc_custom_zend_object(zend_class_entry* ce, zend_object_ha } #endif + From ab55d6933392fbf20d853777429c6738ea407e8e Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 31 Jul 2021 20:27:11 +0100 Subject: [PATCH 16/16] Use generated function entries as well as arginfos --- src/PhpSubChunk.cpp | 47 +++++++------------ .../pocketmine/world/format/SubChunk.stub.php | 21 ++------- .../world/format/SubChunk_arginfo.h | 35 +++++++++++++- 3 files changed, 53 insertions(+), 50 deletions(-) diff --git a/src/PhpSubChunk.cpp b/src/PhpSubChunk.cpp index f9d918f..63d1041 100644 --- a/src/PhpSubChunk.cpp +++ b/src/PhpSubChunk.cpp @@ -259,7 +259,9 @@ static void sub_chunk_collect_garbage(sub_chunk_obj* object) { } } -PHP_METHOD(PhpSubChunk, __construct) { +#define SUB_CHUNK_METHOD(name) PHP_METHOD(pocketmine_world_format_SubChunk, name) + +SUB_CHUNK_METHOD(__construct) { zend_long emptyBlockId; HashTable* htBlockLayers; zval* skyLight = NULL; @@ -300,7 +302,7 @@ PHP_METHOD(PhpSubChunk, __construct) { } } -PHP_METHOD(PhpSubChunk, isEmptyAuthoritative) { +SUB_CHUNK_METHOD(isEmptyAuthoritative) { zend_parse_parameters_none_throw(); auto intern = sub_chunk_this(); @@ -308,17 +310,17 @@ PHP_METHOD(PhpSubChunk, isEmptyAuthoritative) { RETURN_BOOL(intern->blockLayers.empty()); } -PHP_METHOD(PhpSubChunk, isEmptyFast) { +SUB_CHUNK_METHOD(isEmptyFast) { zend_parse_parameters_none_throw(); RETURN_BOOL(sub_chunk_this()->blockLayers.empty()); } -PHP_METHOD(PhpSubChunk, getEmptyBlockId) { +SUB_CHUNK_METHOD(getEmptyBlockId) { zend_parse_parameters_none_throw(); RETURN_LONG(sub_chunk_this()->emptyBlockId); } -PHP_METHOD(PhpSubChunk, getFullBlock) { +SUB_CHUNK_METHOD(getFullBlock) { zend_long x, y, z; ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 3, 3) @@ -335,7 +337,7 @@ PHP_METHOD(PhpSubChunk, getFullBlock) { } } -PHP_METHOD(PhpSubChunk, setFullBlock) { +SUB_CHUNK_METHOD(setFullBlock) { zend_long x, y, z, block; ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4) @@ -361,7 +363,7 @@ PHP_METHOD(PhpSubChunk, setFullBlock) { blockLayer->container.set(x, y, z, block); } -PHP_METHOD(PhpSubChunk, getBlockLayers) { +SUB_CHUNK_METHOD(getBlockLayers) { zend_parse_parameters_none_throw(); auto intern = sub_chunk_this(); @@ -374,7 +376,7 @@ PHP_METHOD(PhpSubChunk, getBlockLayers) { } } -PHP_METHOD(PhpSubChunk, getHighestBlockAt) { +SUB_CHUNK_METHOD(getHighestBlockAt) { zend_long x, z; ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 2, 2) @@ -406,7 +408,7 @@ static inline void ensure_light_array_initialized(light_array_obj** lightArray) } } -PHP_METHOD(PhpSubChunk, getBlockSkyLightArray) { +SUB_CHUNK_METHOD(getBlockSkyLightArray) { zend_parse_parameters_none_throw(); auto intern = sub_chunk_this(); @@ -415,7 +417,7 @@ PHP_METHOD(PhpSubChunk, getBlockSkyLightArray) { Z_ADDREF_P(return_value); } -PHP_METHOD(PhpSubChunk, getBlockLightArray) { +SUB_CHUNK_METHOD(getBlockLightArray) { zend_parse_parameters_none_throw(); auto intern = sub_chunk_this(); @@ -436,37 +438,20 @@ PHP_METHOD(PhpSubChunk, getBlockLightArray) { intern->lightArrayFieldName = fetch_from_zend_object(Z_OBJ_P(data)); \ Z_ADDREF_P(data); -PHP_METHOD(PhpSubChunk, setBlockSkyLightArray) { +SUB_CHUNK_METHOD(setBlockSkyLightArray) { macro_SubChunk_setLightArray(skyLight); } -PHP_METHOD(PhpSubChunk, setBlockLightArray) { +SUB_CHUNK_METHOD(setBlockLightArray) { macro_SubChunk_setLightArray(blockLight); } -PHP_METHOD(PhpSubChunk, collectGarbage) { +SUB_CHUNK_METHOD(collectGarbage) { zend_parse_parameters_none_throw(); sub_chunk_collect_garbage(sub_chunk_this()); } -static zend_function_entry sub_chunk_class_methods[] = { - PHP_ME(PhpSubChunk, __construct, arginfo_class_pocketmine_world_format_SubChunk___construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(PhpSubChunk, isEmptyAuthoritative, arginfo_class_pocketmine_world_format_SubChunk_isEmptyAuthoritative, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, isEmptyFast, arginfo_class_pocketmine_world_format_SubChunk_isEmptyFast, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getEmptyBlockId, arginfo_class_pocketmine_world_format_SubChunk_getEmptyBlockId, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getFullBlock, arginfo_class_pocketmine_world_format_SubChunk_getFullBlock, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, setFullBlock, arginfo_class_pocketmine_world_format_SubChunk_setFullBlock, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getBlockLayers, arginfo_class_pocketmine_world_format_SubChunk_getBlockLayers, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getHighestBlockAt, arginfo_class_pocketmine_world_format_SubChunk_getHighestBlockAt, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getBlockSkyLightArray, arginfo_class_pocketmine_world_format_SubChunk_getBlockSkyLightArray, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, setBlockSkyLightArray, arginfo_class_pocketmine_world_format_SubChunk_setBlockSkyLightArray, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, getBlockLightArray, arginfo_class_pocketmine_world_format_SubChunk_getBlockLightArray, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, setBlockLightArray, arginfo_class_pocketmine_world_format_SubChunk_setBlockLightArray, ZEND_ACC_PUBLIC) - PHP_ME(PhpSubChunk, collectGarbage, arginfo_class_pocketmine_world_format_SubChunk_collectGarbage, ZEND_ACC_PUBLIC) - PHP_FE_END -}; - void register_sub_chunk_class() { memcpy(&sub_chunk_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); sub_chunk_handlers.offset = XtOffsetOf(sub_chunk_obj, std); @@ -474,7 +459,7 @@ void register_sub_chunk_class() { sub_chunk_handlers.clone_obj = sub_chunk_clone; zend_class_entry ce; - INIT_CLASS_ENTRY(ce, "pocketmine\\world\\format\\SubChunk", sub_chunk_class_methods); + INIT_CLASS_ENTRY(ce, "pocketmine\\world\\format\\SubChunk", class_pocketmine_world_format_SubChunk_methods); ce.create_object = sub_chunk_new; ce.serialize = sub_chunk_serialize; ce.unserialize = sub_chunk_unserialize; diff --git a/stubs/pocketmine/world/format/SubChunk.stub.php b/stubs/pocketmine/world/format/SubChunk.stub.php index 5754d4a..766af60 100644 --- a/stubs/pocketmine/world/format/SubChunk.stub.php +++ b/stubs/pocketmine/world/format/SubChunk.stub.php @@ -1,23 +1,8 @@