Refactor some more...

This commit is contained in:
Knaapchen 2022-10-24 21:53:08 +02:00
parent dd25872771
commit 5bd9972c4c
18 changed files with 306 additions and 144 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.vscode
/bin
/build
.idea

View File

@ -2,12 +2,13 @@ add_library(
flyff-api
"src/flyff.cpp"
"src/Neuz.cpp"
"src/Mover.cpp"
"src/object/mover/Mover.cpp"
"src/import.cpp"
"src/api.cpp"
"include/flyff.h"
src/core.h
src/skill/SkillProperty.h
src/object/ObjectProperty.h src/item/ItemKind2.h src/item/ItemKind3.h src/item/Part.h src/item/InventoryItem.h)
src/object/ObjectProperty.h src/item/ItemKind2.h src/item/ItemKind3.h src/item/Part.h src/item/InventoryItem.h src/object/mover/JobProperty.h)
target_include_directories(flyff-api PUBLIC "include")
target_link_libraries(flyff-api PUBLIC flyff-client fugg-api)

1
flyff-api/README.md Normal file
View File

@ -0,0 +1 @@
This project contains all code that is reverse engineered from the original WebAssembly code.

View File

@ -4,13 +4,13 @@
// #include "../src/api.h"
#include "../src/Neuz.h"
#include "../src/Mover.h"
#include "../src/object/mover/Mover.h"
#include "../src/object/Object.h"
#include "../src/object/ObjectProperty.h"
#include "../src/object/ObjectType.h"
#include "../src/skill/Skill.h"
#include "../src/skill/SkillID.h"
#include "../src/skill/SkillProperty.h"
#include "../src/import.h"

View File

@ -1,18 +0,0 @@
#pragma once
enum class Job : int {
Vagrant = 0,
Mercenary = 1,
Acrobat = 2,
Assist = 3,
Magician = 4,
Puppeteer = 5,
Knight = 6,
Blade = 7,
Jester = 8,
Ranger = 9,
Ringmaster = 10,
Billposter = 11,
Psychikeeper = 12,
Elementor = 13
};

View File

@ -142,7 +142,7 @@ namespace flyff {
}
Pointer<SkillProperty> Neuz::get_skill_property(const Skill &id) {
Pointer<SkillProperty> Neuz::get_skill_property(const SkillID &id) {
return Pointer<SkillProperty>(raw::get_skill_prop(static_cast<uint32_t>(id), 1));
}
} // namespace flyff

View File

