Skip to content

Kernel plugin

Kernel manages runtime entities, entity schemas, static configuration and map instances. Application modules use kernel_module to create, find and destroy entities, then use entity to access fields, tables and containers.

Modules and data model

Object / module Responsibility Main interfaces
class_meta_module Load entity and configuration schemas; manage class event callbacks find_meta(), find_static_meta(), add_class_call_back()
config_module Find loaded static data by configuration ID find_static_entity()
map_module Create maps and instances; track entities in each instance create_map(), create_map_instance(), get_inst_entity_list()
kernel_module Manage entities and events; convert entity data create_entity(), get_entity(), destroy_entity(), entity_to_db_data()
entity Runtime fields, tables, containers and spatial position get_int32(), set_int32(), find_table(), find_container()
static_entity A configuration record loaded from resource files get_config_id(), get_int32(), get_string()

Schemas and configuration values are separate data: a schema defines field names, types, indices and attributes; static configuration supplies values for a configuration ID; runtime entities have their own IDs and mutable data.

Resource loading

The metadata module loads resource/meta/config_class.config and resource/meta/entity_class.config during init(). These files reference individual schema files; configuration schemas may also specify data resources. During post_init(), config_module loads static records using this metadata.

Query configuration after the framework has completed the relevant initialization. Creating a runtime entity requires its class schema, map and map instance to exist. Register class event callbacks before creating entities of that class. See Create a module for module integration.

Create and find entities

The following function runs in a process with the Kernel plugin loaded. The application chooses map_id; create_map() creates its default instance with ID 0. This example uses the existing Player schema, with no configuration record or application field writes.

#include <memory>

#include "ark/kernel/data_list_impl.hpp"
#include "ark/kernel/kernel_module.hpp"
#include "ark/kernel/map_module.hpp"
#include "ark/meta_define.hpp"
#include "ark/plugin_manager.hpp"

std::shared_ptr<ark::entity> create_player(ark::plugin_manager& manager, int map_id) {
    auto* kernel = manager.find_module<ark::kernel_module>();
    auto* maps = manager.find_module<ark::map_module>();
    if (kernel == nullptr || maps == nullptr)
    {
        return nullptr;
    }

    if (!maps->exist_map(map_id) && !maps->create_map(map_id))
    {
        return nullptr;
    }

    ark::data_list_impl args;
    return kernel->create_entity(ark::null_guid, map_id, 0, ark::entity_meta_player::self_name(), 0, args);
}

create_entity() returns nullptr on failure, for example when the class schema, map or instance is missing, the entity ID already exists, or the argument count is invalid. Passing null_guid requests an ID from the Guid module. Initialization arguments are value/field-index pairs; this example passes an empty list. Use get_entity(id) to find an entity, exist(id) to test registration and destroy_entity(id) to request destruction.

Holding a shared_ptr<entity> does not mean the entity remains registered with Kernel. After destruction, do not treat an externally retained pointer as a live application entity; look it up by ID again when needed.

Configuration defaults and initialization arguments

When config_id > 0, the configuration record must exist and match the entity class. Configuration supplies defaults for unspecified fields; valid args override the same field, including an explicit 0 or empty string. If a field appears more than once in valid arguments, the last value wins. Entity data is independent of the configuration record, so modifying an entity does not modify the source configuration.

Arguments are (value, uint32_t field_index) pairs: add the value first, then add its index with add_u_int(). Indices must belong to the loaded entity schema, and each value type must exactly match its field type. Do not rely on implicit conversions.

The following example uses Player.level declared as int32 and Player.name declared as string. It explicitly sets the level to 0 and the name to an empty string, while retaining configuration defaults for the other fields. The target map, instance and matching Player configuration record must already exist.

#include <memory>

#include "ark/kernel/data_list_impl.hpp"
#include "ark/kernel/kernel_module.hpp"
#include "ark/meta_define.hpp"

