Untitled
unknown
plain_text
2 years ago
25 kB
4
Indexable
#include <database/item/item_core.hpp> #include <constants/config.hpp> #include <database/item/flags.hpp> #include <database/item/types.hpp> #include <database/item/playmods.hpp> #include <utils/io.hpp> #include <utils/text.hpp> #include <utils/binary_reader.hpp> #include <utils/binary_writer.hpp> #include <proton/gametankpacket.hpp> #include <proton/gameupdatepacket.hpp> #include <proton/tools.hpp> #include <fstream> #include <stdexcept> #include <exception> #include <algorithm> #include <filesystem> #include <stdint.h> #include <fmt/core.h> namespace growxyz { item_database::~item_database() { free(m_data); } void item_database::interface__kill() { free(m_data); m_items.clear(); } void item_database::interface__init(const std::filesystem::path& path) { if (std::filesystem::exists(path)) { uint64_t data_size = std::filesystem::file_size(path); m_data = new uint8_t[data_size]; std::ifstream file(path, std::ios::binary); if (file.bad()) return; file.read(reinterpret_cast<char*>(m_data), data_size); file.close(); m_hash = tools::hash(m_data, data_size); binary_reader br = binary_reader(m_data); m_version = br.read_short(); m_item_count = br.read_int(); fmt::print("items.dat initailized, version: {}, total items: {}\n", m_version, m_item_count); for (uint32_t i = 0; i < m_item_count; i++) { item item; item.m_id = br.read_int(); item.m_editable_type = br.read_byte(); item.m_item_category = br.read_byte(); item.m_action_type = br.read_byte(); item.m_hit_sound_type = br.read_byte(); item.m_name = br.read_item_name(item.m_id); item.m_texture = br.read_string(); item.m_texture_hash = br.read_int(); item.m_item_kind = br.read_byte(); item.m_val1 = br.read_int(); item.m_texture_x = br.read_byte(); item.m_texture_y = br.read_byte(); item.m_spread_type = br.read_byte(); item.m_is_stripey_wallpaper = br.read_byte(); item.m_collision_type = br.read_byte(); item.m_break_hits = br.read_byte() / 6; item.m_reset_time = br.read_int(); item.m_clothing_type = br.read_byte(); item.m_rarity = br.read_short(); item.m_max_amount = br.read_byte(); item.m_extra_file = br.read_string(); item.m_extra_file_hash = br.read_int(); item.m_audio_volume = br.read_int(); item.m_pet_name = br.read_string(); item.m_pet_prefix = br.read_string(); item.m_pet_suffix = br.read_string(); item.m_pet_ability = br.read_string(); item.m_seed_base = br.read_byte(); item.m_seed_overlay = br.read_byte(); item.m_tree_base = br.read_byte(); item.m_tree_leaves = br.read_byte(); item.m_seed_color = br.read_int(); item.m_seed_overlay_color = br.read_int(); item.m_ingredient = br.read_int(); item.m_grow_time = br.read_int(); item.m_val2 = br.read_short(); item.m_rayman = br.read_short(); item.m_extra_options = br.read_string(); item.m_texture2 = br.read_string(); item.m_extra_options2 = br.read_string(); br.skip(80); // reversed bytes item.m_punch_options = br.read_string(); item.m_val3 = br.read_int(); for (auto index = 0; index < 9; index++) item.m_bodypart[index] = br.read_byte(); item.m_val4 = br.read_int(); item.m_val5 = br.read_int(); item.m_punch_id = -1; if (i != item.m_id) fmt::print("items are unordered: {}/{}\n", i, item.m_id); switch (item.m_action_type) { case ITEMTYPE_DOOR: case ITEMTYPE_LOCK: case ITEMTYPE_SIGN: case ITEMTYPE_MAIN_DOOR: case ITEMTYPE_SEED: case ITEMTYPE_PORTAL: case ITEMTYPE_MAILBOX: case ITEMTYPE_BULLETIN: case ITEMTYPE_DICE: case ITEMTYPE_PROVIDER: case ITEMTYPE_ACHIEVEMENT: case ITEMTYPE_SUNGATE: case ITEMTYPE_HEART_MONITOR: case ITEMTYPE_DONATION_BOX: case ITEMTYPE_TOYBOX: case ITEMTYPE_MANNEQUIN: case ITEMTYPE_SECURITY_CAMERA: case ITEMTYPE_MAGIC_EGG: case ITEMTYPE_GAME_RESOURCES: case ITEMTYPE_GAME_GENERATOR: case ITEMTYPE_XENONITE: case ITEMTYPE_DRESSUP: case ITEMTYPE_CRYSTAL: case ITEMTYPE_BURGLAR: case ITEMTYPE_SPOTLIGHT: case ITEMTYPE_DISPLAY_BLOCK: case ITEMTYPE_VENDING_MACHINE: case ITEMTYPE_FISHTANK: case ITEMTYPE_SOLAR: case ITEMTYPE_FORGE: case ITEMTYPE_GIVING_TREE: case ITEMTYPE_GIVING_TREE_STUMP: case ITEMTYPE_STEAM_ORGAN: case ITEMTYPE_TAMAGOTCHI: case ITEMTYPE_SWING: case ITEMTYPE_FLAG: case ITEMTYPE_LOBSTER_TRAP: case ITEMTYPE_ART_CANVAS: case ITEMTYPE_BATTLE_CAGE: case ITEMTYPE_PET_TRAINER: case ITEMTYPE_STEAM_ENGINE: case ITEMTYPE_LOCKBOT: case ITEMTYPE_WEATHER_SPECIAL: case ITEMTYPE_SPIRIT_STORAGE: case ITEMTYPE_DISPLAY_SHELF: case ITEMTYPE_VIP_ENTRANCE: case ITEMTYPE_CHALLENGE_TIMER: case ITEMTYPE_CHALLENGE_FLAG: case ITEMTYPE_FISH_MOUNT: case ITEMTYPE_PORTRAIT: case ITEMTYPE_WEATHER_SPECIAL2: case ITEMTYPE_FOSSIL_PREP: case ITEMTYPE_DNA_MACHINE: case ITEMTYPE_BLASTER: case ITEMTYPE_CHEMTANK: case ITEMTYPE_STORAGE: case ITEMTYPE_OVEN: case ITEMTYPE_SUPER_MUSIC: case ITEMTYPE_GEIGER_CHARGER: case ITEMTYPE_ADVENTURE_RESET: case ITEMTYPE_TOMB_ROBBER: case ITEMTYPE_FACTION: case ITEMTYPE_RED_FACTION: case ITEMTYPE_GREEN_FACTION: case ITEMTYPE_BLUE_FACTION: case ITEMTYPE_FISHGOTCHI_TANK: case ITEMTYPE_ITEM_SUCKER: case ITEMTYPE_ROBOT: case ITEMTYPE_TICKET: case ITEMTYPE_STATS_BLOCK: case ITEMTYPE_FIELD_NODE: case ITEMTYPE_OUIJA_BOARD: case ITEMTYPE_AUTO_ACTION_BREAK: case ITEMTYPE_AUTO_ACTION_HARVEST: case ITEMTYPE_AUTO_ACTION_HARVEST_SUCK: case ITEMTYPE_LIGHTNING_IF_ON: case ITEMTYPE_PHASED_BLOCK: case ITEMTYPE_PASSWORD_STORAGE: case ITEMTYPE_PHASED_BLOCK_2: case ITEMTYPE_WEATHER_INFINITY: case ITEMTYPE_KRANKENS_BLOCK: case ITEMTYPE_FRIENDS_ENTRANCE: case 30: case 133: { item.m_has_extra = true; break; } } /*std::string name = item.m_name; std::transform(name.begin(), name.end(), name.begin(), ::toupper); utils::text::replace(name, " ", "_"); fmt::print("{} = {},\n", name, item.m_id);*/ m_items.push_back(std::move(item)); } m_packet = static_cast<gametextpacket_t*>(malloc(sizeof(gametextpacket_t) + sizeof(gameupdatepacket_t) + data_size)); gameupdatepacket_t* update_packet = static_cast<gameupdatepacket_t*>(malloc(sizeof(gameupdatepacket_t) + data_size)); if (m_packet && update_packet) { memset(update_packet, 0, sizeof(gameupdatepacket_t) + data_size); memset(m_packet, 0, sizeof(gametextpacket_t) + sizeof(gameupdatepacket_t) + data_size); m_packet->m_type = NET_MESSAGE_GAME_PACKET; update_packet->m_type = (uint8_t)PACKET_SEND_ITEM_DATABASE_DATA; update_packet->m_net_id = -1; update_packet->m_flags |= PACKET_FLAGS_EXTENDED; update_packet->m_data_size = (uint32_t)data_size; memcpy(&update_packet->m_data, m_data, data_size); memcpy(&m_packet->m_data, update_packet, sizeof(gameupdatepacket_t) + data_size); m_packet_size = sizeof(gametextpacket_t) + sizeof(gameupdatepacket_t) + (uint32_t)data_size; free(update_packet); } } else fmt::print("items.dat doesn't exists\n"); } void item_database::interface__encode(const std::filesystem::path& path) { uint32_t pos = 0; size_t size = m_items.size() * sizeof(item) * 10; uint8_t* data = static_cast<uint8_t*>(malloc(size)); if (!data) { fmt::print("failed to allocate enough data for encoding items.dat\n"); return; } auto write_string = [&](const std::string& str) { uint16_t strsize = static_cast<uint16_t>(str.size()); memcpy(data + pos, &strsize, 2); pos += 2; for (int i = 0; i < strsize; ++i) data[pos++] = static_cast<uint8_t>(str[i]); }; auto write_string_encrypted = [&](int id, const std::string& str) { uint16_t strsize = static_cast<uint16_t>(str.size()); memcpy(data + pos, &strsize, 2); pos += 2; std::string encrypted = tools::cypher(str, id); for (int i = 0; i < strsize; ++i) data[pos++] = static_cast<uint8_t>(encrypted[i]); }; memset(data, 0, size); memcpy(data + pos, &m_version, 2); memcpy(data + pos + 2, &m_item_count, 4); pos += 6; for (const item& item : m_items) { uint32_t id = item.m_id; memcpy(data + pos, &id, 4); pos += 4; memcpy(data + pos, &item.m_editable_type, 1); pos += 1; memcpy(data + pos, &item.m_item_category, 1); pos += 1; memcpy(data + pos, &item.m_action_type, 1); pos += 1; memcpy(data + pos, &item.m_hit_sound_type, 1); pos += 1; write_string_encrypted(item.m_id, item.m_name); write_string(item.m_texture); memcpy(data + pos, &item.m_texture_hash, 4); pos += 4; memcpy(data + pos, &item.m_item_kind, 1); pos += 1; memcpy(data + pos, &item.m_val1, 4); pos += 4; memcpy(data + pos, &item.m_texture_x, 1); pos += 1; memcpy(data + pos, &item.m_texture_y, 1); pos += 1; memcpy(data + pos, &item.m_spread_type, 1); pos += 1; memcpy(data + pos, &item.m_is_stripey_wallpaper, 1); pos += 1; memcpy(data + pos, &item.m_collision_type, 1); pos += 1; uint8_t breakHits = item.m_break_hits * 6; memcpy(data + pos, &breakHits, 1); pos += 1; memcpy(data + pos, &item.m_reset_time, 4); pos += 4; memcpy(data + pos, &item.m_clothing_type, 1); pos += 1; memcpy(data + pos, &item.m_rarity, 2); pos += 2; memcpy(data + pos, &item.m_max_amount, 1); pos += 1; write_string(item.m_extra_file); memcpy(data + pos, &item.m_extra_file_hash, 4); pos += 4; memcpy(data + pos, &item.m_audio_volume, 4); pos += 4; write_string(item.m_pet_name); write_string(item.m_pet_prefix); write_string(item.m_pet_suffix); write_string(item.m_pet_ability); memcpy(data + pos, &item.m_seed_base, 1); pos += 1; memcpy(data + pos, &item.m_seed_overlay, 1); pos += 1; memcpy(data + pos, &item.m_tree_base, 1); pos += 1; memcpy(data + pos, &item.m_tree_leaves, 1); pos += 1; memcpy(data + pos, &item.m_seed_color, 4); pos += 4; memcpy(data + pos, &item.m_seed_overlay_color, 4); pos += 4; memcpy(data + pos, &item.m_ingredient, 4); pos += 4; memcpy(data + pos, &item.m_grow_time, 4); pos += 4; memcpy(data + pos, &item.m_val2, 2); pos += 2; memcpy(data + pos, &item.m_rayman, 2); pos += 2; write_string(item.m_extra_options); write_string(item.m_texture2); write_string(item.m_extra_options2); memcpy(data + pos, item.m_reserved, 80); pos += 80; if (m_version >= 11) { write_string(item.m_punch_options); } if (m_version >= 12) { memcpy(data + pos, &item.m_val3, 4); pos += 4; memcpy(data + pos, item.m_bodypart, 9); pos += 9; } if (m_version >= 13) { memcpy(data + pos, &item.m_val4, 4); pos += 4; } if (m_version >= 15) { pos += 25; uint16_t l = 0; memcpy(data + pos, &l, 2); pos += 2 + l; } } std::ofstream fs(path, std::ios::binary); fs.write(reinterpret_cast<char*>(data), pos); fs.close(); free(data); } void item_database::interface__punch_data_init(const std::filesystem::path& path) { if (std::filesystem::exists(path)) { uint64_t data_size = std::filesystem::file_size(path); uint8_t* m_punch_data = (uint8_t*)malloc(data_size); std::ifstream file(path, std::ios::binary); if (file.bad()) return; file.read(reinterpret_cast<char*>(m_punch_data), data_size); file.close(); binary_reader br = binary_reader(m_punch_data); uint8_t punch_data_version = br.read_byte(); uint32_t punch_data_count = br.read_uint(); for (auto index = 0; index < punch_data_count; index++) { uint32_t item_id = br.read_uint(); uint16_t punch_id = br.read_short(); m_items[item_id].m_punch_id = punch_id; } fmt::print("punch_data.dat initailized, version: {}, total effects: {}\n", punch_data_version, punch_data_count); } else fmt::print("punch_data.dat doesn't exists\n"); } void item_database::interface__seed_data_init(const std::filesystem::path& path) { if (!std::filesystem::exists(path)) { fmt::print("seed_data.dat doesn't exists\n"); return; } uint64_t data_size = std::filesystem::file_size(path); uint8_t* m_seed_data = (uint8_t*)malloc(data_size); std::ifstream file(path, std::ios::binary); if (file.bad()) return; file.read(reinterpret_cast<char*>(m_seed_data), data_size); file.close(); binary_reader br = binary_reader(m_seed_data); uint32_t seed_data_count = br.read_uint(); for (auto index = 0; index < seed_data_count; index++) { uint32_t id_ = br.read_uint(), first_item = br.read_uint(), second_item = br.read_uint(); seed_info.insert_or_assign(id_ + 1, splice_data{ first_item, second_item }); } fmt::print("seed_data.dat initailized, total splice recipes: {}\n", seed_data_count); } void item_database::interface__playmods_init(const std::filesystem::path& path) { if (std::filesystem::exists(path)) { uint64_t data_size = std::filesystem::file_size(path); uint8_t* m_playmods_data = (uint8_t*)malloc(data_size); std::ifstream file(path, std::ios::binary); if (file.bad()) return; file.read(reinterpret_cast<char*>(m_playmods_data), data_size); file.close(); binary_reader br = binary_reader(m_playmods_data); if (br.read_string() != "GrowXYZ") return; int playmods_count = br.read_int(); for (auto index = 0; index < playmods_count; index++) { uint32_t item_id = br.read_uint(); for (auto index = 0; index < 30; index++) m_items[item_id].m_mods_cloth1[index] = br.read_int(); for (auto index = 0; index < 30; index++) m_items[item_id].m_mods_cloth2[index] = br.read_int(); for (auto index = 0; index < 26; index++) m_items[item_id].m_mods_consumable[index] = br.read_int(); } fmt::print("items_playmod.dat initailized, total playmods: {}\n", playmods_count); } else fmt::print("items_playmod.dat doesn't exists\n"); } void item_database::interface__description_init(const std::filesystem::path& path) { if (!std::filesystem::exists(path)) { fmt::print("items_description.dat doesn't exists\n"); return; } uint64_t data_size = std::filesystem::file_size(path); uint8_t* m_description_data = (uint8_t*)malloc(data_size); std::ifstream file(path, std::ios::binary); if (file.bad()) return; file.read(reinterpret_cast<char*>(m_description_data), data_size); file.close(); binary_reader br = binary_reader(m_description_data); if (br.read_string() != "GrowXYZ") return; int descriptions_count = br.read_int(); for (auto index = 0; index < descriptions_count; index++) { uint32_t item_id = br.read_uint(); m_items[item_id].m_description = br.read_string(); } fmt::print("items_description.dat initailized, total descriptions: {}\n", descriptions_count); } void item_database::interface__pet_abilities_init(const std::filesystem::path& path) { if (!std::filesystem::exists(path)) { fmt::print("items_description.dat doesn't exists\n"); return; } uint64_t data_size = std::filesystem::file_size(path); uint8_t* m_description_data = (uint8_t*)malloc(data_size); std::ifstream file(path, std::ios::binary); if (file.bad()) return; file.read(reinterpret_cast<char*>(m_description_data), data_size); file.close(); binary_reader br = binary_reader(m_description_data); if (br.read_string() != "GrowXYZ") return; int pet_abilities = br.read_int(); for (auto index = 0; index < pet_abilities; index++) { uint32_t item_id = br.read_uint(); item::pet_ability pet; pet.m_element = br.read_byte(); pet.m_ability = br.read_string(); pet.m_cooldown_effect = br.read_string(); pet.m_cooldown = std::chrono::seconds(br.read_long_long()); pet.m_suffix = br.read_string(); m_items[item_id].m_pet_battle = pet; m_items[item_id].m_has_battle_data = true; } fmt::print("pet_abilities.dat initailized, total abilities: {}\n", pet_abilities); } const item& item_database::interface__get_item(uint32_t id) const { if (id > m_items.size() || id < 0) return m_items.at(0); return m_items.at(id); } const item& item_database::interface__get_item(item_component id) const { if ((uint32_t)id > m_items.size()) return m_items.at(0); return m_items.at((uint32_t)id); } item& item_database::interface__get_item_unsafe(uint32_t id) { return m_items.at(id); } const item& item_database::interface__get_item(const std::string& name) const { for (auto& item : m_items) { if (item.m_name == name) return item; } return m_items.at(0); } std::vector<item> item_database::interface__get_items_matching(const std::string& name) const { std::vector<item> items; std::string lower_name = name; std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), [](unsigned char c) { return std::tolower(c); }); for (auto& item : m_items) { std::string lower_case = item.m_name; std::transform(lower_case.begin(), lower_case.end(), lower_case.begin(), [](unsigned char c) { return std::tolower(c); }); if (lower_case.find(lower_name) != std::string::npos) { if (item.m_id % 2 == 1) continue; items.push_back(item); } } return items; } const std::vector<item>& item_database::interface__get_items() { return m_items; } uint32_t item_database::interface__get_hash() const { return m_hash; } uint8_t* item_database::interface__get_data() { return m_data; } gametextpacket_t* item_database::interface__get_packet() { return m_packet; } uint32_t item_database::interface__get_packet_size() const { return m_packet_size; } uint32_t item_database::inteface__modify_item(uint32_t id, const item& item) { growxyz::item it = m_items.at(id); if (it.m_name.find("null_item") == std::string::npos && it.m_name != item.m_name) { m_items.at(id) = item; m_items.at(id).m_id = id; it.m_id = m_items.size(); m_items.push_back(it); m_item_count += 1; } else { m_items.at(id) = item; m_items.at(id).m_id = id; } if (!it.m_texture.empty()) { uintmax_t filesize = 0; std::string file = fmt::format("data/cache/{}", m_items.at(id).m_texture); void* data = NULL; if (std::filesystem::exists(file)) data = utils::io::read_all_bytes(file, filesize); if (!data) {} else { m_items.at(id).m_texture_hash = tools::hash(data, filesize); free(data); } } if (!it.m_extra_file.empty()) { uintmax_t filesize = 0; std::string file = fmt::format("data/cache/{}", m_items.at(id).m_extra_file); void* data = NULL; if (std::filesystem::exists(file)) data = utils::io::read_all_bytes(file, filesize); if (!data) {} else { m_items.at(id).m_extra_file_hash = tools::hash(data, filesize); free(data); } } return id; } bool item_is_world_lock(const item& item_) { return item_.m_id != (uint32_t)item_component::SMALL_LOCK && item_.m_id != (uint32_t)item_component::BIG_LOCK && item_.m_id != (uint32_t)item_component::HUGE_LOCK && item_.m_id != (uint32_t)item_component::BUILDER_LOCK; } bool item_is_background(const item& item_) { return item_.m_action_type == ITEMTYPE_BACKGROUND || item_.m_action_type == ITEMTYPE_BACK_BOOMBOX || item_.m_action_type == ITEMTYPE_MUSIC_NOTE; } }
Editor is loading...