@ -4,10 +4,10 @@
#include <cstdint>
#include "skill/Skill.h"
#include "skill/SkillID.h"
#include "skill/SkillProperty.h"
#include "Mover.h"
#include "object/mover/Mover.h"
namespace flyff {
// Find this is f195_calls_websocket_send
@ -59,7 +59,7 @@ namespace flyff {
bool is_valid_attack(const Pointer<Mover> &attacker, const Pointer<Mover> &defender) const;
static Pointer<SkillProperty> get_skill_property(const Skill& id) ;
static Pointer<SkillProperty> get_skill_property(const SkillID& id) ;
// Easy to implement: Just send a EmscriptenKeyboardEvent* to the registered
// function. void send_keydown(); void send_keyup(); void send_keypress();

View File

@ -1,7 +1,7 @@
#pragma once
#include "core.h"
#include "Mover.h"
#include "object/mover/Mover.h"
namespace flyff {
class Project {

View File

@ -0,0 +1,76 @@
#pragma once
#include <cstdint>
namespace flyff {
enum class JobID : uint32_t {
Vagrant = 0,
Mercenary = 1,
Acrobat = 2,
Assist = 3,
Magician = 4,
Puppeteer = 5,
Knight = 6,
Blade = 7,
Jester = 8,
Ranger = 9,
Ringmaster = 10,
Billposter = 11,
Psychikeeper = 12,
Elementor = 13
};
static std::ostream &operator<<(std::ostream &os, const JobID &type) {
switch (type) {
case JobID::Vagrant:
os << "Vagrant";
break;
case JobID::Mercenary:
os << "Mercenary";
break;
case JobID::Acrobat:
os << "Acrobat";
break;
case JobID::Assist:
os << "Assist";
break;
case JobID::Magician:
os << "Magician";
break;
case JobID::Puppeteer:
os << "Puppeteer";
break;
case JobID::Knight:
os << "Knight";
break;
case JobID::Blade:
os << "Blade";
break;
case JobID::Jester:
os << "Jester";
break;
case JobID::Ranger:
os << "Ranger";
break;
case JobID::Ringmaster:
os << "Ringmaster";
break;
case JobID::Billposter:
os << "Billposter";
break;
case JobID::Psychikeeper:
os << "Psychikeeper";
break;
case JobID::Elementor:
os << "Elementor";
break;
default:
os << "Unknown";
break;
}
return os;
}
};

View File

@ -0,0 +1,23 @@
//
// Created by main on 22-10-22.
//
#ifndef FUGG_JOBPROPERTY_H
#define FUGG_JOBPROPERTY_H
#include "../../core.h"
#include "JobID.h"
namespace flyff {
struct JobProperty {
union {
DEFINE_MEMBER(12, const JobID, id);
const MinimumSize<28> _size;
};
};
};
#endif //FUGG_JOBPROPERTY_H

View File

@ -0,0 +1,29 @@
#include "Mover.h"
#include "../../Neuz.h"
namespace flyff {
uint64_t Mover::Buff::get_time_remaining() const {
const auto &neuz = Neuz::instance();
if (time_instantiated == 0)
return 0;
auto elapsed =
(neuz.maybe_login_time +
((neuz.current_time + time_instantiated * -1000) - neuz.start_time)) /
1000;
if (elapsed <= time_total) {
return time_total - elapsed;
}
return 0;
}
bool Mover::is_in_combat() const {
const auto &neuz = flyff::Neuz::instance();
// 10 seconds
return neuz.current_time - last_combat < 10000000;
}
}; // namespace flyff

View File

@ -1,24 +1,25 @@
#pragma once
#include <fugg.h>
#include "fugg.h"
#include <cstddef>
#include <iterator>
#include <bitset>
#include <cmath>
#include "core.h"
#include "item/ItemProperty.h"
#include "math.h"
#include "../../core.h"
#include "../../item/ItemProperty.h"
#include "../../math.h"
#include "object/Object.h"
#include "object/ObjectProperty.h"
#include "object/ObjectType.h"
#include "../Object.h"
#include "../ObjectProperty.h"
#include "../ObjectType.h"
#include "skill/Skill.h"
#include "../../skill/SkillID.h"
#include "item/InventoryItem.h"
#include "item/Part.h"
#include "../../item/InventoryItem.h"
#include "../../item/Part.h"
#include "JobProperty.h"
namespace flyff {
namespace raw {
@ -57,7 +58,7 @@ namespace flyff {
struct __attribute__((packed)) Skill {
union {
DEFINE_MEMBER(0, const flyff::Skill, id);
DEFINE_MEMBER(0, const flyff::SkillID, id);
DEFINE_MEMBER(4, const uintptr_t, level);
};
};
@ -76,9 +77,9 @@ namespace flyff {
};
union {
DEFINE_MEMBER(0, const Pointer<Vtable>, vtable);
DEFINE_MEMBER(0, const Pointer<const Vtable>, vtable);
DEFINE_MEMBER(4, const Pointer<ObjectProperty>, property);
DEFINE_MEMBER(4, const Pointer<const ObjectProperty>, property);
DEFINE_MEMBER(8, const Parameter, param_id);
DEFINE_MEMBER(16, const uint64_t, time_instantiated);
@ -108,14 +109,14 @@ namespace flyff {
};
union {
DEFINE_MEMBER(0x0, const Pointer<Vtable>, vtable);
DEFINE_MEMBER(0x0, const Pointer<const Vtable>, vtable);
DEFINE_MEMBER(0x18, Matrix4, world_matrix);
DEFINE_MEMBER(152, Vector3, position);
DEFINE_MEMBER(164, Vector3, rotation);
DEFINE_MEMBER(188, Pointer<ObjectProperty>, property);
DEFINE_MEMBER(188, const Pointer<const ObjectProperty>, property);
DEFINE_MEMBER(212, int, property_id);
DEFINE_MEMBER(216, bool, is_despawned);
@ -150,7 +151,7 @@ namespace flyff {
DEFINE_MEMBER(1792, int, current_animation);
DEFINE_MEMBER(204, ObjectType, type);
DEFINE_MEMBER(204, const ObjectType, type);
DEFINE_MEMBER(216, uint32_t, existence_check);
@ -163,6 +164,8 @@ namespace flyff {
DEFINE_MEMBER(860, Vector<InventoryItem>, inventory);
DEFINE_MEMBER(2432, const flyff::Pointer<const JobProperty>, job_property);
DEFINE_MEMBER(3324, Timestamp, last_food_time);
DEFINE_MEMBER(3348, Timestamp, last_refresher_time);
DEFINE_MEMBER(3356, Timestamp, last_vitaldrink_time);
@ -172,7 +175,11 @@ namespace flyff {
const MinimumSize<4096> size;
};
uint32_t get_skill_level(const flyff::Skill &skill_index) const {
JobID get_job() const {
return job_property ? job_property->id : static_cast<JobID>(-1);
}
uint32_t get_skill_level(const flyff::SkillID &skill_index) const {
for (const auto &skill: skills) {
if (skill_index == skill.id)
return skill.level;

View File

@ -0,0 +1,31 @@
#pragma once
#include "../core.h"
namespace flyff {
enum class SkillID : uint32_t {
// Assist skills
Haste = 20,
Heal = 44,
Resurrection = 45,
Patience = 46,
Prevention = 48,
HeapUp = 49,
CannonBall = 50,
CircleHealing = 51,
MentalSign = 52,
BeefUp = 53,
Stonehand = 113,
QuickStep = 114,
CatsReflex = 115,
Accuracy = 116,
PowerFist = 117,
};
static std::ostream &operator<<(std::ostream &os, const SkillID &type) {
os << static_cast<uint32_t>(type);
return os;
}
}; // namespace flyff

View File

@ -7,7 +7,7 @@
#include "../core.h"
#include "Skill.h"
#include "SkillID.h"
namespace flyff {
struct __attribute__((packed)) SkillProperty {
@ -18,7 +18,7 @@ namespace flyff {
DEFINE_MEMBER(216, const int, required_level);
DEFINE_MEMBER(224, const int, level);
DEFINE_MEMBER(288, const Skill, id);
DEFINE_MEMBER(288, const SkillID, id);
const MinimumSize<332> _size;
};

View File

@ -1 +1 @@
# Decompiled Flyff Universe source
This project contains all code that is decompiled from the original WebAssembly code.

View File

@ -3,9 +3,13 @@
#include <flyff.h>
#include <iostream>
#include <memory>
#include <sstream>
namespace fugg {
Client::Client() {
}
}
constexpr const uint32_t hash_to_id(const uint32_t hashed) {
@ -42,7 +46,7 @@ void send_packet(const uint32_t &id, std::vector<uint8_t> payload) {
auto raw_payload = reinterpret_cast<const Vector *>(&payload);
// Copy the message into a new ptr
auto payload_ = std::unique_ptr<Vector>(new Vector{
auto payload_ = std::make_unique<Vector>(Vector{
.begin = fugg::RuntimePointer<uintptr_t>(raw_payload->begin).as_raw(),
.end = fugg::RuntimePointer<uintptr_t>(raw_payload->end).as_raw(),
.capacity = fugg::RuntimePointer<uintptr_t>(raw_payload->capacity).as_raw()
@ -142,7 +146,7 @@ void interact_target(const unsigned long long &index) {
send_motion_packet(0x11, {index});
}
void use_skill(const flyff::Skill& id, uint32_t server_tick_delta = 0) {
void use_skill(const flyff::SkillID &id, uint32_t server_tick_delta = 0) {
static constexpr unsigned long long param1 = -1;
send_motion_packet(0x5, {static_cast<unsigned long long>(id), param1}, server_tick_delta);
@ -177,11 +181,12 @@ void write_chat_message(const std::string &message) {
send_packet(0x2000, packet);
}
flyff::Pointer<flyff::Mover::Buff> find_skill_buff(const flyff::Pointer<flyff::Mover> &mover, const flyff::Skill& skill_index) {
flyff::Pointer<flyff::Mover::Buff>
find_skill_buff(const flyff::Pointer<flyff::Mover> &mover, const flyff::SkillID &skill_index) {
for (const auto &buff: mover->buffs) {
if (buff->get_type() == flyff::Mover::Buff::Type::Skill) {
auto skill_property = reinterpret_cast<flyff::SkillProperty *>(
static_cast<flyff::ObjectProperty *>(buff->property)
auto skill_property = reinterpret_cast<const flyff::SkillProperty *>(
static_cast<const flyff::ObjectProperty *>(buff->property)
);
if (!buff->is_removed && skill_property->id == skill_index)
@ -193,10 +198,11 @@ flyff::Pointer<flyff::Mover::Buff> find_skill_buff(const flyff::Pointer<flyff::M
}
template<size_t size>
std::vector<flyff::Skill> check_rebuff(const flyff::Pointer<flyff::Mover> &player, const flyff::Skill (&buffs_to_check)[size]) {
std::vector<flyff::SkillID>
check_rebuff(const flyff::Pointer<flyff::Mover> &player, const flyff::SkillID (&buffs_to_check)[size]) {
const auto &neuz = flyff::Neuz::instance();
auto result = std::vector<flyff::Skill>();
auto result = std::vector<flyff::SkillID>();
for (const auto &skill_index: buffs_to_check) {
const auto &buff = find_skill_buff(player, skill_index);
const auto &skill_property = flyff::Neuz::get_skill_property(skill_index);
@ -205,8 +211,8 @@ std::vector<flyff::Skill> check_rebuff(const flyff::Pointer<flyff::Mover> &playe
auto player_skill_level = player->get_skill_level(skill_index);
// For some reason it's one off...
auto current_skill_level = buff->level + 1;
auto buff_property = reinterpret_cast<flyff::SkillProperty *>(
static_cast<flyff::ObjectProperty *>(buff->property)
auto buff_property = reinterpret_cast<const flyff::SkillProperty *>(
static_cast<const flyff::ObjectProperty *>(buff->property)
);
if (player_skill_level > current_skill_level) {
@ -225,7 +231,7 @@ std::vector<flyff::Skill> check_rebuff(const flyff::Pointer<flyff::Mover> &playe
return result;
}
flyff::Pointer<flyff::InventoryItem> find_first_equippable_item(const flyff::ItemKind3& item_kind) {
flyff::Pointer<const flyff::InventoryItem> find_first_equippable_item(const flyff::ItemKind3 &item_kind) {
const auto &neuz = flyff::Neuz::instance();
const auto &player = neuz.player;
@ -241,7 +247,7 @@ flyff::Pointer<flyff::InventoryItem> find_first_equippable_item(const flyff::Ite
}
}
return flyff::Pointer<flyff::InventoryItem>(highest);
return flyff::Pointer<const flyff::InventoryItem>(highest);
}
@ -374,26 +380,28 @@ void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent *event, void *u
} else {
if (!neuz.player) return;
neuz.show_announcement("Hello world!", {0xFF, 0, 0});
std::cout << "My job is " << neuz.player->get_job() << std::endl;
auto current = neuz.movers.first;
do {
const auto &mover = current->mover;
// neuz.show_announcement("Hello world!", {0xFF, 0, 0});
if (mover->type == flyff::ObjectType::Mover) {
// int level = mover->get_level();
std::cout << neuz.get_text(mover->name) << " <Lv. " << mover->get_level() << ">): "
<< (mover->is_dead() ? "Dead" : "Not dead") << ", "
<< (mover->is_fly() ? "Flying" : "Not flying") << ", "
<< (mover->is_jumping() ? "Jumping" : "Not jumping") << ", "
<< (mover->is_moving() ? "Moving" : "Not moving")
<< (mover->is_grounded ? "On ground" : "Flying")
<< std::endl;
}
current = current->next;
} while (current);
// auto current = neuz.movers.first;
// do {
// const auto &mover = current->mover;
//
// if (mover->type == flyff::ObjectType::Mover) {
// // int level = mover->get_level();
//
// std::cout << neuz.get_text(mover->name) << " <Lv. " << mover->get_level() << ">): "
// << (mover->is_dead() ? "Dead" : "Not dead") << ", "
// << (mover->is_fly() ? "Flying" : "Not flying") << ", "
// << (mover->is_jumping() ? "Jumping" : "Not jumping") << ", "
// << (mover->is_moving() ? "Moving" : "Not moving") << ", "
// << (mover->is_grounded ? "On ground" : "Flying") << ", "
// << std::endl;
// }
//
// current = current->next;
// } while (current);
// auto items = player.inventory.begin();
// auto length = ((uintptr_t)player.inventory.end() - (uintptr_t)player.inventory.begin()) / 0x60;
@ -492,8 +500,8 @@ flyff::MoverID find_next_item() {
mover->type == flyff::ObjectType::Item &&
d <= lowest_distance) {
auto *prop = reinterpret_cast<flyff::ItemProperty *>(
static_cast<flyff::ObjectProperty *>(mover->property)
auto *prop = reinterpret_cast<const flyff::ItemProperty *>(
static_cast<const flyff::ObjectProperty *>(mover->property)
);
if (!prop->is_quest()) {
@ -589,58 +597,61 @@ void bot_tick() {
// Check buffs.
static constexpr flyff::Skill buffs_to_check[] = {
flyff::Skill::HeapUp,
flyff::Skill::Haste,
flyff::Skill::Patience
static constexpr flyff::SkillID buffs_to_check[] = {
flyff::SkillID::HeapUp,
flyff::SkillID::Haste,
flyff::SkillID::Patience,
flyff::SkillID::BeefUp,
};
auto item = neuz.get_mover(current_pickup_item);
auto monster = neuz.get_mover(current_target);
const auto &main_hand = player->get_equipped_item(flyff::Part::MainHand);
const auto &off_hand = player->get_equipped_item(flyff::Part::Shield);
if (neuz.player->get_job() == flyff::JobID::Assist) {
const auto &main_hand = player->get_equipped_item(flyff::Part::MainHand);
const auto &off_hand = player->get_equipped_item(flyff::Part::Shield);
auto buffs = check_rebuff(neuz.player, buffs_to_check);
if (!buffs.empty() && (!item || item->is_despawned) && (!monster || monster->is_dead())) {
const auto next_buff = buffs.back();
if (!main_hand || main_hand->item_kind3 != flyff::ItemKind3::CheerStick) {
const auto &stick = find_first_equippable_item(flyff::ItemKind3::CheerStick);
auto buffs = check_rebuff(neuz.player, buffs_to_check);
if (!buffs.empty() && (!item || item->is_despawned) && (!monster || monster->is_dead())) {
const auto skill_index = buffs.back();
if (!main_hand || main_hand->item_kind3 != flyff::ItemKind3::CheerStick) {
const auto &stick = find_first_equippable_item(flyff::ItemKind3::CheerStick);
if (stick) {
if (stick) {
buffs.pop_back();
use_item_in_inventory(stick->index);
use_skill(skill_index);
return;
} else {
neuz.show_message("Unable to find a stick", {0xFF, 0, 0});
}
} else {
buffs.pop_back();
use_item_in_inventory(stick->index);
use_skill(next_buff);
use_skill(skill_index);
return;
} else {
neuz.show_message("Unable to find a stick", {0xFF, 0, 0});
}
} else {
buffs.pop_back();
use_skill(next_buff);
return;
}
}
if (buffs.empty()) {
if (!main_hand || main_hand->item_kind3 != flyff::ItemKind3::KnuckleHammer) {
const auto &knuckle = find_first_equippable_item(flyff::ItemKind3::KnuckleHammer);
if (knuckle) {
use_item_in_inventory(knuckle->index);
} else {
neuz.show_message("Unable to find a knuckle", {0xFF, 0, 0});
}
}
if (!off_hand || off_hand->item_kind3 != flyff::ItemKind3::Shield) {
const auto &shield = find_first_equippable_item(flyff::ItemKind3::Shield);
if (buffs.empty()) {
if (!main_hand || main_hand->item_kind3 != flyff::ItemKind3::KnuckleHammer) {
const auto &knuckle = find_first_equippable_item(flyff::ItemKind3::KnuckleHammer);
if (shield) {
use_item_in_inventory(shield->index);
} else {
neuz.show_message("Unable to find a shield", {0xFF, 0, 0});
if (knuckle) {
use_item_in_inventory(knuckle->index);
} else {
neuz.show_message("Unable to find a knuckle", {0xFF, 0, 0});
}
}
if (!off_hand || off_hand->item_kind3 != flyff::ItemKind3::Shield) {
const auto &shield = find_first_equippable_item(flyff::ItemKind3::Shield);
if (shield) {
use_item_in_inventory(shield->index);
} else {
neuz.show_message("Unable to find a shield", {0xFF, 0, 0});
}
}
}
}
@ -689,8 +700,8 @@ void bot_tick() {
current_pickup_item = find_next_item();
item = neuz.get_mover(current_pickup_item);
if (item) {
flyff::ItemProperty *prop = reinterpret_cast<flyff::ItemProperty *>(
static_cast<flyff::ObjectProperty *>(item->property)
auto *prop = reinterpret_cast<const flyff::ItemProperty *>(
static_cast<const flyff::ObjectProperty *>(item->property)
);
std::string str = "Picking up ";

View File

@ -1,10 +1,11 @@
#include <fugg.h>
namespace fugg {
// class Client {
// Client();
class Client {
Client();
// public:
public:
// };
};
}

View File

@ -11,59 +11,58 @@
#define TRACE_ALLOC 0
void *malloc (size_t __size) {
// void * operator new(std::size_t __size) {
void *malloc(size_t size) {
// void * operator new(std::size_t size) {
// This malloc is always called from the runtime.
if((*flyff::malloc) != nullptr) {
if ((*flyff::malloc) != nullptr) {
// Since this malloc is always called from the interop, we need to
// transform it to point to the actual address where the WASM runtime memory
// resides.
const auto& ptr = fugg::ModulePointer<void> {
(*flyff::malloc)(__size)
const auto &ptr = fugg::ModulePointer<void>{
(*flyff::malloc)(size)
};
#if TRACE_ALLOC
std::cout << "FLYFF: Allocated INSIDE " << __size << " bytes at " << reinterpret_cast<void*>(ptr.as_raw()) << std::endl;
std::cout << "FLYFF: Allocated INSIDE " << size << " bytes at " << reinterpret_cast<void*>(ptr.as_raw()) << std::endl;
#endif
return ptr;
} else {
auto ptr = emscripten_builtin_malloc(__size);
auto ptr = emscripten_builtin_malloc(size);
#if TRACE_ALLOC
std::cout << "FUGG: Allocated OUTSIDE " << __size << " bytes at " << reinterpret_cast<void*>(ptr) << std::endl;
std::cout << "FUGG: Allocated OUTSIDE " << size << " bytes at " << reinterpret_cast<void*>(ptr) << std::endl;
#endif
return ptr;
}
}
void free (void *__ptr) {
// void operator delete(void * __ptr) {
// printf("Trying to free ptr %p\n", __ptr);
if((*flyff::free) != nullptr) {
const auto& ptr = fugg::RuntimePointer<void> { __ptr };
void free(void *ptr_) {
if ((*flyff::free) != nullptr) {
const auto &ptr = fugg::RuntimePointer<void>{ptr_};
(*flyff::free)(ptr.as_raw());
#if TRACE_ALLOC
std::cout << "FLYFF: Free'd INSIDE pointer at " << reinterpret_cast<void*>(ptr.as_raw()) << std::endl;
std::cout << "FLYFF: Free'd INSIDE pointer at " << reinterpret_cast<void*>(ptr.as_raw()) << std::endl;
#endif
} else {
emscripten_builtin_free(__ptr);
emscripten_builtin_free(ptr_);
#if TRACE_ALLOC
std::cout << "FUGG: Free'd OUTSIDE pointer at " << reinterpret_cast<void*>(__ptr) << std::endl;
std::cout << "FUGG: Free'd OUTSIDE pointer at " << reinterpret_cast<void*>(ptr) << std::endl;
#endif
}
}
void get_text(std::string text) {
const auto& neuz = flyff::Neuz::instance();
void get_text(const std::string& text) {
const auto &neuz = flyff::Neuz::instance();
const auto& result = neuz.get_text(text);
const auto &result = neuz.get_text(text);
std::cout << text << " = \"" << result << "\"" << std::endl;
}
@ -77,8 +76,8 @@ int main() {
std::cout << "Hello world from fugg!" << std::endl;
std::cout << "Initialising runtime... ";
auto& neuz = Neuz::instance();
auto &neuz = Neuz::instance();
std::cout << "Ok!" << std::endl;