std::shared_ptr<ark::entity> create_configured_player(
    ark::kernel_module& kernel, int map_id, int instance_id, ark::id_type config_id) {
    ark::data_list_impl args;
    args.add_int(0);
    args.add_u_int(ark::entity_meta_player::level_index());
    args.add_string("");
    args.add_u_int(ark::entity_meta_player::name_index());

    return kernel.create_entity(
        ark::null_guid, map_id, instance_id, ark::entity_meta_player::self_name(), config_id, args);
}

Defaults and argument values are ready before the first class event, entity_evt_pre_load_data. create_container_entity() has no args parameter and initializes from configuration. create_entity(protobuf_data) restores saved data without automatically merging configuration defaults.

Access fields, tables and configuration

Field access belongs to entity, using a field name or metadata index. The accessor type must match the schema. Do not use a numeric field value to determine whether an entity or field exists.

#include <cstdint>
#include <string>

#include "ark/kernel/kernel_module.hpp"

bool set_int32_field(ark::kernel_module& kernel, const ark::guid_t& id, const std::string& field, std::int32_t value) {
    auto object = kernel.get_entity(id);
    if (object == nullptr || object->get_node_type(field) != ark::data_type::dt_int32)
    {
        return false;
    }

    return object->set_int32(field, value);
}
Data Access
Scalar fields entity::get_bool(), get_int32(), get_int64(), get_string(), get_guid() and related methods; write using the matching set_*()
Tables entity::find_table() returns table*; use find_row() / add_row() to obtain row*, then access columns by name or index
Containers entity::find_container() returns a container; kernel_module::create_container_entity() creates an entity inside it
Static configuration config_module::find_static_entity(config_id) returns shared_ptr<static_entity>; check for null, then read fields with their known schema types

table* and row* are borrowed pointers, with no independent ownership of entity data. Do not retain them after removing the row, clearing the table or destroying the owning entity.

Register events

Class callbacks cover creation / destruction, field changes, table changes and container operations. Individual entities can also have application event handlers. Register common class callbacks with add_common_class_event().

#include <string>

#include "ark/kernel/kernel_module.hpp"

class entity_observer
{
public:
    bool attach(ark::kernel_module& kernel, const std::string& class_name) {
        return kernel.add_class_call_back(class_name, this, &entity_observer::on_class_event);
    }

private:
    int on_class_event(
        const ark::guid_t& id, const std::string& class_name, ark::entity_event event, const ark::data_list& args) {
        if (event == ark::entity_event::entity_evt_data_finished)
        {
            // Handle the entity after its creation stages complete.
        }
        return 0;
    }
};

Registration retains the object pointer. Keep entity_observer alive while its callback can run; do not register a local object that immediately leaves scope. The current interface has no matching public unregister method.

The ordinary create_entity() overload dispatches class events synchronously in this order:

Stage entity_event
Before loading entity_evt_pre_load_data
Loading entity_evt_load_data
Before applying data entity_evt_pre_effect_data
Applying data entity_evt_effect_data
After applying data entity_evt_post_effect_data
Data stages complete entity_evt_data_finished

The application may explicitly dispatch entity_evt_all_finished; the creation function above does not send it automatically. Normal entity destruction dispatches entity_evt_pre_destroy followed by entity_evt_destroy.

Use add_node_call_back() and add_table_call_back() for field and table changes. Their arguments include the entity ID, changed location and old / new values. do_event(id, event_id, args) dispatches an application event for one entity. Consult the public headers for callback signatures and priority parameters.

Maps and data conversion

Each map is identified by map_id and can have multiple instances. create_map_instance() returns an instance ID on success or -1 on failure. switch_map() moves an existing entity to a target instance; the target map and instance must already exist.

The map module exposes entity lists and online counts. It does not provide a complete area-of-interest (AOI) system. Applications supply spatial indices, grid visibility and broadcast rules. get_max_online_count() currently returns a fixed value; it is not a deployment capacity limit or a capacity test result.

entity_to_db_data() converts an entity to ark::protobuf::protobuf_db_entity; the corresponding create_entity(protobuf_data) overload restores it. entity_node_to_protobuf_data() and entity_table_to_protobuf_data() can select fields by data mask. Conversion does not persist data to a database: applications own persistence, version compatibility and validation after restoration.

API sources

Navigation

Type to search…

↑↓ navigate↵ selectEsc close