Mad progress

Figured out how to send packets
This commit is contained in:
Knaapchen 2022-10-09 03:46:56 +02:00
parent 144838d708
commit a5416d098c
20 changed files with 590 additions and 173 deletions

View File

@ -1,6 +1,8 @@
add_library (
flyff-api
"src/flyff.cpp"
"src/Neuz.cpp"
"src/import.cpp"
"include/flyff.h"
)

View File

@ -1,15 +1,19 @@
#pragma once
#include <fugg.h>
#include <string>
#include "../src/Neuz.h"
#include "../src/Mover.h"
#include "../src/import.h"
#include "../src/raw/Mover.h"
namespace flyff {
#include "../src/raw/ItemProperty.h"
#include "../src/raw/MusicProperty.h"
#include "../src/raw/Mover.h"
// #include "../src/raw/ItemProperty.h"
// #include "../src/raw/MusicProperty.h"
// #include "../src/raw/Mover.h"
namespace api {
// static_assert(sizeof(fugg::ModulePointer<void>) == sizeof(u32), "ModulePointer needs the same size as u32");
@ -21,6 +25,14 @@ namespace flyff {
extern void w2c_f167(u32, u32);
extern u32 w2c_f208(u64);
extern void w2c_f337(u32, u32, u32);
// f271_called_on_attack
extern u32 w2c_f271(u32 w2c_p0, u32 w2c_p1, u64 w2c_p2, u64 w2c_p3, u64 w2c_p4, u64 w2c_p5);
// f2300_finalize_packet: Encrypts and constructs a packet for wire.
extern void w2c_f2300(u32);
// f2296_websocket_send: Sends a packet over the WebSocket connection.
extern void w2c_f2296(u32, u32);
};
}

30
flyff-api/src/Mover.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include <fugg.h>
#include <cstddef>
#include "core.h"
#include "math.h"
namespace flyff {
struct __attribute__((packed)) Mover {
union {
DEFINE_MEMBER(0x18, flyff::Matrix4, world_matrix);
DEFINE_MEMBER(0x98, flyff::Vector3, position);
DEFINE_MEMBER(2020, const flyff::String, name);
DEFINE_MEMBER(1744, flyff::MoverID, selected_target);
DEFINE_MEMBER(1752, flyff::MoverID, attack_target);
DEFINE_MEMBER(1760, flyff::MoverID, follow_target);
DEFINE_MEMBER(1768, flyff::MoverID, current_attack_target);
DEFINE_MEMBER(1776, flyff::MoverID, platform_standing_on);
DEFINE_MEMBER(1792, int, current_animation);
const MinimumSize<4096> __size;
};
};
};

45
flyff-api/src/Neuz.cpp Normal file
View File

@ -0,0 +1,45 @@
#include "Neuz.h"
#include <client.h>
// static_assert(sizeof(TestMover) == 4096, "Mover needs to be 4096 bytes");
// static_assert(offsetof(TestMover, name) == 0x7f4, "Mover.name needs to be at 2020");
namespace flyff {
// Emscripten runtime:
// 1. Pre-run
// 2. Init runtime
// 3. Pre-main
// 4. Call main
// 5. Post-run
Neuz::Neuz() {
// 1. Pre-run: There are no pre-runs in this binary.
// 2. Init runtime: `___wasm_call_ctors` is added to on init runtime.
(*flyff::raw::_wasm_call_ctors)();
}
Neuz& Neuz::instance() {
static bool initialised = false;
if (!initialised) {
// Initialise the WebAssembly runtime.
wasm_rt_init();
// Initialise the client.
flyff::raw::init();
// Only init the module once.
initialised = true;
}
// Constructor will be called.
static Neuz instance;
// Whole module is initialised now.
return instance;
}
int Neuz::main() const {
// 3. Pre-main: There are no pre-mains in this binary.
// 4. Call main: `_main` is main in the binary.
// TODO: Fix arguments.
return (*flyff::raw::main)(0, 0);
}
} // namespace flyff

35
flyff-api/src/Neuz.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
#include <cstdint>
#include <client.h>
namespace flyff {
namespace raw {
static const auto& init = &Z_client_init;
static const auto& _wasm_call_ctors = &Z_clientZ____wasm_call_ctors;
static const auto& main = &Z_clientZ__main;
static const auto& malloc = &Z_clientZ__malloc;
static const auto& free = &Z_clientZ__free;
}
// static_assert(sizeof(Pointer<void>) == sizeof(u32), "Pointers needs to be the size of u32");
class Neuz {
Neuz();
public:
static Neuz& instance();
Neuz(Neuz const&) = delete;
void operator=(Neuz const&) = delete;
// Execute the `main` function of the flyff-client.
int main() const;
// Easy to implement: Just send a EmscriptenKeyboardEvent* to the registered function.
// void send_keydown();
// void send_keyup();
// void send_keypress();
};
}

View File

@ -0,0 +1,13 @@
#pragma once
enum class ObjectType : int {
Object = 0 /* Background object */,
Animation = 1 /* Animation object */,
Ctrl = 2 /* Special background object */,
Sfx = 3 /* Special effect object */,
Item = 4 /* Item */,
Mover = 5 /* Moving object */,
Region = 6 /* Region (event, attribute) */,
Ship = 7,
Path = 8
};

105
flyff-api/src/core.h Normal file
View File

@ -0,0 +1,105 @@
#pragma once
#include <cstddef>
#include <string>
#include <iostream>
template <const size_t kSize>
class MinimumSize {
unsigned char __padding[kSize];
};
#define STR_MERGE_IMPL(a, b) a##b
#define STR_MERGE(a, b) STR_MERGE_IMPL(a, b)
#define MAKE_PAD(size) STR_MERGE(_pad, __COUNTER__)[size]
#define DEFINE_MEMBER(offset, type, name) struct {unsigned char MAKE_PAD(offset); type name;}
namespace flyff {
namespace detail {
template<typename I, typename O>
struct ArrowProxy {
I value;
O* operator->() {
return reinterpret_cast<O*>(&value);
}
O& operator*() {
return *(operator->)();
}
};
}
class Memory {
wasm_rt_memory_t** memory;
public:
explicit Memory(wasm_rt_memory_t** mem) : memory(mem) {}
const uintptr_t to_outside(const uintptr_t& offset) const {
return reinterpret_cast<uintptr_t>(&(*memory)->data[offset]);
}
template<typename T>
T* to_outside(T* offset) const {
return reinterpret_cast<T*>(
to_outside(
reinterpret_cast<uintptr_t>(offset)
)
);
}
};
static auto kMemory = Memory(&Z_clientZ_memory);
class Table {};
static const auto& kTable = &Z_clientZ_table;
template <typename T>
class Pointer {
uintptr_t offset;
public:
T* operator->() { return reinterpret_cast<T*>(kMemory.to_outside(offset)); }
};
class String {
union {
DEFINE_MEMBER(0x0, char*, text);
DEFINE_MEMBER(0x4, size_t, length);
DEFINE_MEMBER(0x8, void*, capacity);
DEFINE_MEMBER(0x0, char, data[1]);
DEFINE_MEMBER(0xb, char, short_length);
const MinimumSize<12> __size;
};
public:
// This has to be const until strings can allocate...
operator const std::string() const {
auto copy = *this;
auto is_short = -1 < copy.short_length;
if (!is_short) {
copy.text = kMemory.to_outside(text);
// TODO: Probably offset capacity too.
}
std::cout << "RIGHT BEFORE COPY!" << std::endl;
return *reinterpret_cast<std::string*>(&copy);
}
friend std::ostream& operator<<(std::ostream& os, const String& str) {
const std::string conv = str;
os << conv;
return os;
}
};
typedef unsigned long long MoverID;
static_assert(sizeof(String) == sizeof(std::string),
"String needs to be the same size as std::string");
}; // namespace flyff

15
flyff-api/src/import.cpp Normal file
View File

@ -0,0 +1,15 @@
#include <wasm-rt.h>
#include <client.h>
namespace flyff {
namespace raw {
static const auto& init = &Z_client_init;
static const auto& _wasm_call_ctors = &Z_clientZ____wasm_call_ctors;
static const auto& main = &Z_clientZ__main;
static const auto& malloc = &Z_clientZ__malloc;
static const auto& free = &Z_clientZ__free;
}
}

21
flyff-api/src/math.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
namespace flyff {
struct Vector4 {
float x, y, z, w;
};
struct Vector3 {
float x, y, z;
};
struct Matrix4 {
Vector4 a, b, c, d;
};
struct Color {
unsigned char r;
unsigned char g;
unsigned char b;
};
}

View File

@ -30,13 +30,11 @@ typedef struct SomethingWithJob SomethingWithJob, *PSomethingWithJob;
typedef uint uint32_t;
typedef uint32_t wasm_rt_funcref_t;
#include "ObjectType.h"
#include "../ObjectType.h"
#include "../Job.h"
typedef struct astruct_30 astruct_30, *Pastruct_30;
#include "Job.h"
struct Vector4 {
float x;
@ -3318,7 +3316,7 @@ struct __attribute__ ((packed)) Mover {
};
struct astruct_30 {
wasm_rt_funcref_t * vtable;
uint32_t * vtable;
};
struct SomethingWithJob {
@ -3331,7 +3329,7 @@ struct SomethingWithJob {
undefined field6_0x9;
undefined field7_0xa;
undefined field8_0xb;
enum Job job;
Job job;
undefined field10_0x10;
undefined field11_0x11;
undefined field12_0x12;
@ -31554,7 +31552,7 @@ struct CCtrl {
undefined field183_0xc9;
undefined field184_0xca;
undefined field185_0xcb;
enum ObjectType maybe_dynamic_object_type;
ObjectType maybe_dynamic_object_type;
undefined field187_0xd0;
undefined field188_0xd1;
undefined field189_0xd2;
@ -34493,40 +34491,40 @@ struct CCtrl {
};
struct Mover_Vtable {
wasm_rt_funcref_t field0_0x0;
wasm_rt_funcref_t field1_0x4;
wasm_rt_funcref_t field2_0x8;
wasm_rt_funcref_t field3_0xc;
wasm_rt_funcref_t field4_0x10;
wasm_rt_funcref_t field5_0x14;
wasm_rt_funcref_t field6_0x18;
wasm_rt_funcref_t field7_0x1c;
wasm_rt_funcref_t field8_0x20;
wasm_rt_funcref_t field9_0x24;
wasm_rt_funcref_t field10_0x28;
wasm_rt_funcref_t field11_0x2c;
wasm_rt_funcref_t field12_0x30;
wasm_rt_funcref_t field13_0x34;
wasm_rt_funcref_t field14_0x38;
wasm_rt_funcref_t field15_0x3c;
wasm_rt_funcref_t field16_0x40;
wasm_rt_funcref_t field17_0x44;
wasm_rt_funcref_t field18_0x48;
wasm_rt_funcref_t field19_0x4c;
wasm_rt_funcref_t field20_0x50;
wasm_rt_funcref_t field21_0x54;
wasm_rt_funcref_t field22_0x58;
wasm_rt_funcref_t field23_0x5c;
wasm_rt_funcref_t field24_0x60;
wasm_rt_funcref_t field25_0x64;
wasm_rt_funcref_t field26_0x68;
wasm_rt_funcref_t field27_0x6c;
wasm_rt_funcref_t field28_0x70;
wasm_rt_funcref_t field29_0x74;
wasm_rt_funcref_t field30_0x78;
wasm_rt_funcref_t field31_0x7c;
wasm_rt_funcref_t field32_0x80;
wasm_rt_funcref_t field33_0x84;
wasm_rt_funcref_t field34_0x88;
uint32_t field0_0x0;
uint32_t field1_0x4;
uint32_t field2_0x8;
uint32_t field3_0xc;
uint32_t field4_0x10;
uint32_t field5_0x14;
uint32_t field6_0x18;
uint32_t field7_0x1c;
uint32_t field8_0x20;
uint32_t field9_0x24;
uint32_t field10_0x28;
uint32_t field11_0x2c;
uint32_t field12_0x30;
uint32_t field13_0x34;
uint32_t field14_0x38;
uint32_t field15_0x3c;
uint32_t field16_0x40;
uint32_t field17_0x44;
uint32_t field18_0x48;
uint32_t field19_0x4c;
uint32_t field20_0x50;
uint32_t field21_0x54;
uint32_t field22_0x58;
uint32_t field23_0x5c;
uint32_t field24_0x60;
uint32_t field25_0x64;
uint32_t field26_0x68;
uint32_t field27_0x6c;
uint32_t field28_0x70;
uint32_t field29_0x74;
uint32_t field30_0x78;
uint32_t field31_0x7c;
uint32_t field32_0x80;
uint32_t field33_0x84;
uint32_t field34_0x88;
};

View File

@ -1,13 +0,0 @@
#pragma once
enum class ObjectType : int {
Object = 0 /* Background object */,
Animation = 1 /* Animation object */,
Ctrl = 2 /* Special background object */,
Sfx = 3 /* Special effect object */,
Item = 4 /* Item */,
Mover = 5 /* Moving object */,
Region = 6 /* Region (event, attribute) */,
Ship = 7,
Path = 8
};

View File

@ -512,7 +512,7 @@ static u32 w2c__malloc(u32);
static u32 w2c_f268(u32);
static u32 w2c_f269(u32);
static void w2c_f270(u32, u32);
static u32 w2c_f271(u32, u32, u64, u64, u64, u64);
u32 w2c_f271(u32, u32, u64, u64, u64, u64);
static u32 w2c_f272(u32);
static void w2c_f273(u32, u32);
static void w2c_f274(u32);
@ -578,7 +578,7 @@ static void w2c_f333(void);
static void w2c_f334(u32, u32, f32, u32);
static u32 w2c_f335(u32);
static void w2c_f336(u32, u32);
static void w2c_f337(u32, u32, u32);
void w2c_f337(u32, u32, u32);
static u32 w2c_f338(u32, u32);
static void w2c_f339(u32);
static void w2c_f340(u32, u32, u32, u32);
@ -2537,11 +2537,11 @@ static void w2c_f2292(u32, u32);
static u32 w2c_f2293(u32);
static void w2c_f2294(u32);
static u32 w2c_f2295(u32);
static void w2c_f2296(u32, u32);
void w2c_f2296(u32, u32);
static void w2c_f2297(u32);
static void w2c_f2298(u32, u32);
static void w2c_f2299(u32);
static void w2c_f2300(u32);
void w2c_f2300(u32);
static void w2c_f2301(u32);
static void w2c_f2302(u32);
static void w2c_f2303(u32);
@ -44146,7 +44146,11 @@ static void w2c_f270(u32 w2c_p0, u32 w2c_p1) {
FUNC_EPILOGUE;
}
static u32 w2c_f271(u32 w2c_p0, u32 w2c_p1, u64 w2c_p2, u64 w2c_p3, u64 w2c_p4, u64 w2c_p5) {
u32 w2c_f271(u32 w2c_p0, u32 w2c_p1, u64 w2c_p2, u64 w2c_p3, u64 w2c_p4, u64 w2c_p5) {
// printf("called_on_attack(): p0=%u, p1=%u, p2=%llu, p3=%llu, p4=%llu, p5=%llu\n",
// w2c_p0, w2c_p1, w2c_p2, w2c_p3, w2c_p4, w2c_p5
// );
u32 w2c_l6 = 0, w2c_l7 = 0, w2c_l8 = 0, w2c_l9 = 0, w2c_l10 = 0, w2c_l11 = 0, w2c_l12 = 0, w2c_l13 = 0,
w2c_l14 = 0, w2c_l15 = 0, w2c_l16 = 0, w2c_l17 = 0, w2c_l18 = 0, w2c_l19 = 0, w2c_l20 = 0;
u64 w2c_l24 = 0;
@ -71282,7 +71286,7 @@ static void w2c_f336(u32 w2c_p0, u32 w2c_p1) {
FUNC_EPILOGUE;
}
static void w2c_f337(u32 w2c_p0, u32 w2c_p1, u32 w2c_p2) {
void w2c_f337(u32 w2c_p0, u32 w2c_p1, u32 w2c_p2) {
u32 w2c_l3 = 0, w2c_l4 = 0, w2c_l5 = 0, w2c_l6 = 0, w2c_l7 = 0, w2c_l8 = 0, w2c_l9 = 0, w2c_l10 = 0,
w2c_l11 = 0;
FUNC_PROLOGUE;
@ -116326,9 +116330,8 @@ static void w2c_f424(u32 w2c_p0) {
w2c_i1 = 4294967232u;
w2c_i0 -= w2c_i1;
w2c_i1 = 17381u;
w2c_i0 = w2c_f204(w2c_i0, w2c_i1);
printf("This gets printed when you have no target.\n");
w2c_i0 = w2c_f204(w2c_i0, w2c_i1);
w2c_p0 = w2c_i0;
w2c_i0 = w2c_l5;
@ -1035771,6 +1035774,15 @@ static void w2c_f2291(u32 w2c_p0) {
}
static void w2c_f2292(u32 w2c_p0, u32 w2c_p1) {
// u32 length = w2c_p1;
// u32 buffer = w2c_p0;
// printf("Server sent message of length %u: ", length);
// for(u32 i = 0; i < length; i++) {
// printf("%02x ", (&w2c_memory)->data[buffer + i]);
// }
// printf("\n");
u32 w2c_l2 = 0, w2c_l3 = 0, w2c_l4 = 0, w2c_l5 = 0, w2c_l6 = 0, w2c_l7 = 0;
u64 w2c_l9 = 0;
f64 w2c_l8 = 0;
@ -1036664,12 +1036676,12 @@ static u32 w2c_f2295(u32 w2c_p0) {
return w2c_i0;
}
static void w2c_f2296(u32 w2c_p0, u32 w2c_p1) {
void w2c_f2296(u32 w2c_p0, u32 w2c_p1) {
const wasm_rt_memory_t* memory = &w2c_memory;
const unsigned char* data = &memory->data[w2c_p0];
const size_t length = w2c_p1;
puts("Sending network packet:");
printf("Sending network packet of length %zd (expecting finalized %zd): ", length, length - 9);
for(int i = 0; i < length; i++) {
printf("%02X ", data[i]);
}
@ -1036901,17 +1036913,31 @@ static void w2c_f2299(u32 w2c_p0) {
FUNC_EPILOGUE;
}
static void w2c_f2300(u32 w2c_p0) {
void w2c_f2300(u32 w2c_p0) {
u32 w2c_l1 = 0, w2c_l2 = 0, w2c_l3 = 0, w2c_l4 = 0, w2c_l5 = 0, w2c_l6 = 0, w2c_l7 = 0, w2c_l8 = 0;
FUNC_PROLOGUE;
u32 w2c_i0, w2c_i1, w2c_i2, w2c_i3;
u64 w2c_j1;
w2c_i0 = w2c_p0;
w2c_i0 = i32_load((&w2c_memory), (u64)(w2c_i0) + 4u);
w2c_i0 = i32_load((&w2c_memory), (u64)(w2c_i0) + 4u);
w2c_l4 = w2c_i0;
const uintptr_t end = w2c_l4;
w2c_i1 = w2c_p0;
w2c_i1 = i32_load((&w2c_memory), (u64)(w2c_i1));
w2c_l2 = w2c_i1;
const uintptr_t begin = w2c_l2;
const size_t length = end - begin;
const unsigned char* data = &(&w2c_memory)->data[begin];
printf("Finalizing packet of length %zd: ", length);
for(int i = 0; i < length; i++) {
printf("%02X ", data[i]);
}
printf("\n");
w2c_i0 -= w2c_i1;
w2c_l7 = w2c_i0;
w2c_i0 = 9u;

View File

@ -6,51 +6,9 @@
namespace fugg
{
// Emscripten runtime:
// 1. Pre-run
// 2. Init runtime
// 3. Pre-main
// 4. Call main
// 5. Post-run
using wasm::kMemory;
using wasm::kTable;
Client::Client() {
// 1. Pre-run: There are no pre-runs in this binary.
// 2. Init runtime: `___wasm_call_ctors` is added to on init runtime.
(*flyff::_wasm_call_ctors)();
}
Client& Client::instance() {
static bool initialised = false;
if(!initialised) {
// Initialise the WebAssembly runtime.
wasm_rt_init();
// Initialise the client.
flyff::init();
// Only init the module once.
initialised = true;
}
// Constructor will be called.
static Client instance;
// Whole module is initialised now.
return instance;
}
void Client::initialise() {
}
int Client::main() const {
// 3. Pre-main: There are no pre-mains in this binary.
// 4. Call main: `_main` is main in the binary.
// TODO: Fix arguments.
return (*flyff::main)(0, 0);
}
}
fugg::String translate(const std::string& id) {
const flyff::String get_text(const std::string& id) {
auto result = std::make_unique<fugg::detail::RawBasicString>();
auto id_ = std::make_unique<fugg::String>(id);
@ -59,7 +17,53 @@ fugg::String translate(const std::string& id) {
fugg::RuntimePointer<fugg::String>(id_.get()).as_raw()
);
return *reinterpret_cast<fugg::String*>(result.get());
return *reinterpret_cast<flyff::String*>(result.get());
}
void show_message(const std::string& message, const flyff::Color& color) {
// Copy the message into a new auto ptr
auto message_ = std::make_unique<fugg::String>(message);
auto color_ = std::make_unique<flyff::Color>(color);
const auto& kUnknownParam1 = fugg::module_ref<uintptr_t>(0x00034da8);
std::cout << "Got pointers: 1 = " << kUnknownParam1 << std::endl;
if(kUnknownParam1 == NULL) {
std::cout << "kUnknownParam1 == 0, returning..." << std::endl;
return;
}
flyff::api::w2c_f337(
0x00034da8,
fugg::RuntimePointer<fugg::String>(message_.get()).as_raw(),
fugg::RuntimePointer<flyff::Color>(color_.get()).as_raw()
);
}
void send_packet(std::vector<uint8_t> payload) {
struct Vector {
uintptr_t begin;
uintptr_t end;
uintptr_t capacity;
};
auto raw_payload = reinterpret_cast<const Vector*>(&payload);
// Copy the message into a new ptr
auto payload_ = std::unique_ptr<Vector>(new 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()
});
flyff::api::w2c_f2300(
fugg::RuntimePointer<Vector>(payload_.get()).as_raw()
);
flyff::api::w2c_f2296(
payload_->begin,
payload_->end - payload_->begin
);
}
#include <unordered_set>
@ -69,11 +73,130 @@ fugg::String translate(const std::string& id) {
#include <string>
#include <memory>
void before_main_loop() {
auto& client = fugg::Client::instance();
#include <emscripten/html5.h>
const auto& test = translate("ids_textclient_cannot_dropmoney");
std::cout << test->c_str() << std::endl;
#include <cstddef>
template<typename T>
void packet_push(std::vector<uint8_t>& packet, const T& value) {
union ToBytes {
T value;
uint8_t bytes[sizeof(T)];
};
ToBytes ref = { value };
packet.insert(packet.end(), std::begin(ref.bytes), std::end(ref.bytes));
}
void move_item_in_inventory(const uint32_t& from_slot, const uint32_t& to_slot) {
std::vector<uint8_t> packet;
// Not sure yet about these
packet.insert(packet.end(), { 0x01, 0x94 });
packet.insert(packet.end(), { 0x4a, 0x64 });
packet_push<uint32_t>(packet, from_slot);
packet_push<uint32_t>(packet, to_slot);
send_packet(packet);
}
void use_item_in_inventory(const uint32_t& slot) {
std::vector<uint8_t> packet;
// Not sure yet
packet.insert(packet.end(), { 0x10, 0xb0 });
// Same as move_item_in_inventory
packet.insert(packet.end(), { 0x4a, 0x64 });
packet_push<uint32_t>(packet, slot);
// Unknown yet
packet_push<uint32_t>(packet, 0);
send_packet(packet);
}
void move_to(const float& x, const float& y, const float& z) {
// Mouse click
// 04 B0 4A 64 FC D9 D4 45 AC 20 D4 42 C3 B9 52 45 00 07 65 30 00 00 68 F5 D4 45 00 00 00 00 8B A8 D1 42 00 00 00 00 FE 98 52 45 00 00 00 00
std::vector<uint8_t> packet;
packet.push_back(0x04);
packet.push_back(0xb0);
// Same as move_item_in_inventory
packet.insert(packet.end(), { 0x4a, 0x64 });
packet_push<float>(packet, x);
packet_push<float>(packet, y);
packet_push<float>(packet, z);
// ...
// send_packet(packet);
}
void write_chat_message(const std::string& message) {
// 00 94 4A 64 [0B 00 00 00] [48 65 6C 6C 6F 20 77 6F 72 6C 64] 00 00 00 00 00 00 00 00
std::vector<uint8_t> packet;
packet.push_back(0x00);
packet.push_back(0x94);
// Same as move_item_in_inventory
packet.insert(packet.end(), { 0x4a, 0x64 });
// Message length
packet_push<uint32_t>(packet, message.length());
// Write message
for(const auto& character : message) {
packet_push<uint8_t>(packet, character);
}
// Unknown 1
packet_push<uint32_t>(packet, 0);
// Unknown 2
packet_push<uint32_t>(packet, 0);
send_packet(packet);
}
void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent* event, void* user_data) {
// [
if(event->keyCode == 219) {
show_message("HAHAH DIKKE VETTE ANUSSEN", { 0xFF, 0, 0 });
// send_packet({
// 0x01, 0x94, 0x4a, 0x64,
// // From slot
// 0x05, 0x00, 0x00, 0x00,
// // To slot
// 0x00, 0x00, 0x00, 0x00
// });
// move_item_in_inventory(0, 50);
use_item_in_inventory(0);
write_chat_message("Hahaha dikke vette moeders");
}
}
void before_main_loop() {
// auto& client = fugg::Client::instance();
// const auto& test = translate("ids_textclient_cannot_dropmoney");
// const auto& test = translate("ids_textclient_skill_self");
// const auto& test = get_text("ids_textclient_notarget");
// const auto& test = get_text("ids_textclient_checkequip");
// const auto& test = get_text("ids_textclient_reapskill");
// const auto& test = get_text("ids_textclient_skillpoint_up");
// const auto& test = get_text("ids_textclient_skill_mate");
// const auto& test = get_text("IDS_PROPMOVER_TXT_000002");
// {
// const auto& test = get_text("ids_textclient_app_party");
// std::cout << test << std::endl;
// }
// {
// const auto& test = get_text("ids_ui_party_permanent");
// std::cout << test << std::endl;
// }
// show_message("HAHAH DIKKE VETTE ANUSSEN");
}
void after_main_loop() {
@ -91,40 +214,47 @@ void after_main_loop() {
// if(player_pointer != 0) {
// auto& player = fugg::module_ref<flyff::Mover>(player_pointer);
// std::cout << "Player pos: "
// << player.world_position.x << ", "
// << player.world_position.y << ", "
// << player.world_position.z << std::endl;
// std::cout << "Player pos: "
// << player.position.x << ", "
// << player.position.y << ", "
// << player.position.z << std::endl;
// std::cout << "Current target: " << player.selected_target_id << std::endl;
// std::cout << "Current animation: " << player.current_animation << std::endl;
// std::cout << "Name: " << player.name->c_str() << std::endl;
// // std::cout << "Current target: " << player.selected_target << std::endl;
// std::cout << "Current animation: " << player.current_animation << std::endl;
// std::cout << "Name: " << player.name << std::endl;
// if(player.selected_target_id != 0) {
// struct ObjectHolder {
// uintptr_t next;
// unsigned int list_index;
// unsigned long long hash;
// uintptr_t mover;
// };
// const int bla = offsetof(Mover, name);
// const int test = offsetof(flyff::Mover, name);
// auto& selected_target_holder = fugg::module_ref<ObjectHolder>(
// w2c_f208(player.selected_target_id)
// );
// static_assert(bla == test, "OMG");
// auto& selected_target = fugg::module_ref<flyff::Mover>(
// selected_target_holder.mover
// );
// // static_assert(offsetof(Mover, name) == 2020, "ASD");
// std::cout << "(" << reinterpret_cast<void*>(selected_target_holder.mover) << ") Target: "
// << selected_target.name->c_str() << " at "
// << selected_target.world_position.x << ", "
// << selected_target.world_position.y << ", "
// << selected_target.world_position.z << std::endl;
// if(player.selected_target != 0) {
// struct ObjectHolder {
// uintptr_t next;
// unsigned int list_index;
// unsigned long long hash;
// uintptr_t mover;
// };
// } else {
// std::cout << "Got no target." << std::endl;
// }
// auto& selected_target_holder = fugg::module_ref<ObjectHolder>(
// flyff::api::w2c_f208(player.selected_target)
// );
// auto& selected_target = fugg::module_ref<Mover>(
// selected_target_holder.mover
// );
// std::cout << "(" << reinterpret_cast<void*>(selected_target_holder.mover) << ") Target: "
// << selected_target.name->c_str() << " at "
// << selected_target.world_position.x << ", "
// << selected_target.world_position.y << ", "
// << selected_target.world_position.z << std::endl;
// } else {
// std::cout << "Got no target." << std::endl;
// }
// }
// auto& item_properties = fugg::module_ref<fugg::Vector<flyff::ItemProperty>>(0x00035194);

View File

@ -1,23 +1,10 @@
#include <fugg.h>
namespace fugg {
class Client {
Client();
// class Client {
// Client();
public:
static Client& instance();
// public:
Client(Client const&) = delete;
void operator=(Client const&) = delete;
void initialise();
// Execute the `main` function of the flyff-client.
int main() const;
template<typename T>
T* allocate(size_t size);
template<typename T>
void deallocate(T* ptr);
};
// };
}

View File

@ -139,6 +139,9 @@ WASM_IMPORT_IMPL(env, _emscripten_set_focusout_callback_on_thread) = [](u32 a, u
emscripten_set_focusout_callback_on_thread(target, user_data, use_capture, hook, target_thread)
);
};
extern void on_keyup_hook(int, const EmscriptenKeyboardEvent*, void*);
u32 original_keyup_callback = 0;
/* import: 'a' 'Da' */
/* _emscripten_set_keyup_callback_on_thread */
@ -157,6 +160,9 @@ WASM_IMPORT_IMPL(env, _emscripten_set_keyup_callback_on_thread) = [](u32 a, u32
original_keyup_callback = callback_;
auto hook = [](int eventType, const EmscriptenKeyboardEvent* event, void* userData) {
// Call hook
on_keyup_hook(eventType, event, userData);
assert(original_keyup_callback);
const auto& callback = fugg::function_ref<em_key_callback_func>(original_keyup_callback);

View File

@ -365,7 +365,7 @@ WASM_IMPORT_IMPL(env, __embind_register_function) = [](u32 a, u32 arg_count, u32
#endif
// if(std::string(name) != "platform_text_edited") {
// emscripten::internal::_embind_register_function(name, arg_count, arg_types, signature, invoker, function);
// emscripten::internal::_embind_register_function(name, arg_count, arg_types, signature, invoker, function);
// } else {
std::cout << "Skipping registration of " << static_cast<const char*>(name)
<< " with " << arg_count << " arguments." << std::endl;

View File

@ -1,5 +1,6 @@
#include <wasm-rt.h>
#include <client.h>
#include <flyff.h>
#include <fugg.h>
#include <stdio.h>
@ -49,6 +50,7 @@ WASM_IMPORT_IMPL(env, _emscripten_cancel_main_loop) = []() {
/* import: 'a' 'ab' */
// "ab": "_emscripten_async_wget_data",
WASM_IMPORT_IMPL(env, _emscripten_async_wget_data) = [](u32 url_, u32 arg_, u32 onload_, u32 onerror_) {
auto& neuz = flyff::Neuz::instance();
// This function is only called by the flyff runtime, so we introduce
// stubs to refer the onload and onerror on to actual flyff functions.
// See `onload_stub` and `onerror_stub`.
@ -95,7 +97,7 @@ WASM_IMPORT_IMPL(env, _emscripten_async_wget_data) = [](u32 url_, u32 arg_, u32
delete interop_data;
};
const auto& url = fugg::ModulePointer<const char> { url_ };
const auto& url = fugg::module_ref<const char>(url_);
const auto data = new wget_data {
.onload = onload_,
@ -114,7 +116,7 @@ WASM_IMPORT_IMPL(env, _emscripten_async_wget_data) = [](u32 url_, u32 arg_, u32
// std::cout << "Client: Downloading " << static_cast<const char*>(url) << std::endl;
// This function can allocate, which will call the Flyff runtime allocate.
emscripten_async_wget_data(url, data, onload_stub, onerror_stub);
emscripten_async_wget_data(&url, data, onload_stub, onerror_stub);
};
/* import: 'a' 'fb' */
// "fb": "_emscripten_set_element_css_size",

View File

@ -84,7 +84,7 @@ void platform_websocket_close_hook(emscripten::val event) {
void platform_websocket_message_hook(emscripten::val event) {
// std::cout << "platform_websocket_message: Got " << event["data"]["byteLength"].as<unsigned long>() << " bytes" << std::endl;
struct Test {
emscripten::EM_VAL handle;
};

View File

@ -4,7 +4,9 @@
#include <fugg.h>
#include <flyff.h>
#include "client.h"
// #include "client.h"
#define TRACE_ALLOC 0
void *malloc (size_t __size) {
// void * operator new(std::size_t __size) {
@ -56,14 +58,15 @@ void free (void *__ptr) {
}
int main() {
using flyff::Neuz;
std::cout << "Hello world from fugg!" << std::endl;
std::cout << "Initialising runtime... ";
auto& client = fugg::Client::instance();
client.initialise();
auto& neuz = Neuz::instance();
std::cout << "Ok!" << std::endl;
std::cout << "Starting Flyff..." << std::endl;
return client.main();
return neuz.main();
}