1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-04-19 22:36:49 +00:00

Send the welcome server message in the onBeginLogin Lua function

I finally got a proof-of-concept working, and am somewhat happy with how I can
start building this API now.
This commit is contained in:
Joshua Goins 2025-03-27 22:54:36 -04:00
parent a99b0e7c17
commit 652beadaa4
8 changed files with 117 additions and 46 deletions

36
Cargo.lock generated
View file

@ -199,7 +199,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
"windows-sys",
"windows-sys 0.59.0",
]
[[package]]
@ -266,6 +266,7 @@ dependencies = [
"futures-task",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
@ -549,7 +550,7 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -560,6 +561,7 @@ checksum = "d3f763c1041eff92ffb5d7169968a327e1ed2ebfe425dac0ee5a35f29082534b"
dependencies = [
"bstr",
"either",
"futures-util",
"mlua-sys",
"num-traits",
"parking_lot",
@ -599,9 +601,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.21.1"
version = "1.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
checksum = "c2806eaa3524762875e21c3dcd057bc4b7bfa01ce4da8d46be1cd43649e1cc6b"
[[package]]
name = "parking_lot"
@ -635,7 +637,7 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "physis"
version = "0.4.0"
source = "git+https://github.com/redstrate/physis#020480e82c5537bdcd15ab3b9826f409d9e77e1a"
source = "git+https://github.com/redstrate/physis#eee7d5867fb7424592ff1249f28c90dbe1daec13"
dependencies = [
"binrw",
"bitflags 1.3.2",
@ -770,7 +772,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
"windows-sys 0.59.0",
]
[[package]]
@ -873,6 +875,15 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "1.14.0"
@ -886,7 +897,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
dependencies = [
"libc",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -940,7 +951,7 @@ dependencies = [
"pin-project-lite",
"socket2",
"tokio-macros",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -1065,6 +1076,15 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"

View file

@ -86,4 +86,4 @@ rusqlite = { version = "0.34", features = ["bundled"], default-features = false
bitflags = { version = "1.3", default-features = false }
# For server-side scripting
mlua = { version = "0.10", features = ["lua51", "vendored", "send"] }
mlua = { version = "0.10", features = ["lua51", "vendored", "send", "async"] }

View file

@ -11,6 +11,8 @@ fn main() {
let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
d.push("resources/opcodes.json");
println!("cargo::rerun-if-changed={}", d.to_str().unwrap());
let mut output_str = "use binrw::binrw;\n".to_string();
let opcodes_buffer = std::fs::read_to_string(d).unwrap();

View file

@ -52,7 +52,7 @@
},
{
"name": "ServerChatMessage",
"opcode": 406,
"opcode": 837,
"size": 776
},
{

View file

@ -1,3 +1,4 @@
function onBeginLogin(player)
print("Player " .. player.content_id .. " is connecting!")
-- send a welcome message
player:send_message("Welcome to Kawari!")
end

View file

@ -23,8 +23,8 @@ use kawari::world::{
SocialList,
},
};
use kawari::world::{PlayerData, WorldDatabase};
use mlua::{Function, Lua};
use kawari::world::{LuaPlayer, PlayerData, WorldDatabase};
use mlua::{AnyUserData, Function, Lua};
use physis::common::{Language, Platform};
use physis::gamedata::GameData;
use tokio::io::AsyncReadExt;
@ -47,12 +47,11 @@ async fn main() {
{
let lua = lua.lock().unwrap();
lua.load(
std::fs::read(format!("{}/test.lua", &config.world.scripts_location))
.expect("Failed to locate scripts directory!"),
)
.exec()
.unwrap();
let file_name = format!("{}/test.lua", &config.world.scripts_location);
lua.load(std::fs::read(&file_name).expect("Failed to locate scripts directory!"))
.set_name("@".to_string() + &file_name)
.exec()
.unwrap();
}
loop {
@ -79,6 +78,8 @@ async fn main() {
inventory: Inventory::new(),
};
let mut lua_player = LuaPlayer::default();
tokio::spawn(async move {
let mut buf = [0; 2056];
loop {
@ -98,6 +99,7 @@ async fn main() {
// collect actor data
connection.player_data =
database.find_player_data(actor_id.parse::<u32>().unwrap());
lua_player.player_data = connection.player_data;
// We have send THEM a keep alive
{
@ -309,37 +311,16 @@ async fn main() {
connection.change_zone(zone_id).await;
// send welcome message
{
let ipc = ServerZoneIpcSegment {
op_code: ServerZoneIpcType::ServerChatMessage,
timestamp: timestamp_secs(),
data: ServerZoneIpcData::ServerChatMessage {
message: "Welcome to Kawari!".to_string(),
unk: 0,
},
..Default::default()
};
connection
.send_segment(PacketSegment {
source_actor: connection.player_data.actor_id,
target_actor: connection.player_data.actor_id,
segment_type: SegmentType::Ipc { data: ipc },
})
.await;
}
let lua = lua.lock().unwrap();
lua.scope(|scope| {
let player_data = scope
.create_userdata_ref(&connection.player_data)
let connection_data = scope
.create_userdata_ref_mut(&mut lua_player)
.unwrap();
let func: Function =
lua.globals().get("onBeginLogin").unwrap();
func.call::<()>(player_data).unwrap();
func.call::<()>(connection_data).unwrap();
Ok(())
})
@ -976,6 +957,8 @@ async fn main() {
}
}
}
connection.process_lua_player(&mut lua_player).await;
}
}
});

View file

@ -1,4 +1,4 @@
use mlua::{UserData, UserDataFields};
use mlua::{UserData, UserDataFields, UserDataMethods};
use tokio::net::TcpStream;
use crate::{
@ -18,7 +18,7 @@ use super::{
},
};
#[derive(Debug, Default)]
#[derive(Debug, Default, Clone, Copy)]
pub struct PlayerData {
pub actor_id: u32,
pub content_id: u64,
@ -243,4 +243,69 @@ impl ZoneConnection {
.await;
}
}
pub async fn send_message(&mut self, message: &str) {
let ipc = ServerZoneIpcSegment {
op_code: ServerZoneIpcType::ServerChatMessage,
timestamp: timestamp_secs(),
data: ServerZoneIpcData::ServerChatMessage {
message: message.to_string(),
unk: 0,
},
..Default::default()
};
self.send_segment(PacketSegment {
source_actor: self.player_data.actor_id,
target_actor: self.player_data.actor_id,
segment_type: SegmentType::Ipc { data: ipc },
})
.await;
}
pub async fn process_lua_player(&mut self, player: &mut LuaPlayer) {
for segment in &player.queued_segments {
self.send_segment(segment.clone()).await;
}
player.queued_segments.clear();
}
}
#[derive(Default)]
pub struct LuaPlayer {
pub player_data: PlayerData,
queued_segments: Vec<PacketSegment<ServerZoneIpcSegment>>,
}
impl LuaPlayer {
fn queue_segment(&mut self, segment: PacketSegment<ServerZoneIpcSegment>) {
self.queued_segments.push(segment);
}
fn send_message(&mut self, message: &str) {
let ipc = ServerZoneIpcSegment {
op_code: ServerZoneIpcType::ServerChatMessage,
timestamp: timestamp_secs(),
data: ServerZoneIpcData::ServerChatMessage {
message: message.to_string(),
unk: 0,
},
..Default::default()
};
self.queue_segment(PacketSegment {
source_actor: self.player_data.actor_id,
target_actor: self.player_data.actor_id,
segment_type: SegmentType::Ipc { data: ipc },
});
}
}
impl UserData for LuaPlayer {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_method_mut("send_message", |_, this, message: String| {
this.send_message(&message);
Ok(())
});
}
}

View file

@ -7,7 +7,7 @@ mod chat_handler;
pub use chat_handler::ChatHandler;
mod connection;
pub use connection::{PlayerData, ZoneConnection};
pub use connection::{LuaPlayer, PlayerData, ZoneConnection};
mod database;
pub use database::{CharacterData, WorldDatabase};