0, "Body" => 0, ...]
* If the slot is used by an item, the value is the item_id, else it is 0
*
* The inventory ID of an item is generated each time the item is added to the character's inventory.
* It is not the same as the item definition ID.
*/
class Item_Definition {
public $id;
public $code;
public $name;
public $description;
public $stats;
public $image_url;
public function __construct( $id, $code, $name, $description, $stats, $image_url ) {
$this->id = $id;
$this->code = $code;
$this->name = $name;
$this->description = $description;
$this->stats = json_decode( $stats, true );
$this->image_url = $image_url;
}
public static function get_item_definition_by_id( $id ): ?Item_Definition {
global $wpdb;
$result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM " . $wpdb->prefix . "adventurebook_item_definitions WHERE id = %d", $id ), ARRAY_A );// phpcs:ignore WordPress.DB.DirectDatabaseQuery
if ( $result === null ) {
return null;
}
return new Item_Definition( $result['id'], $result['code'], $result['name'], $result['description'], $result['stats'], $result['image_url'] );
}
public static function get_item_definition_by_code( $code ): ?Item_Definition {
global $wpdb;
$result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM " . $wpdb->prefix . "adventurebook_item_definitions WHERE code = %s", $code ), ARRAY_A );// phpcs:ignore WordPress.DB.DirectDatabaseQuery
if ( $result === null ) {
return null;
}
return new Item_Definition( $result['id'], $result['code'], $result['name'], $result['description'], $result['stats'], $result['image_url'] );
}
public static function get_all_item_definitions(): array {
global $wpdb;
$results = $wpdb->get_results( "SELECT * FROM " . $wpdb->prefix . "adventurebook_item_definitions", ARRAY_A );// phpcs:ignore WordPress.DB.DirectDatabaseQuery
$item_definitions = array();
foreach ( $results as $result ) {
$item_definitions[] = new Item_Definition( $result['id'], $result['code'], $result['name'], $result['description'], $result['stats'], $result['image_url'] );
}
// sort by name
usort( $item_definitions, function ( $a, $b ) {
return strcmp( $a->name, $b->name );
} );
return $item_definitions;
}
public static function create_item_definition( $code, $name, $description, $stats, $image_url ): void {
global $wpdb;
$table_name = $wpdb->prefix . 'adventurebook_item_definitions';
$wpdb->insert( $table_name, array(// phpcs:ignore WordPress.DB.DirectDatabaseQuery
'code' => $code,
'name' => $name,
'description' => $description,
'stats' => json_encode( $stats ),
'image_url' => $image_url
) );
}
public static function update_item_definition( $id, $code, $name, $description, $stats, $image_url ): void {
global $wpdb;
$table_name = $wpdb->prefix . 'adventurebook_item_definitions';
$wpdb->update( $table_name, array(// phpcs:ignore WordPress.DB.DirectDatabaseQuery
'code' => $code,
'name' => $name,
'description' => $description,
'stats' => json_encode( $stats ),
'image_url' => $image_url
), array( 'id' => $id ) );
}
public static function delete_item_definition( $id ): void {
global $wpdb;
$table_name = $wpdb->prefix . 'adventurebook_item_definitions';
$wpdb->delete( $table_name, array( 'id' => $id ) );// phpcs:ignore WordPress.DB.DirectDatabaseQuery
}
public function save_to_db(): void {
if ( $this->id === 0 ) {
self::create_item_definition( $this->code, $this->name, $this->description, $this->stats, $this->image_url );
} else {
self::update_item_definition( $this->id, $this->code, $this->name, $this->description, $this->stats, $this->image_url );
}
}
// get stats for this item
public function get_stats(): array {
if(!is_array($this->stats)) {
return array();
}
return $this->stats;
}
/**
* If this item is a recipe, get the resulting item code from the recipe data
* It is the last part of the recipe data string, separated by ";"
*
* @param string $recipe_data The recipe data string
* @return string The resulting item code
*/
public static function get_recipe_resulting_itemcode(string $recipe_data) : string {
$parts = explode( ';', $recipe_data );
return trim( end( $parts ) );
}
public static function get_recipe_needed_ingredients(string $recipe_data) : array {
$parts = explode( ';', $recipe_data );
array_pop( $parts ); // remove the last part (resulting item code)
$ingredients = array();
foreach ( $parts as $part ) {
$ingredient_parts = explode( ':', $part );
if ( count( $ingredient_parts ) === 2 ) {
$ingredient_code = trim( $ingredient_parts[0] );
$ingredient_quantity = intval( trim( $ingredient_parts[1] ) );
$ingredients[ $ingredient_code ] = $ingredient_quantity;
}
}
return $ingredients;
}
public function get_description(): string {
// if this item has the slot "Recipe", it has also a stat "UseData" which contains the recipe description
$output = '';
if ( isset( $this->stats['Slot'] ) && $this->stats['Slot'] === 'Recipe' && isset( $this->stats['UseData'] ) && ! empty( $this->stats['UseData'] ) ) {
$use_data = $this->stats['UseData'];
$resulting_item_code = Item_Definition::get_recipe_resulting_itemcode( $use_data );
$resulting_item_definition = Item_Definition::get_item_definition_by_code( $resulting_item_code );
$resulting_item_name = $resulting_item_definition ? $resulting_item_definition->name : __('Unknown Item', 'adventurebook');
/* translators: %s is the name of the resulting item */
$output .= sprintf( __( 'This recipe can be used to craft: %s', 'adventurebook' ), esc_html( $resulting_item_name ) ) . '
';
// now print out the needed ingredients
$needed_ingredients = Item_Definition::get_recipe_needed_ingredients( $use_data );
$output .= __( 'Needed ingredients:', 'adventurebook' );
// iterate over needed ingredients and show their names with the quantity as comma separated string (e.g. "1x Item_Name1, 4x Item_Name2")
$ingredient_strings = array();
foreach ( $needed_ingredients as $ingredient_code => $quantity ) {
$ingredient_definition = Item_Definition::get_item_definition_by_code( $ingredient_code );
$ingredient_name = $ingredient_definition ? $ingredient_definition->name : __('Unknown Item', 'adventurebook');
$ingredient_strings[] = intval( $quantity ) . 'x ' . esc_html( $ingredient_name );
}
$output .= ' ' . implode( ', ', $ingredient_strings );
return $output;
}
return $this->description;
}
public function get_item_slot(): ?string {
if ( isset( $this->stats['Slot'] ) && ! empty( $this->stats['Slot'] ) ) {
return $this->stats['Slot'];
}
return null;
}
public function get_main_slot(): ?string {
$slot = $this->get_item_slot();
if ( $slot === null ) {
return null;
}
// if the slot contains a "+", return only the part before the "+"
if ( str_contains( $slot, '+' ) ) {
$parts = explode( '+', $slot );
return trim( $parts[0] );
}
return $slot;
}
public function is_two_handed(): bool {
$slot = $this->get_item_slot();
if ( $slot === null ) {
return false;
}
$parts = explode( '+', $slot );
return count( $parts ) > 1;
}
/** * Generates the HTML representation of the item, including its image, name, and description.
*
* @param Combat_System $adventurebook_combat_system The combat system to determine which stats to show.
*
* @return string The HTML content for the item.
*/
public function get_item_html( Combat_System $adventurebook_combat_system, $count = 0 ): string {
$item = $this;
$item_id = 'adventurebook_item_' . $item->id; // eindeutige ID für JS-Selektoren
$content = '